Compare commits
3339 Commits
e5.5.0-alp
...
master
Author | SHA1 | Date |
---|---|---|
![]() |
bcd63344b8 | |
![]() |
cc3b26a3ac | |
![]() |
dd686c24a0 | |
![]() |
592c4e0045 | |
![]() |
073e3ea0a8 | |
![]() |
81978ceaeb | |
![]() |
6bfddd9952 | |
![]() |
cf608a73a5 | |
![]() |
a8200fb83d | |
![]() |
9ad65c6ac1 | |
![]() |
9ca3985bbd | |
![]() |
e17becb84d | |
![]() |
5dd8fefded | |
![]() |
7b85faf12a | |
![]() |
b0594271b2 | |
![]() |
d8aa39a310 | |
![]() |
fc0434afc8 | |
![]() |
5502af18b7 | |
![]() |
9f96e0957e | |
![]() |
109ffe7a70 | |
![]() |
1559aac486 | |
![]() |
68990f1538 | |
![]() |
5356d678cc | |
![]() |
11951f8f6c | |
![]() |
0aa4cdbaf3 | |
![]() |
281f8ddc83 | |
![]() |
b80513e941 | |
![]() |
822ed71282 | |
![]() |
b8fd5de2a5 | |
![]() |
3ee84d60ae | |
![]() |
3b52b658cd | |
![]() |
cba3dcbeda | |
![]() |
caf1897979 | |
![]() |
dbbd5e1458 | |
![]() |
0ab31df9d2 | |
![]() |
613fc644f5 | |
![]() |
b1a53568d6 | |
![]() |
d6651a1889 | |
![]() |
4cf7151139 | |
![]() |
4865999606 | |
![]() |
382feab7d1 | |
![]() |
6aad774075 | |
![]() |
649cbf1c79 | |
![]() |
4cde5e98a3 | |
![]() |
d631b5b296 | |
![]() |
26ec69d5f4 | |
![]() |
58b9ab0210 | |
![]() |
4644072fd8 | |
![]() |
bd87e3ce2b | |
![]() |
c9c4d1a196 | |
![]() |
11546b72f4 | |
![]() |
bcb70a9fb9 | |
![]() |
09ec31908b | |
![]() |
b94ec4014f | |
![]() |
74c346f9d1 | |
![]() |
8a33ef8576 | |
![]() |
6c2033ecbf | |
![]() |
51530588ef | |
![]() |
bba9d085d6 | |
![]() |
3162fe7a27 | |
![]() |
52b2d73b28 | |
![]() |
44e7f2e9b2 | |
![]() |
baf2b96cbc | |
![]() |
ba2d4f3df3 | |
![]() |
11aaa7b07d | |
![]() |
4250d01363 | |
![]() |
86853ac6ef | |
![]() |
810a4d3cf9 | |
![]() |
7b243ef7ad | |
![]() |
fcf76d28ba | |
![]() |
3b5d98c1d9 | |
![]() |
451b03ff99 | |
![]() |
f792418a68 | |
![]() |
4915cc0da6 | |
![]() |
15b3f4deb0 | |
![]() |
7a251c9ead | |
![]() |
37a89d0094 | |
![]() |
c313aa89f0 | |
![]() |
6db1c0a446 | |
![]() |
d4508a4f1d | |
![]() |
a6a9538e73 | |
![]() |
9f97bff7d0 | |
![]() |
577f1a7d8a | |
![]() |
e42021d314 | |
![]() |
08c58cc319 | |
![]() |
150fee87f1 | |
![]() |
6058b50c91 | |
![]() |
85cff5e7eb | |
![]() |
569f48f5a1 | |
![]() |
2cf86e76ee | |
![]() |
74cef7937d | |
![]() |
c658cfe269 | |
![]() |
a246551914 | |
![]() |
b1c8bc2421 | |
![]() |
200b5ab294 | |
![]() |
8d8ff6cf5d | |
![]() |
a23b8266b1 | |
![]() |
d69342a2fc | |
![]() |
e6bfc14cc9 | |
![]() |
3d1f0c756c | |
![]() |
83041a8b83 | |
![]() |
1c4402b12c | |
![]() |
ebb69f4ebf | |
![]() |
fd961f9da7 | |
![]() |
359bc38aa4 | |
![]() |
08f70e4a25 | |
![]() |
e408804efb | |
![]() |
e294d35703 | |
![]() |
303ff95e10 | |
![]() |
23f0e88b45 | |
![]() |
f0dd1bc4f4 | |
![]() |
9b30320ddb | |
![]() |
cae27293a5 | |
![]() |
81f4103d60 | |
![]() |
bab526be24 | |
![]() |
9307a82004 | |
![]() |
b8e8f7c8e0 | |
![]() |
a97a0d6400 | |
![]() |
8705956cdc | |
![]() |
f213569460 | |
![]() |
7e23f8d19f | |
![]() |
a676ede6b8 | |
![]() |
9e5e7a23c5 | |
![]() |
143086b0ef | |
![]() |
c569625dd1 | |
![]() |
7daab1ab23 | |
![]() |
077ee38530 | |
![]() |
b74189570d | |
![]() |
649cf88042 | |
![]() |
1496f7f778 | |
![]() |
91dd1183ad | |
![]() |
65ab81ff74 | |
![]() |
53d4cd3174 | |
![]() |
7d004b37da | |
![]() |
e5547005eb | |
![]() |
fada2a3fea | |
![]() |
b4a010d63b | |
![]() |
9bde981c44 | |
![]() |
7658e081c5 | |
![]() |
8dce530d15 | |
![]() |
a20d262327 | |
![]() |
d32f282feb | |
![]() |
1d728a05b2 | |
![]() |
49bff5c08a | |
![]() |
61eda0ff31 | |
![]() |
8f0d807c00 | |
![]() |
bceb5d43ed | |
![]() |
03fea34962 | |
![]() |
082514f557 | |
![]() |
c831f0772f | |
![]() |
ca455ad992 | |
![]() |
c347c2c285 | |
![]() |
a49cd78aae | |
![]() |
4065158be7 | |
![]() |
18721d05bc | |
![]() |
7f7d0741d2 | |
![]() |
2e39c4ad5e | |
![]() |
5b50d5433a | |
![]() |
eab440e0c1 | |
![]() |
e08425e67d | |
![]() |
f6f1d32da0 | |
![]() |
2924ec582a | |
![]() |
8dc1d1424a | |
![]() |
693d5dd394 | |
![]() |
f85db0a0e9 | |
![]() |
60aefd1065 | |
![]() |
c637422302 | |
![]() |
e80d43d14d | |
![]() |
b3074144cc | |
![]() |
6786c9b517 | |
![]() |
8913de10c0 | |
![]() |
5ddd7d7a6a | |
![]() |
d7cac74bed | |
![]() |
0b0a28ae44 | |
![]() |
c1e2801f41 | |
![]() |
8036baf22c | |
![]() |
268f887700 | |
![]() |
1d56ac6e5e | |
![]() |
4e0742c66f | |
![]() |
8c1302f455 | |
![]() |
b8a2a8ea18 | |
![]() |
b7c424a13d | |
![]() |
1b6494ab9a | |
![]() |
41bf5cd6ca | |
![]() |
548bcceab7 | |
![]() |
1beda1cd11 | |
![]() |
9da744c423 | |
![]() |
b2f2af6871 | |
![]() |
3fae704903 | |
![]() |
2d6b2bff8e | |
![]() |
dc342a35ac | |
![]() |
397c104a85 | |
![]() |
49b24a3049 | |
![]() |
7bf70aaab6 | |
![]() |
9a5d50f26a | |
![]() |
df1f4fad70 | |
![]() |
39b8cb1789 | |
![]() |
33eccb35da | |
![]() |
f6a0f56771 | |
![]() |
7631420eef | |
![]() |
8f94e9684c | |
![]() |
43f799508a | |
![]() |
03821c7b49 | |
![]() |
6da71200f3 | |
![]() |
6dbf015c93 | |
![]() |
30259284d1 | |
![]() |
87e4e2340d | |
![]() |
1925ed2f55 | |
![]() |
a45f817f0e | |
![]() |
57959ac7d4 | |
![]() |
79020b2436 | |
![]() |
141d8144e4 | |
![]() |
4f21594707 | |
![]() |
117c8197d7 | |
![]() |
b283a8c1ff | |
![]() |
c728b98e79 | |
![]() |
dda73651c5 | |
![]() |
c31e28153f | |
![]() |
7829838dc5 | |
![]() |
80e035f115 | |
![]() |
34f5a886ce | |
![]() |
79db2e6d7f | |
![]() |
3e4eeddb78 | |
![]() |
d2da311416 | |
![]() |
76e51fa532 | |
![]() |
82bb876de0 | |
![]() |
2d507146ab | |
![]() |
216a6abed9 | |
![]() |
ca2d4ad2a0 | |
![]() |
311419f621 | |
![]() |
9a950571d8 | |
![]() |
9e65e0d048 | |
![]() |
d1edf8aad2 | |
![]() |
b010efb647 | |
![]() |
606d829256 | |
![]() |
c7a7658c7a | |
![]() |
4d7535df2d | |
![]() |
8a344a8646 | |
![]() |
7374123c5c | |
![]() |
9c0f1df8a3 | |
![]() |
e7d07ea17c | |
![]() |
7bf270a242 | |
![]() |
878b218692 | |
![]() |
e74a921d33 | |
![]() |
2a58a36e37 | |
![]() |
2bb062d3a3 | |
![]() |
f29988ed8e | |
![]() |
e148d903e8 | |
![]() |
0a04b1ad6e | |
![]() |
cba3f532f8 | |
![]() |
7bb7b10a31 | |
![]() |
439abe430b | |
![]() |
eb71477f43 | |
![]() |
99e6613713 | |
![]() |
d9832252d8 | |
![]() |
6a5849488c | |
![]() |
07cb147d38 | |
![]() |
ba3cbe02e3 | |
![]() |
0b1f0db73c | |
![]() |
7ca5205f3f | |
![]() |
d1c218303d | |
![]() |
d7112921a6 | |
![]() |
69f5b6fa6c | |
![]() |
8ae54ac325 | |
![]() |
220fbe8a0a | |
![]() |
a2bed1efb8 | |
![]() |
57b67ebb37 | |
![]() |
862336a2cb | |
![]() |
ed2fab51e9 | |
![]() |
65544f34ec | |
![]() |
8d535bbd24 | |
![]() |
d7e72808a8 | |
![]() |
4d174b8678 | |
![]() |
b5231c29e3 | |
![]() |
eb2d3a3b7e | |
![]() |
ae828e8cfb | |
![]() |
464e202742 | |
![]() |
b7200656a5 | |
![]() |
fc3405fe4c | |
![]() |
f11dfce292 | |
![]() |
c61828460a | |
![]() |
4d25f28bb2 | |
![]() |
5c2a7dfdfa | |
![]() |
3ad7dc262b | |
![]() |
3c8ef35b18 | |
![]() |
01883e9759 | |
![]() |
ca47e4768d | |
![]() |
79b65a28c1 | |
![]() |
3a893626b8 | |
![]() |
2008130071 | |
![]() |
c6b02bc13f | |
![]() |
4a04ffdca1 | |
![]() |
c2d49ff34f | |
![]() |
ac52bf39ce | |
![]() |
0e545ffcec | |
![]() |
2e89656a90 | |
![]() |
466fa41ec3 | |
![]() |
93c725732c | |
![]() |
4edbcc55e7 | |
![]() |
cd8bf2725a | |
![]() |
0c05b3f019 | |
![]() |
78fe9304be | |
![]() |
14022aded1 | |
![]() |
02e1007a16 | |
![]() |
3381eecd6f | |
![]() |
3c832db13d | |
![]() |
937fb153c2 | |
![]() |
7b6b9580c8 | |
![]() |
2783192f77 | |
![]() |
083537daa3 | |
![]() |
ae3812da85 | |
![]() |
4c51cfdb68 | |
![]() |
6b130c6422 | |
![]() |
67880ab6a0 | |
![]() |
292b331064 | |
![]() |
52031441cf | |
![]() |
604cff4887 | |
![]() |
6697035812 | |
![]() |
1ad02a11e2 | |
![]() |
d04915d6a6 | |
![]() |
78bb102311 | |
![]() |
706cab3c86 | |
![]() |
4a08bfc93f | |
![]() |
0555a8ec61 | |
![]() |
02a0ccfdd1 | |
![]() |
9a003ee3cf | |
![]() |
bbd51bdf18 | |
![]() |
39c82fbe89 | |
![]() |
70786d6aca | |
![]() |
066fd0481b | |
![]() |
9e4a84cf76 | |
![]() |
269f6b29cc | |
![]() |
ec183f1d4c | |
![]() |
46c2c75b7b | |
![]() |
0e57b39cf2 | |
![]() |
2401a2fb80 | |
![]() |
96c9020727 | |
![]() |
af81800aec | |
![]() |
8e8b382ec0 | |
![]() |
70a760850f | |
![]() |
205ad507ea | |
![]() |
ffa69df6f8 | |
![]() |
e07d96e4d8 | |
![]() |
82e723bd18 | |
![]() |
9ca8aeb155 | |
![]() |
854754eb60 | |
![]() |
4e3095b1c4 | |
![]() |
83cc3ffeb0 | |
![]() |
1b7d23cef4 | |
![]() |
2816170e9d | |
![]() |
5f595966d8 | |
![]() |
5be654e31e | |
![]() |
04b547d6f5 | |
![]() |
21313c766d | |
![]() |
f3c6d10f76 | |
![]() |
01d89be743 | |
![]() |
44e4b3616d | |
![]() |
a4cc3ba9e8 | |
![]() |
bf2abba17a | |
![]() |
d9b5c5863b | |
![]() |
c9e12f30cd | |
![]() |
3004e32473 | |
![]() |
7664b06e98 | |
![]() |
02ce7e1b07 | |
![]() |
4825079964 | |
![]() |
b0e3e405cf | |
![]() |
44d533fe6d | |
![]() |
917df38a07 | |
![]() |
7a23ae7b4d | |
![]() |
ee13773496 | |
![]() |
48e604bda8 | |
![]() |
818070ad44 | |
![]() |
5279ad76be | |
![]() |
b91515b131 | |
![]() |
6d94809950 | |
![]() |
50e6ee4c88 | |
![]() |
3c370a90aa | |
![]() |
92dc059908 | |
![]() |
9f8a1885a7 | |
![]() |
d25c4ba06f | |
![]() |
3721be65ee | |
![]() |
d7732a6aac | |
![]() |
e70c1cfea3 | |
![]() |
dc4ae82798 | |
![]() |
d1b574a67e | |
![]() |
661f79544b | |
![]() |
23dafbb03b | |
![]() |
afeb2ab8aa | |
![]() |
b68ebb9a73 | |
![]() |
8c5e4a2376 | |
![]() |
086e7256f5 | |
![]() |
a4642d4d06 | |
![]() |
de48077ac4 | |
![]() |
210556e545 | |
![]() |
843973ef32 | |
![]() |
f84fb34692 | |
![]() |
eb80402ccb | |
![]() |
71dad0242e | |
![]() |
afe1c5617d | |
![]() |
0f2c19b656 | |
![]() |
b565976794 | |
![]() |
91fd01ed21 | |
![]() |
0d1eaba82e | |
![]() |
f00bb383d4 | |
![]() |
811184ddad | |
![]() |
893630aee3 | |
![]() |
d34fc7a03a | |
![]() |
166f5e5f12 | |
![]() |
fd18e5feb3 | |
![]() |
820789a09f | |
![]() |
457ea93570 | |
![]() |
f490a0cba2 | |
![]() |
298211d101 | |
![]() |
bdf3fc63a6 | |
![]() |
22fc3c49cc | |
![]() |
5b105fcdbb | |
![]() |
3ed4340145 | |
![]() |
2069910ad1 | |
![]() |
ae3b8fe146 | |
![]() |
f76444fbf8 | |
![]() |
5fca0a16f9 | |
![]() |
92594d042b | |
![]() |
e9163f2752 | |
![]() |
29d7a511f1 | |
![]() |
f9b6ae0c1a | |
![]() |
f1b4467fe1 | |
![]() |
70fab51354 | |
![]() |
c8258cebe8 | |
![]() |
36ee7bed77 | |
![]() |
e7351d949d | |
![]() |
e99fee68c0 | |
![]() |
7d851872ec | |
![]() |
9ffe6420c2 | |
![]() |
d94fcb9cfd | |
![]() |
ba3097dc56 | |
![]() |
f0a1d785ca | |
![]() |
8aab919f74 | |
![]() |
b4cffc581b | |
![]() |
aeacb3d58a | |
![]() |
c7f4e85760 | |
![]() |
f2f8c2ae92 | |
![]() |
3e69a52596 | |
![]() |
094259f444 | |
![]() |
755d6c9e0f | |
![]() |
9d0b5a9bc6 | |
![]() |
d3d3303dcb | |
![]() |
aa84ca5a88 | |
![]() |
c4dd167cb9 | |
![]() |
b333babb4c | |
![]() |
d84d31cbc5 | |
![]() |
16113001fe | |
![]() |
b994e0f1c0 | |
![]() |
420493deb4 | |
![]() |
d206d24975 | |
![]() |
f758fd9279 | |
![]() |
8c6cd69caa | |
![]() |
20be0df62d | |
![]() |
ac77b8a131 | |
![]() |
a912751458 | |
![]() |
913e0ce18b | |
![]() |
947cddb2eb | |
![]() |
5446bc305f | |
![]() |
eaaee725c2 | |
![]() |
e9265b88e5 | |
![]() |
7ee5b90084 | |
![]() |
32ace85e1c | |
![]() |
ae24b7a37b | |
![]() |
72579f9014 | |
![]() |
afb65817c4 | |
![]() |
187f5e5936 | |
![]() |
45dbfb77e3 | |
![]() |
d7d5eb2c52 | |
![]() |
532c7831b2 | |
![]() |
35f1ddc0eb | |
![]() |
9194756963 | |
![]() |
950f4d9483 | |
![]() |
947af1faaf | |
![]() |
c3579f338b | |
![]() |
e1420a27bb | |
![]() |
2c3209e258 | |
![]() |
17261c6499 | |
![]() |
7f17981a12 | |
![]() |
fe256363ad | |
![]() |
cfa29eaa6f | |
![]() |
5f321702e7 | |
![]() |
9f44c50025 | |
![]() |
cfa7c3bf04 | |
![]() |
f4527ce609 | |
![]() |
112433da87 | |
![]() |
ac6bbd2977 | |
![]() |
0dfa3e8c86 | |
![]() |
920e039487 | |
![]() |
7c02e1979e | |
![]() |
059baf9ea5 | |
![]() |
e1c3b7587d | |
![]() |
9ef3eff4c6 | |
![]() |
fdf43455d9 | |
![]() |
b0c0c02df9 | |
![]() |
ea30d50125 | |
![]() |
1d5669d008 | |
![]() |
5532f40d83 | |
![]() |
f64bd313aa | |
![]() |
55298ab6f3 | |
![]() |
3f0d59300b | |
![]() |
a57917b66b | |
![]() |
9a4f3f88e3 | |
![]() |
dc73b957b3 | |
![]() |
4df2e0be85 | |
![]() |
08596f886a | |
![]() |
8e904099c7 | |
![]() |
4d912516c8 | |
![]() |
8a68f5dada | |
![]() |
bd0c8f0204 | |
![]() |
a95c9e76a3 | |
![]() |
89bd69eb50 | |
![]() |
b38e7066a5 | |
![]() |
8843fcbbf4 | |
![]() |
19f3b030f9 | |
![]() |
8c4a67de31 | |
![]() |
b74828d7ea | |
![]() |
77ef648573 | |
![]() |
0ece860383 | |
![]() |
dea2bf19b1 | |
![]() |
5a0bae2318 | |
![]() |
24ac241727 | |
![]() |
db07a1ebea | |
![]() |
3779ddcd65 | |
![]() |
686f79c036 | |
![]() |
dc43fdd5fc | |
![]() |
a46440d00a | |
![]() |
a5b114a7d4 | |
![]() |
7e0bcd4eda | |
![]() |
317b29451f | |
![]() |
51a8d3b041 | |
![]() |
c04e93838f | |
![]() |
97c28553eb | |
![]() |
8f4b8d2ea2 | |
![]() |
59084dbfbe | |
![]() |
6dbb561944 | |
![]() |
b14856cf1a | |
![]() |
72664780df | |
![]() |
7c0e85d239 | |
![]() |
532f04da9d | |
![]() |
d1e9b097d1 | |
![]() |
505f568c32 | |
![]() |
e28750b522 | |
![]() |
82bb03a2a3 | |
![]() |
e291dcdd18 | |
![]() |
bd075caf56 | |
![]() |
6c665037de | |
![]() |
b38b4ee5a2 | |
![]() |
a0644d4612 | |
![]() |
888ab81ff3 | |
![]() |
b5d507bad8 | |
![]() |
ec6e862539 | |
![]() |
9215b3710f | |
![]() |
b69f298058 | |
![]() |
795d280861 | |
![]() |
6db1ed9e82 | |
![]() |
9ede62c9b1 | |
![]() |
2a9c27d206 | |
![]() |
063e7657b5 | |
![]() |
fd49f66267 | |
![]() |
067beece75 | |
![]() |
89186f46a1 | |
![]() |
7cf0e69fdf | |
![]() |
e8176b80a6 | |
![]() |
b39557f6fd | |
![]() |
2c48d7e0f0 | |
![]() |
79f15b1daa | |
![]() |
278c2ef1ec | |
![]() |
20c47243ab | |
![]() |
c2827a03b3 | |
![]() |
f7d33ff3c0 | |
![]() |
e76e94b497 | |
![]() |
0b329dbf06 | |
![]() |
c49900af50 | |
![]() |
3ff9440a01 | |
![]() |
7b7f44b9ac | |
![]() |
6f00df6452 | |
![]() |
ff8c2bc1d8 | |
![]() |
4bd0abc93f | |
![]() |
4c3c86e919 | |
![]() |
164a507899 | |
![]() |
ed5e6599d9 | |
![]() |
6023012f8b | |
![]() |
cf8dbdf0a0 | |
![]() |
58b931160f | |
![]() |
8e9eb441db | |
![]() |
7e089dce6b | |
![]() |
d9086139eb | |
![]() |
8a42d664b8 | |
![]() |
3b21c41690 | |
![]() |
b6e7d7566d | |
![]() |
852a135040 | |
![]() |
ef28579c4a | |
![]() |
cbaa0b0be0 | |
![]() |
6a78951715 | |
![]() |
68d747b7b9 | |
![]() |
3d398873f1 | |
![]() |
9594b6df32 | |
![]() |
24d2534641 | |
![]() |
29076f7eb8 | |
![]() |
5265c3cc1f | |
![]() |
557a843c69 | |
![]() |
82e7b75a02 | |
![]() |
98f70ea8d8 | |
![]() |
d8963c836e | |
![]() |
e1de18ef10 | |
![]() |
30efa1f57e | |
![]() |
3d296abde9 | |
![]() |
733751fadd | |
![]() |
5b5f33c421 | |
![]() |
8ff48ac5ea | |
![]() |
b6a249baa9 | |
![]() |
8db70b5bbc | |
![]() |
ae89b61af0 | |
![]() |
5fd5fc76e5 | |
![]() |
8538a5a5b6 | |
![]() |
19072414cb | |
![]() |
cd0663074e | |
![]() |
2180cc7c26 | |
![]() |
80ea2e62f7 | |
![]() |
7895e9cc45 | |
![]() |
0c0757b8c2 | |
![]() |
2705226eb5 | |
![]() |
b6894c18fa | |
![]() |
483cf6d7af | |
![]() |
263e654208 | |
![]() |
7dea8e08b5 | |
![]() |
e81494a132 | |
![]() |
ef89afae3e | |
![]() |
954adc71c4 | |
![]() |
f7b1baf1ef | |
![]() |
21f8cdd4c9 | |
![]() |
f6f2ea7451 | |
![]() |
5e6d4d53a9 | |
![]() |
fec5db18c1 | |
![]() |
98e4e45df7 | |
![]() |
c240e6b729 | |
![]() |
1735f8deef | |
![]() |
ef1b6d2a55 | |
![]() |
e79e615c15 | |
![]() |
465ae507d8 | |
![]() |
af9bfc21cb | |
![]() |
7f73f27d56 | |
![]() |
4942f6f75a | |
![]() |
debad00e82 | |
![]() |
b5486b8908 | |
![]() |
66d60d10bb | |
![]() |
21c01f32ff | |
![]() |
da214be5a1 | |
![]() |
0eedab3d76 | |
![]() |
10e9fed22b | |
![]() |
ed130fdc57 | |
![]() |
02a9885aa5 | |
![]() |
983f02ea1b | |
![]() |
130571b56e | |
![]() |
31509f02cc | |
![]() |
6190192cbc | |
![]() |
299934bb1e | |
![]() |
cc89a20ed9 | |
![]() |
486a041adf | |
![]() |
fb9afd8313 | |
![]() |
f3ffbd4710 | |
![]() |
98e4ea6fde | |
![]() |
a2e8d49847 | |
![]() |
1a497bcaf2 | |
![]() |
c9ec5ac87b | |
![]() |
e93edefef7 | |
![]() |
9f30da334f | |
![]() |
d349f84f04 | |
![]() |
d12b985507 | |
![]() |
ea077eac62 | |
![]() |
6b3f293ac6 | |
![]() |
af0fe1db89 | |
![]() |
5d1608f34b | |
![]() |
debf1e6cd5 | |
![]() |
abc255bb02 | |
![]() |
892420e2c6 | |
![]() |
ddb197951e | |
![]() |
9c0df3c0a8 | |
![]() |
5e2693c9b4 | |
![]() |
512b4b9cbb | |
![]() |
23acbb664e | |
![]() |
f9e17d6c25 | |
![]() |
4a81c3ac18 | |
![]() |
14e2ed7be1 | |
![]() |
c0472a06f1 | |
![]() |
6682004dc8 | |
![]() |
ec83d999bf | |
![]() |
9a58d71378 | |
![]() |
3d69ec496a | |
![]() |
d7d878fd43 | |
![]() |
8aa27488b6 | |
![]() |
1d3b1868fb | |
![]() |
b2f7815a7f | |
![]() |
3851fc189f | |
![]() |
bc915216a0 | |
![]() |
be6c5e172f | |
![]() |
99c9b56cf3 | |
![]() |
5a8818edf3 | |
![]() |
4484f30021 | |
![]() |
8990b1312b | |
![]() |
ea48b1265d | |
![]() |
abe41de19b | |
![]() |
ecb172b07e | |
![]() |
09c3ae795d | |
![]() |
a0fbd37e58 | |
![]() |
ef09cfcd71 | |
![]() |
279619fc80 | |
![]() |
a8ea0ae4e5 | |
![]() |
63f1856a2c | |
![]() |
83dc8f4d77 | |
![]() |
a18d1987a2 | |
![]() |
f1b8c356a6 | |
![]() |
28c7d94bd2 | |
![]() |
db28a042d5 | |
![]() |
75a524c916 | |
![]() |
2096755ad6 | |
![]() |
b9c5911883 | |
![]() |
fb266fbf8c | |
![]() |
8a99995810 | |
![]() |
d8e6c07ca0 | |
![]() |
a8af90f912 | |
![]() |
08f085d823 | |
![]() |
979fb58e50 | |
![]() |
1205e34650 | |
![]() |
acc8bf3405 | |
![]() |
ba4fb0d3f9 | |
![]() |
2a0071aa01 | |
![]() |
be175d205c | |
![]() |
a9c976b6c1 | |
![]() |
d0cff63ed6 | |
![]() |
a92460d38f | |
![]() |
24bc54035a | |
![]() |
fcc9f5cca4 | |
![]() |
4cdfb1453a | |
![]() |
23df47664a | |
![]() |
ac8762be10 | |
![]() |
464a0a82f0 | |
![]() |
7d32275ebe | |
![]() |
f969a4ef5e | |
![]() |
12859b8959 | |
![]() |
3a276e8875 | |
![]() |
675abd7512 | |
![]() |
cf9d6943d5 | |
![]() |
c307c1dfc2 | |
![]() |
6da10036dc | |
![]() |
a4bbab4aa2 | |
![]() |
ff742d926a | |
![]() |
71f5eaf11e | |
![]() |
ef5cf4fac3 | |
![]() |
2b0146663a | |
![]() |
e3c4816035 | |
![]() |
9559ba2f06 | |
![]() |
8d04545f03 | |
![]() |
41239ae766 | |
![]() |
021b6b3902 | |
![]() |
02a6ee1ef4 | |
![]() |
213e4785e7 | |
![]() |
a6fa3e82d9 | |
![]() |
b7b2a08399 | |
![]() |
28293284a7 | |
![]() |
19e039e0d2 | |
![]() |
ff2e6e1434 | |
![]() |
95d387a790 | |
![]() |
f0e5721959 | |
![]() |
0d098a01ef | |
![]() |
ffec1c7fe0 | |
![]() |
9dd419d822 | |
![]() |
54fc605cc5 | |
![]() |
a53fa977df | |
![]() |
e69ba33420 | |
![]() |
bca743054b | |
![]() |
4c54ab6379 | |
![]() |
12363cec4a | |
![]() |
4a318f8f51 | |
![]() |
baa7996289 | |
![]() |
60882a616e | |
![]() |
3c8c8ddf36 | |
![]() |
6bde6aa711 | |
![]() |
8ce16fd7d9 | |
![]() |
a4f855108c | |
![]() |
3f7723b2dc | |
![]() |
43cca6c9f8 | |
![]() |
4e83ca34ce | |
![]() |
a5110da37c | |
![]() |
20cffb54d4 | |
![]() |
6897f0141b | |
![]() |
ad993437aa | |
![]() |
9479c8d33b | |
![]() |
eede9f349e | |
![]() |
ae22a64157 | |
![]() |
0cbbae9655 | |
![]() |
6d36f4a228 | |
![]() |
c39c544c96 | |
![]() |
b64f0c0ca7 | |
![]() |
240bb09070 | |
![]() |
f8e6aab86f | |
![]() |
82588fbc35 | |
![]() |
4f7b13e634 | |
![]() |
05d97397d3 | |
![]() |
22009bcc58 | |
![]() |
68f6556856 | |
![]() |
830266b4d5 | |
![]() |
04439fc51f | |
![]() |
3ac4ddcbe3 | |
![]() |
5126373862 | |
![]() |
00dfdc22cf | |
![]() |
3143475769 | |
![]() |
5ab4b321a0 | |
![]() |
fb492e3dc5 | |
![]() |
5665a4917c | |
![]() |
ec4f462684 | |
![]() |
1464094967 | |
![]() |
420cd84cf1 | |
![]() |
b71212b022 | |
![]() |
f5eb3e7471 | |
![]() |
19c9f0d76f | |
![]() |
f7ac829f28 | |
![]() |
a905a6048c | |
![]() |
a95a08efd3 | |
![]() |
44c37571cc | |
![]() |
00f912928f | |
![]() |
179870c573 | |
![]() |
ed16ff07df | |
![]() |
d282c61120 | |
![]() |
5304ca1563 | |
![]() |
ff16521d4f | |
![]() |
94e81ba812 | |
![]() |
c871b37453 | |
![]() |
780a0bf807 | |
![]() |
d0df4de2a3 | |
![]() |
c4840b30d2 | |
![]() |
ede35df24a | |
![]() |
e0604e3af6 | |
![]() |
0219b8bd4d | |
![]() |
7fccb5dbc9 | |
![]() |
7b8f466adf | |
![]() |
24be189728 | |
![]() |
de1ac131f7 | |
![]() |
58eaf07627 | |
![]() |
54d51d0982 | |
![]() |
e9c24090d4 | |
![]() |
036c7e8492 | |
![]() |
45eda4f3b9 | |
![]() |
43d114546c | |
![]() |
5771a41a32 | |
![]() |
d4b449c6e1 | |
![]() |
faa4420e1f | |
![]() |
21711c6e0d | |
![]() |
d5e82cdfac | |
![]() |
d578ac3f9e | |
![]() |
b1aeb35370 | |
![]() |
ac19cf89df | |
![]() |
e26e7acaa1 | |
![]() |
e7305c62ee | |
![]() |
f036b641eb | |
![]() |
7df91d852c | |
![]() |
cbd01ae818 | |
![]() |
7b95273218 | |
![]() |
5bd9ee5c7f | |
![]() |
4097585f5d | |
![]() |
a53524c826 | |
![]() |
2dd99c5a08 | |
![]() |
f08342c704 | |
![]() |
98a54994c0 | |
![]() |
735245977b | |
![]() |
17809a5803 | |
![]() |
1716852057 | |
![]() |
a49e5877ec | |
![]() |
8daaf7b727 | |
![]() |
2b7f3a597f | |
![]() |
d433fc7c30 | |
![]() |
aadbcb69a7 | |
![]() |
198ccd320b | |
![]() |
6e702cd16c | |
![]() |
626aae6edf | |
![]() |
d95f17fe77 | |
![]() |
fd5e844cc1 | |
![]() |
f713f13b2c | |
![]() |
9b3c806ba7 | |
![]() |
62ecdb8ad0 | |
![]() |
378a16b4fb | |
![]() |
945ea785ae | |
![]() |
a6e3a09118 | |
![]() |
0f0e7d18db | |
![]() |
6823c79ae0 | |
![]() |
b86d631744 | |
![]() |
d39b8caff9 | |
![]() |
afd4b46f72 | |
![]() |
01635722e9 | |
![]() |
52e6c88941 | |
![]() |
cba5c7bb45 | |
![]() |
4d876f2af2 | |
![]() |
3adf64e637 | |
![]() |
5b73670252 | |
![]() |
b6613e7b27 | |
![]() |
6ccf1dcbf9 | |
![]() |
62cf277cd7 | |
![]() |
c81a3ebc0a | |
![]() |
1664ea4ad4 | |
![]() |
1dd4b6de5e | |
![]() |
723144199e | |
![]() |
129bc6b013 | |
![]() |
0f53b33417 | |
![]() |
0eee2edd28 | |
![]() |
2b1fa1711b | |
![]() |
623845d07d | |
![]() |
825bfe4717 | |
![]() |
5d3f464ec3 | |
![]() |
e1536961ce | |
![]() |
800a79adde | |
![]() |
2c264d9a4b | |
![]() |
c72b455a83 | |
![]() |
d0e6f22a79 | |
![]() |
0c805e049e | |
![]() |
fe303231cf | |
![]() |
daeb10151b | |
![]() |
cde4cb1358 | |
![]() |
756797b258 | |
![]() |
263d2dbae2 | |
![]() |
9a78a6f640 | |
![]() |
cbac4019b3 | |
![]() |
46ab3be1f4 | |
![]() |
0874768c1d | |
![]() |
8a283b1cc0 | |
![]() |
09f91159c9 | |
![]() |
51810c6919 | |
![]() |
db572d35a7 | |
![]() |
7cb57606bf | |
![]() |
751f7a24e9 | |
![]() |
337009c3a0 | |
![]() |
0f9c3b4cea | |
![]() |
03b226248a | |
![]() |
c70e8252fe | |
![]() |
b2d716909f | |
![]() |
686bcc8a48 | |
![]() |
2c6aa80b3c | |
![]() |
83ff07ade0 | |
![]() |
ab5329be02 | |
![]() |
46a51bd92b | |
![]() |
2f0eb3560b | |
![]() |
57ecf4de9c | |
![]() |
d4fb812352 | |
![]() |
29fc30ea69 | |
![]() |
fb0da9848c | |
![]() |
9d22089104 | |
![]() |
44258204bd | |
![]() |
e64f60b73f | |
![]() |
b657dc537c | |
![]() |
3f77c6f64e | |
![]() |
05ebb17cd6 | |
![]() |
5eff4a7544 | |
![]() |
d93c8540c8 | |
![]() |
6e0ef893f4 | |
![]() |
3c501e4f2a | |
![]() |
1a20a40218 | |
![]() |
e586178479 | |
![]() |
f6680ed063 | |
![]() |
5629fe60c1 | |
![]() |
8c7a7cf9db | |
![]() |
e54cf2f218 | |
![]() |
d34558954d | |
![]() |
e6ece52575 | |
![]() |
4aa1c3842f | |
![]() |
aa416cc0ad | |
![]() |
7a09b0470d | |
![]() |
f911347318 | |
![]() |
a885f0b41a | |
![]() |
7b2b2b527c | |
![]() |
64d7d2484f | |
![]() |
2ca7e9c55e | |
![]() |
a1aa9a4375 | |
![]() |
f8cb5161a9 | |
![]() |
bb9fb10ec5 | |
![]() |
4347f3de3e | |
![]() |
95e515d585 | |
![]() |
76cfc309a9 | |
![]() |
7c37bf9965 | |
![]() |
2b50610a60 | |
![]() |
1040c752db | |
![]() |
38115f9233 | |
![]() |
e60380d205 | |
![]() |
e9b813d8ef | |
![]() |
1739bc0c24 | |
![]() |
45dd7816d7 | |
![]() |
672173c7fd | |
![]() |
5da5ce1aae | |
![]() |
abbf2ef62f | |
![]() |
9e196680de | |
![]() |
221b748b0f | |
![]() |
463d1a1875 | |
![]() |
788cdbc6dd | |
![]() |
3fc99315e0 | |
![]() |
c5dccdf526 | |
![]() |
aa25e3badd | |
![]() |
9e5cfea8c0 | |
![]() |
c5657029ab | |
![]() |
f7ff9496e6 | |
![]() |
1ce13242a8 | |
![]() |
c13631102e | |
![]() |
b2f027c974 | |
![]() |
15fbb966a0 | |
![]() |
39615e1cb6 | |
![]() |
28a3c77e88 | |
![]() |
9574b33832 | |
![]() |
590569776d | |
![]() |
2828e8a5c5 | |
![]() |
e63dcc84b0 | |
![]() |
a3f3f96781 | |
![]() |
f07aaac256 | |
![]() |
eea399e3ed | |
![]() |
381ed6a451 | |
![]() |
78a196e215 | |
![]() |
eb215726d5 | |
![]() |
ef36350bf6 | |
![]() |
c0c5545c21 | |
![]() |
5672326ca8 | |
![]() |
8a85d7cb5a | |
![]() |
c17c788438 | |
![]() |
ebf17c8143 | |
![]() |
3ae26c8a54 | |
![]() |
5532c7b0a6 | |
![]() |
69caf4b4eb | |
![]() |
2525bd0c16 | |
![]() |
5c3f5d8085 | |
![]() |
257435799d | |
![]() |
d4118c6e8e | |
![]() |
dff31b293c | |
![]() |
c41be7ee22 | |
![]() |
07a3fbaf1a | |
![]() |
1af06e4533 | |
![]() |
dc2e6d1695 | |
![]() |
c7f585cc21 | |
![]() |
64862b296c | |
![]() |
159da912c2 | |
![]() |
6bf3492eb4 | |
![]() |
144264e0d8 | |
![]() |
627b8c45d2 | |
![]() |
b075b7120c | |
![]() |
60556abc4f | |
![]() |
2956e849eb | |
![]() |
e1e5dc231d | |
![]() |
9e3c817e5b | |
![]() |
336089f8a7 | |
![]() |
ae0379f974 | |
![]() |
cf0eefee54 | |
![]() |
d79193fde4 | |
![]() |
f0721bdb97 | |
![]() |
0eac19ef12 | |
![]() |
51e55dcad8 | |
![]() |
336ed1b922 | |
![]() |
023bb5e766 | |
![]() |
5eab221f7c | |
![]() |
f17aefe3d7 | |
![]() |
3d992e4501 | |
![]() |
cda6d5f636 | |
![]() |
3013189cd7 | |
![]() |
9cdfbb0845 | |
![]() |
c07bc68e6f | |
![]() |
8276ae54a1 | |
![]() |
87384cae32 | |
![]() |
92d26ff27b | |
![]() |
e4e53844d5 | |
![]() |
dc95218c68 | |
![]() |
572ca6433e | |
![]() |
a8a67a2ac9 | |
![]() |
93d5e77698 | |
![]() |
e3596ad836 | |
![]() |
e7fecd5e91 | |
![]() |
aa7ce1f641 | |
![]() |
f2ccfff803 | |
![]() |
e3ed7b59dd | |
![]() |
c5547543e0 | |
![]() |
193978af90 | |
![]() |
fda365a87b | |
![]() |
95c23fb3ad | |
![]() |
21624bc865 | |
![]() |
b6ff67d712 | |
![]() |
8d22a5a3ae | |
![]() |
8d7417d51c | |
![]() |
9637b14543 | |
![]() |
ec7ec7261e | |
![]() |
12fd1f6a48 | |
![]() |
57741a41e9 | |
![]() |
fb07f40bea | |
![]() |
20c92407c7 | |
![]() |
37ce8d93a1 | |
![]() |
efa4432eef | |
![]() |
347971e24a | |
![]() |
4859cebd9f | |
![]() |
9a1d3ea04f | |
![]() |
616f14ae53 | |
![]() |
af99829a21 | |
![]() |
c916c83c7c | |
![]() |
60d24c6ad5 | |
![]() |
729441d1ce | |
![]() |
db713cb656 | |
![]() |
c289c7d065 | |
![]() |
6fe8a09e97 | |
![]() |
b457c2a49c | |
![]() |
45e2c81ebc | |
![]() |
b232784df2 | |
![]() |
29ad07ce29 | |
![]() |
b14a138bf1 | |
![]() |
f681126f4d | |
![]() |
ca32cf8d29 | |
![]() |
e381696c55 | |
![]() |
a22f633f60 | |
![]() |
2d5d96ae33 | |
![]() |
830926044c | |
![]() |
e54395f501 | |
![]() |
38f49de6d9 | |
![]() |
a00d9f17b1 | |
![]() |
460081a22e | |
![]() |
97f9c81e19 | |
![]() |
0c4da98b52 | |
![]() |
1129c18330 | |
![]() |
8ab7e75e64 | |
![]() |
532812f6f6 | |
![]() |
9fe29bf5f7 | |
![]() |
78a6100346 | |
![]() |
1db9d54d17 | |
![]() |
c54d25de98 | |
![]() |
5017ef82a3 | |
![]() |
6810591911 | |
![]() |
3769bbb7f4 | |
![]() |
9b089a4e5a | |
![]() |
479889f162 | |
![]() |
a4ec9d7cb0 | |
![]() |
7d9333a9d7 | |
![]() |
00d74826ec | |
![]() |
802361dbd0 | |
![]() |
9d7acc6a32 | |
![]() |
82800faadf | |
![]() |
3151a3123e | |
![]() |
3f1fe413ee | |
![]() |
4099e22a77 | |
![]() |
cbdde7165e | |
![]() |
5e3de1a4e3 | |
![]() |
062ab31ecf | |
![]() |
40080f5e7d | |
![]() |
9ae4de10ed | |
![]() |
e9cc88cb95 | |
![]() |
2eb5c24068 | |
![]() |
84bc6ba28c | |
![]() |
e3cb63f59a | |
![]() |
e55bda6fe6 | |
![]() |
f65168982b | |
![]() |
8f2ca71d8b | |
![]() |
c04aaad0a4 | |
![]() |
02d10a2023 | |
![]() |
e4abd8fca6 | |
![]() |
8fbeca4321 | |
![]() |
04305d004f | |
![]() |
16d1425982 | |
![]() |
1148091f0b | |
![]() |
96ef37d0ea | |
![]() |
e552b81ade | |
![]() |
2771a10d39 | |
![]() |
5050ddb174 | |
![]() |
238c207b09 | |
![]() |
41cbfcfaa1 | |
![]() |
663f4fd39f | |
![]() |
08d88ea814 | |
![]() |
ed7c29ec26 | |
![]() |
d885ac3dd8 | |
![]() |
5c2a68076f | |
![]() |
f393fd5304 | |
![]() |
b2f5e50f16 | |
![]() |
4e07437e80 | |
![]() |
0763e29786 | |
![]() |
73df01e934 | |
![]() |
7f356aa3a8 | |
![]() |
b0e1fa9474 | |
![]() |
830b62d899 | |
![]() |
1ffc7d5d9e | |
![]() |
25721bceba | |
![]() |
3d9837a0b8 | |
![]() |
327080e70e | |
![]() |
2908da4a8a | |
![]() |
c30b881239 | |
![]() |
fd9655bc35 | |
![]() |
7b137c0aaf | |
![]() |
9091b8378e | |
![]() |
6f937a8817 | |
![]() |
6ec8ae5a5f | |
![]() |
29d203ae33 | |
![]() |
9a64b95a53 | |
![]() |
adaf238131 | |
![]() |
e5da4aa128 | |
![]() |
1899cf2daf | |
![]() |
5b60f6a5b2 | |
![]() |
6798a26ecb | |
![]() |
43506495ae | |
![]() |
874bcd9a8b | |
![]() |
3aa1f86d9e | |
![]() |
c013366b27 | |
![]() |
5c759941d5 | |
![]() |
3265a5f9b0 | |
![]() |
63721bf1db | |
![]() |
c3c6da7ec4 | |
![]() |
3a4b8e6c24 | |
![]() |
40288b99b2 | |
![]() |
c952e46f08 | |
![]() |
823a6bc521 | |
![]() |
7878d106f6 | |
![]() |
b4c6968f8c | |
![]() |
0dc507441a | |
![]() |
b1e3c941fb | |
![]() |
d47bf8076a | |
![]() |
d13737ab6c | |
![]() |
c737045dff | |
![]() |
5584b658c9 | |
![]() |
1d99ba2a8a | |
![]() |
118c1d2806 | |
![]() |
bb3f858db2 | |
![]() |
ba6382adae | |
![]() |
839b143fc4 | |
![]() |
c0e3a81c61 | |
![]() |
bf326acd7b | |
![]() |
0e5b02c373 | |
![]() |
a40c7d646a | |
![]() |
b91ecac168 | |
![]() |
065411c69c | |
![]() |
147d7f5d11 | |
![]() |
89b47e8ffc | |
![]() |
fb7688ab94 | |
![]() |
5dc96a37e2 | |
![]() |
25a9aa1797 | |
![]() |
99869821fb | |
![]() |
94e59c8fa7 | |
![]() |
d8eecfe64f | |
![]() |
e10c87b825 | |
![]() |
398dc97ed6 | |
![]() |
950fa82be3 | |
![]() |
34a69625b5 | |
![]() |
26c988fe11 | |
![]() |
2f6729d203 | |
![]() |
1d5f3d7a36 | |
![]() |
b0832ecc74 | |
![]() |
4053356597 | |
![]() |
b1076221b0 | |
![]() |
63c34a4c40 | |
![]() |
625fcd5821 | |
![]() |
07774ab060 | |
![]() |
8d1abe8766 | |
![]() |
63cb12d7c2 | |
![]() |
20a767eee8 | |
![]() |
aa86772f96 | |
![]() |
bfd01c425d | |
![]() |
6eb04f90a3 | |
![]() |
5cad4497de | |
![]() |
3f23548cc5 | |
![]() |
927b1337fa | |
![]() |
4094032649 | |
![]() |
1bc9600c58 | |
![]() |
88c96e26de | |
![]() |
59a09fb86f | |
![]() |
5c78ecba40 | |
![]() |
29345aaa30 | |
![]() |
b3ded7edce | |
![]() |
60edf5e9b8 | |
![]() |
0ff307e789 | |
![]() |
acdae4fba3 | |
![]() |
eb7c43ee9d | |
![]() |
074d98a14a | |
![]() |
e4a73f003a | |
![]() |
1526c527d0 | |
![]() |
aca2d9586c | |
![]() |
c6fc76e335 | |
![]() |
4580906405 | |
![]() |
8016e9adf4 | |
![]() |
d4acceb858 | |
![]() |
4b540e3bd0 | |
![]() |
e6c5c1b598 | |
![]() |
c355c9ad50 | |
![]() |
5c9f1d9401 | |
![]() |
cff8b97e8a | |
![]() |
39d758c4d6 | |
![]() |
331f9a1b96 | |
![]() |
917474f694 | |
![]() |
f3e8037e0f | |
![]() |
a3cd3e31b1 | |
![]() |
e5f7aa9817 | |
![]() |
33aa61daea | |
![]() |
14f2a68799 | |
![]() |
31a35f2a15 | |
![]() |
5abd23af5a | |
![]() |
87b3b214b9 | |
![]() |
3ce091e9d7 | |
![]() |
1abc8cf502 | |
![]() |
677352e498 | |
![]() |
2076681e76 | |
![]() |
140b7ce51e | |
![]() |
a7f2f95318 | |
![]() |
df7dcb2764 | |
![]() |
e0e4517d9e | |
![]() |
e8d4e88118 | |
![]() |
4bc80ee483 | |
![]() |
4ad0743f61 | |
![]() |
28f6eb0200 | |
![]() |
528d6b7ef1 | |
![]() |
72c0ada578 | |
![]() |
38e57e321f | |
![]() |
0db6b8dc54 | |
![]() |
acb19a06cf | |
![]() |
7c5cb1acc5 | |
![]() |
bb3c66638c | |
![]() |
4f341bef8b | |
![]() |
7696f78d07 | |
![]() |
8b4a1c3d75 | |
![]() |
8279d8c787 | |
![]() |
8f9942149a | |
![]() |
a5d973b681 | |
![]() |
3c87bcde46 | |
![]() |
7880353224 | |
![]() |
02097b577c | |
![]() |
905e116b6b | |
![]() |
6940930c3e | |
![]() |
331d44a78a | |
![]() |
c3bc3cc514 | |
![]() |
c6ee37bacd | |
![]() |
fc3f525a67 | |
![]() |
d37edd69ae | |
![]() |
b3afff9638 | |
![]() |
388e6c8262 | |
![]() |
5ce095f30e | |
![]() |
385ac268d7 | |
![]() |
c348f759af | |
![]() |
7e6f61f818 | |
![]() |
2e6db85578 | |
![]() |
4d1db9f847 | |
![]() |
2209b26fa5 | |
![]() |
5ba71ae6f7 | |
![]() |
39c2433afb | |
![]() |
86f99959b0 | |
![]() |
5b2c2b336c | |
![]() |
b4eb910cb1 | |
![]() |
1ac7aa151e | |
![]() |
6f30c1c541 | |
![]() |
93f1a158f7 | |
![]() |
73f17249e9 | |
![]() |
ee6e7174cf | |
![]() |
5157e61418 | |
![]() |
0119728d45 | |
![]() |
26c4a4f597 | |
![]() |
7e86e3e61c | |
![]() |
ed16e678be | |
![]() |
520e91c8fd | |
![]() |
22d5f17de8 | |
![]() |
b7c2f4a6d7 | |
![]() |
1a664c941b | |
![]() |
ba74135079 | |
![]() |
34a29e6363 | |
![]() |
322989c83f | |
![]() |
0be1249bbe | |
![]() |
71b393be89 | |
![]() |
413ad60bdb | |
![]() |
9fd8e930be | |
![]() |
e1ce6377f3 | |
![]() |
1f7e358e1e | |
![]() |
f2d26b9972 | |
![]() |
2acde5a4e4 | |
![]() |
4fb484d4cf | |
![]() |
daf2e5a444 | |
![]() |
cf5b464777 | |
![]() |
72b0c63ed2 | |
![]() |
deffb01544 | |
![]() |
552b62236c | |
![]() |
0b39aaadbd | |
![]() |
2eb1bb2b13 | |
![]() |
bde17158e9 | |
![]() |
246bce85ec | |
![]() |
c72682d81b | |
![]() |
78a87ab5a6 | |
![]() |
8cbfc4c0cd | |
![]() |
faf3492e58 | |
![]() |
3e1e4bab17 | |
![]() |
bcbeadd4af | |
![]() |
f062517ccb | |
![]() |
b0aa7f25aa | |
![]() |
e67b078775 | |
![]() |
202e145db7 | |
![]() |
fd949240c0 | |
![]() |
bc5071590b | |
![]() |
7023e6ad96 | |
![]() |
db125d54dd | |
![]() |
2a0ac34656 | |
![]() |
e811f4a392 | |
![]() |
1730a41337 | |
![]() |
adbc392265 | |
![]() |
437a0c0d55 | |
![]() |
2f90d15ce6 | |
![]() |
35e360fcbe | |
![]() |
257dae5211 | |
![]() |
dc391d2403 | |
![]() |
15acd86b31 | |
![]() |
e8d2c48d3c | |
![]() |
f75c7a5cea | |
![]() |
74ed0f578a | |
![]() |
121084b2ff | |
![]() |
525e4dac95 | |
![]() |
f663373c57 | |
![]() |
c10a48f4be | |
![]() |
5983b7c6f2 | |
![]() |
93232d4253 | |
![]() |
98a93662c1 | |
![]() |
34bf291539 | |
![]() |
7a7bd84cba | |
![]() |
bca3782d73 | |
![]() |
25c6ac3d16 | |
![]() |
ac3f5a083d | |
![]() |
8506ca7919 | |
![]() |
66b7ac4c45 | |
![]() |
a2a5fd1f8e | |
![]() |
3da3a36863 | |
![]() |
9f7ef9f34f | |
![]() |
e7c47f4ec0 | |
![]() |
1c34a84dd2 | |
![]() |
81473519bd | |
![]() |
a31d05d1ce | |
![]() |
39899b917d | |
![]() |
6b032faebc | |
![]() |
6e03479fd7 | |
![]() |
0dee2d67b1 | |
![]() |
c8690a8273 | |
![]() |
921d82f083 | |
![]() |
7faf73e0f4 | |
![]() |
290ebe2fc5 | |
![]() |
54f6bd181b | |
![]() |
ac9da9d8a2 | |
![]() |
e92d1f4468 | |
![]() |
2f212f34a3 | |
![]() |
c08c8cef22 | |
![]() |
a5ecceb755 | |
![]() |
e25fe62cbc | |
![]() |
c7c04bbdeb | |
![]() |
c6df069c5a | |
![]() |
c02701dfa1 | |
![]() |
f690db9849 | |
![]() |
91a5644b0e | |
![]() |
3c7e8a3bd5 | |
![]() |
f8fd4d15be | |
![]() |
d4450d543b | |
![]() |
7ab06bcdc9 | |
![]() |
c491b83857 | |
![]() |
b13fa37771 | |
![]() |
5094ce4ef6 | |
![]() |
6be4e6f631 | |
![]() |
0eaef18391 | |
![]() |
0d053a6897 | |
![]() |
2bed5894e3 | |
![]() |
3a29696a48 | |
![]() |
47df968d4a | |
![]() |
37b959a3e9 | |
![]() |
bd7ccc3546 | |
![]() |
1fefb421bc | |
![]() |
0aeb2cd77f | |
![]() |
1a6f0c9234 | |
![]() |
b07242515f | |
![]() |
900536712d | |
![]() |
8c0b55a89e | |
![]() |
da7b11020a | |
![]() |
1f3b640a3d | |
![]() |
e9af99c625 | |
![]() |
7b80a9aa44 | |
![]() |
57dda70d2f | |
![]() |
23a1b18459 | |
![]() |
401f0fa84b | |
![]() |
2bc014db69 | |
![]() |
e3a59c4037 | |
![]() |
a1aedee446 | |
![]() |
d2ca4e9f11 | |
![]() |
07aa708894 | |
![]() |
107d00adee | |
![]() |
63e51fca66 | |
![]() |
a0a3977043 | |
![]() |
2236af84ba | |
![]() |
f250f00f3f | |
![]() |
1ddbbca90e | |
![]() |
68ca891f41 | |
![]() |
018d79b498 | |
![]() |
55f27281b3 | |
![]() |
d3905b6336 | |
![]() |
57287f0722 | |
![]() |
8d0574abf0 | |
![]() |
ba66f2303a | |
![]() |
d84c180ccb | |
![]() |
3e956e8711 | |
![]() |
c75cee3c04 | |
![]() |
9edbad5459 | |
![]() |
d3bc32dc35 | |
![]() |
916168c755 | |
![]() |
5172606032 | |
![]() |
3a2ff34433 | |
![]() |
f0a6fb0285 | |
![]() |
25be9c2890 | |
![]() |
68c601ad72 | |
![]() |
4403b4f5ce | |
![]() |
72f68afbca | |
![]() |
1b2a204e38 | |
![]() |
0c7b221c42 | |
![]() |
d5324e295f | |
![]() |
6e5d04e9fa | |
![]() |
02c58b67f0 | |
![]() |
2989793f4c | |
![]() |
d4d2b4c460 | |
![]() |
09ee7ec0e2 | |
![]() |
ad9ace8d0a | |
![]() |
96bb6e7d88 | |
![]() |
06f16d4ee0 | |
![]() |
6d6eb42fa3 | |
![]() |
b869488d35 | |
![]() |
78095ef9bc | |
![]() |
a0bf06caba | |
![]() |
c947455b15 | |
![]() |
f641d0b2b7 | |
![]() |
feecc36607 | |
![]() |
1642b06bf9 | |
![]() |
28355a4cfc | |
![]() |
93e31d088a | |
![]() |
83a0206aaa | |
![]() |
28b17a2562 | |
![]() |
ca88f5731b | |
![]() |
01467246fc | |
![]() |
c3f8ba5762 | |
![]() |
cd4aaf663b | |
![]() |
e6b1dfb095 | |
![]() |
793cc4df2c | |
![]() |
edcb750d9f | |
![]() |
36542a4b1d | |
![]() |
e19222fc0d | |
![]() |
1df2d837ee | |
![]() |
3642bcd1b6 | |
![]() |
b2a633aca1 | |
![]() |
1ff2e02fd9 | |
![]() |
8ac9700aab | |
![]() |
86d45522e3 | |
![]() |
bcfa7b2209 | |
![]() |
9999ccd36c | |
![]() |
31026d51f7 | |
![]() |
b320b20c7b | |
![]() |
cabe2ae100 | |
![]() |
d2b6e41cd1 | |
![]() |
3b655f56cb | |
![]() |
e7f0c83406 | |
![]() |
c5d8659f35 | |
![]() |
32493e395c | |
![]() |
157e2c2535 | |
![]() |
a6508e2fca | |
![]() |
d61f4078e2 | |
![]() |
4d3156b5ed | |
![]() |
3818b75188 | |
![]() |
3c5c76fcfc | |
![]() |
004dc80fb2 | |
![]() |
52357742aa | |
![]() |
5bfe31b691 | |
![]() |
e32745bca6 | |
![]() |
b9cd75eef0 | |
![]() |
76ccef7ce3 | |
![]() |
9576efb716 | |
![]() |
3ba5cb7858 | |
![]() |
ea7633c484 | |
![]() |
37d66e90fb | |
![]() |
3ed385201c | |
![]() |
6f3da6b131 | |
![]() |
28cdce7464 | |
![]() |
5b39b9c11f | |
![]() |
c71f73924b | |
![]() |
98dee03773 | |
![]() |
cc577e636d | |
![]() |
3064a1cbae | |
![]() |
905d04f1c3 | |
![]() |
eb113fa578 | |
![]() |
8f780ae8bc | |
![]() |
607bf0fe44 | |
![]() |
3942b371d7 | |
![]() |
cc025ce4ae | |
![]() |
92359fd305 | |
![]() |
adb9f68228 | |
![]() |
f9211aadd8 | |
![]() |
6c3c97d58c | |
![]() |
9ab2eef56c | |
![]() |
26d0c41f02 | |
![]() |
6c6580bc08 | |
![]() |
035b8480b0 | |
![]() |
3386f565aa | |
![]() |
1a4a4bb3a5 | |
![]() |
14ef0b1e51 | |
![]() |
437e7968b1 | |
![]() |
42cb17360e | |
![]() |
7a44746492 | |
![]() |
874f1f2428 | |
![]() |
dd6566f3c5 | |
![]() |
e4154dd472 | |
![]() |
fb30207ef3 | |
![]() |
337c230e79 | |
![]() |
80d724c504 | |
![]() |
279169105b | |
![]() |
2fbbe43c87 | |
![]() |
1974ec15ec | |
![]() |
a88862ebe0 | |
![]() |
7e7ae92e0f | |
![]() |
e40d298752 | |
![]() |
6d3add3646 | |
![]() |
4bea938ef2 | |
![]() |
83366cbed0 | |
![]() |
a1a313d992 | |
![]() |
f6e5eea4f7 | |
![]() |
339036045d | |
![]() |
5b15b2d641 | |
![]() |
ccbcc0c4e3 | |
![]() |
b91ff97170 | |
![]() |
3a674f44f1 | |
![]() |
7b638a5829 | |
![]() |
70ffd77f99 | |
![]() |
c8d6976b14 | |
![]() |
03b0935564 | |
![]() |
650cf4b27e | |
![]() |
43ad665dcf | |
![]() |
a29a43e5fc | |
![]() |
4e9c1ec0c9 | |
![]() |
8eb463c58d | |
![]() |
90430fa66d | |
![]() |
eb1ab9adfe | |
![]() |
8bc3a86f63 | |
![]() |
fa4357ce89 | |
![]() |
0b95a08d32 | |
![]() |
ad91ca4401 | |
![]() |
9917293fd0 | |
![]() |
bd7ff8a03f | |
![]() |
2972d2df7c | |
![]() |
ffedce014f | |
![]() |
a847389159 | |
![]() |
5cf92dcb73 | |
![]() |
475077c798 | |
![]() |
79526d539a | |
![]() |
1e64e531f0 | |
![]() |
154eb18657 | |
![]() |
0bb4308a48 | |
![]() |
7a05a4754f | |
![]() |
70d2c6c6cd | |
![]() |
a41652ec31 | |
![]() |
67ef42220e | |
![]() |
1db932df21 | |
![]() |
9602deacfa | |
![]() |
ef9a63ae17 | |
![]() |
c3d27347b0 | |
![]() |
07cbdc6e90 | |
![]() |
10625eacac | |
![]() |
d6c203b4fd | |
![]() |
e76c350d30 | |
![]() |
5f4215b333 | |
![]() |
b96c6c243a | |
![]() |
a3320ab51b | |
![]() |
002dc8541b | |
![]() |
b98f3d27b8 | |
![]() |
43ac4f5dfe | |
![]() |
5ff4e76904 | |
![]() |
db48a977bb | |
![]() |
00cab33fde | |
![]() |
aaf57ecfbc | |
![]() |
11389bc086 | |
![]() |
28e8131984 | |
![]() |
e5bd747b32 | |
![]() |
670ddae57c | |
![]() |
c884dfb451 | |
![]() |
1869f6fd0a | |
![]() |
b0aa3bb70f | |
![]() |
f343cd2021 | |
![]() |
d2ecccc2ff | |
![]() |
c180b6a417 | |
![]() |
1f00ce789f | |
![]() |
c0429ca333 | |
![]() |
27d1f91cac | |
![]() |
2686a66b14 | |
![]() |
d2e0c09f2e | |
![]() |
d06f410fd5 | |
![]() |
8db5e51592 | |
![]() |
71cdcc860a | |
![]() |
6af651cf2f | |
![]() |
47c0bdf172 | |
![]() |
a0e0a27f87 | |
![]() |
75dab4dff0 | |
![]() |
01923147a2 | |
![]() |
d30b52f0f9 | |
![]() |
6ab9460c16 | |
![]() |
15594b4db6 | |
![]() |
407b0cd0ca | |
![]() |
cad5d8bc31 | |
![]() |
c42583550d | |
![]() |
ff09f14191 | |
![]() |
ef9884cf47 | |
![]() |
0dbaef4316 | |
![]() |
d6ceeb3b30 | |
![]() |
11d9d30fc0 | |
![]() |
a0b2357abb | |
![]() |
03e3ac19a9 | |
![]() |
22c7224267 | |
![]() |
2abc1b1141 | |
![]() |
74fac80e7e | |
![]() |
9c37c99b62 | |
![]() |
d27f05fa60 | |
![]() |
279ad186f7 | |
![]() |
beedc72be4 | |
![]() |
e2b35ea242 | |
![]() |
9d6655bc30 | |
![]() |
7c7590fbc8 | |
![]() |
7922d5d422 | |
![]() |
a2dd8f5aee | |
![]() |
810aa68b02 | |
![]() |
120b35ac75 | |
![]() |
b2811f96b2 | |
![]() |
7ad354f412 | |
![]() |
32c27f1711 | |
![]() |
b02ed4e6ec | |
![]() |
1f676ce035 | |
![]() |
5ca90ccced | |
![]() |
a67773e973 | |
![]() |
82790e6ea4 | |
![]() |
eaeaeb57d6 | |
![]() |
2cbf4dc789 | |
![]() |
2a2da3766e | |
![]() |
0ee71cfad2 | |
![]() |
f2fa35efdf | |
![]() |
d856d4e745 | |
![]() |
7fb309c429 | |
![]() |
b1a29665cb | |
![]() |
4754a1c845 | |
![]() |
05f544495e | |
![]() |
02a0faa1d6 | |
![]() |
b66d7a688e | |
![]() |
d2e0094dfd | |
![]() |
4f12d45436 | |
![]() |
712008bc1d | |
![]() |
5804b70c1f | |
![]() |
e4c3283c9c | |
![]() |
e1eed30b5d | |
![]() |
34f963741d | |
![]() |
0d1c13661f | |
![]() |
a81ca359fc | |
![]() |
f5169e4e21 | |
![]() |
e9d498dde2 | |
![]() |
6049b4966f | |
![]() |
f9eda1883f | |
![]() |
16a263e09b | |
![]() |
170809362e | |
![]() |
c5c4bb987f | |
![]() |
689daad297 | |
![]() |
5da9486b06 | |
![]() |
b723e87e54 | |
![]() |
617b2137b4 | |
![]() |
d5cdc07eab | |
![]() |
46f339dfab | |
![]() |
a1e85e3c59 | |
![]() |
6e99f01ecd | |
![]() |
d85df14b85 | |
![]() |
69bdcd2f24 | |
![]() |
4c76a2574d | |
![]() |
307cd79be2 | |
![]() |
2e21bc5180 | |
![]() |
5520e54147 | |
![]() |
aaf7953968 | |
![]() |
95f3e49edb | |
![]() |
ebc02cd39d | |
![]() |
43f8346c00 | |
![]() |
bac5100635 | |
![]() |
2890bc2619 | |
![]() |
9e46c18443 | |
![]() |
ec83fbe3dc | |
![]() |
ede7246882 | |
![]() |
b7a4536f47 | |
![]() |
a8b1224225 | |
![]() |
c163956d08 | |
![]() |
b163a87386 | |
![]() |
c0521fd250 | |
![]() |
f1e6565ddd | |
![]() |
d12966db5b | |
![]() |
180130d684 | |
![]() |
09b414f368 | |
![]() |
285bfa9367 | |
![]() |
7be18730e8 | |
![]() |
f5b0439724 | |
![]() |
8f1486f6d3 | |
![]() |
5b38d592f0 | |
![]() |
ede4eeae9f | |
![]() |
ca56e7e8d7 | |
![]() |
3232ab5ea3 | |
![]() |
aa388adba9 | |
![]() |
10957e7d79 | |
![]() |
ef9f8a8fdf | |
![]() |
6c0ee8bb01 | |
![]() |
968dc2ccda | |
![]() |
aa39835242 | |
![]() |
6fd7a06c5d | |
![]() |
3c5c3ebe1b | |
![]() |
a6558740e8 | |
![]() |
ab763fe665 | |
![]() |
2a2fadfbff | |
![]() |
d7ebecddb4 | |
![]() |
e93bd314bc | |
![]() |
75632bb2cd | |
![]() |
b16b9d8fcc | |
![]() |
55941000c0 | |
![]() |
6ab2b004ed | |
![]() |
c96ae8dd23 | |
![]() |
5a4bfff9e5 | |
![]() |
5c014f4c29 | |
![]() |
95891db29a | |
![]() |
6cf29ba688 | |
![]() |
cf56050759 | |
![]() |
d49e98bc4b | |
![]() |
f9f14f9758 | |
![]() |
51c8173174 | |
![]() |
2468243dfd | |
![]() |
124c5047d0 | |
![]() |
38a2e8add9 | |
![]() |
e439a2e0f2 | |
![]() |
18196ec19c | |
![]() |
c61c3157c6 | |
![]() |
1dfd9115cd | |
![]() |
197a4c30be | |
![]() |
93bb840365 | |
![]() |
87ffaf89e5 | |
![]() |
113a990482 | |
![]() |
6c897c26ae | |
![]() |
6c83bbe10b | |
![]() |
b30ddc206e | |
![]() |
3e0c649e8e | |
![]() |
df458b98d7 | |
![]() |
2bd72aab44 | |
![]() |
4d38a8fd44 | |
![]() |
2f0b72e0aa | |
![]() |
6b8111c066 | |
![]() |
a1c879a6f8 | |
![]() |
c645cfa5d6 | |
![]() |
088c44465b | |
![]() |
8fe471c967 | |
![]() |
f3bb28c6af | |
![]() |
9b65c12075 | |
![]() |
ab0f1888bf | |
![]() |
3b71fba9e3 | |
![]() |
d82f7c3f71 | |
![]() |
5d7b2e2ce6 | |
![]() |
a0ffe5e7ae | |
![]() |
091aa71a6b | |
![]() |
f481871792 | |
![]() |
1fe92bddd0 | |
![]() |
2fe36776b5 | |
![]() |
7f9a311988 | |
![]() |
f80d078de3 | |
![]() |
89f42f1171 | |
![]() |
c4d1360b96 | |
![]() |
13ab9f0987 | |
![]() |
084e920c6e | |
![]() |
8ed397d4fa | |
![]() |
34be2ea9a0 | |
![]() |
3ef160eed2 | |
![]() |
b76b6fbe63 | |
![]() |
da5b01aa46 | |
![]() |
2577224bc7 | |
![]() |
06b07460e8 | |
![]() |
85774733fc | |
![]() |
b4198185bc | |
![]() |
6777f04780 | |
![]() |
500d4fedda | |
![]() |
ed5409fb6a | |
![]() |
f444c6fc32 | |
![]() |
aa950f97fa | |
![]() |
76aa4cf434 | |
![]() |
9998940aa2 | |
![]() |
b27fc0da26 | |
![]() |
dfd13b4ab5 | |
![]() |
afc87ddc9e | |
![]() |
3b7cade671 | |
![]() |
eac25194e5 | |
![]() |
e7a4210943 | |
![]() |
fd29bd5f57 | |
![]() |
834bddadad | |
![]() |
e6330dddec | |
![]() |
2fea651d1d | |
![]() |
91ffc95f29 | |
![]() |
5f8986209e | |
![]() |
0b167aaa92 | |
![]() |
fae9005f87 | |
![]() |
55179ccfed | |
![]() |
31142df5cf | |
![]() |
43ff2e3a74 | |
![]() |
7bcd553786 | |
![]() |
027d1d9c7a | |
![]() |
a79df4ba69 | |
![]() |
3898950017 | |
![]() |
16641f9367 | |
![]() |
958748cf7f | |
![]() |
03a9c46ca7 | |
![]() |
47e0f3bb1f | |
![]() |
d393e96379 | |
![]() |
4827186994 | |
![]() |
8bbfa9ca8b | |
![]() |
54d770d32e | |
![]() |
53b78086ed | |
![]() |
8381132919 | |
![]() |
5579086220 | |
![]() |
a1495689c0 | |
![]() |
6cb00cc8c7 | |
![]() |
698b8e6a05 | |
![]() |
d12e907209 | |
![]() |
3223797ae5 | |
![]() |
1e95bd4da6 | |
![]() |
41677eb785 | |
![]() |
bf12efac6d | |
![]() |
c3ac53eb43 | |
![]() |
4a4381f9f9 | |
![]() |
7a836317ac | |
![]() |
75bb7f5cdc | |
![]() |
9628a00a82 | |
![]() |
ba96edb061 | |
![]() |
c4fd94c7c5 | |
![]() |
600526a0e4 | |
![]() |
02ee873094 | |
![]() |
4c0cc079c2 | |
![]() |
dcde30c38a | |
![]() |
b57725f996 | |
![]() |
79440064fe | |
![]() |
e11c4a9c83 | |
![]() |
3e87d4bf9f | |
![]() |
282cbb18be | |
![]() |
2ace9bb893 | |
![]() |
ecaad348a7 | |
![]() |
6293efb995 | |
![]() |
826ce5806d | |
![]() |
e89dc32c90 | |
![]() |
f40e47365c | |
![]() |
1c81c79a2c | |
![]() |
9d1a69aaa9 | |
![]() |
5479932190 | |
![]() |
ef705c2285 | |
![]() |
04ba2aaf8a | |
![]() |
8d9917dd9c | |
![]() |
556ffc78c9 | |
![]() |
d6058b7f51 | |
![]() |
a07295d3bc | |
![]() |
64cc064ddb | |
![]() |
3f7b14c861 | |
![]() |
b6dc52020d | |
![]() |
2504b8126b | |
![]() |
46261440cb | |
![]() |
a62db08676 | |
![]() |
d09787d1a6 | |
![]() |
be47fe49ad | |
![]() |
7930136803 | |
![]() |
ca0eecb9d0 | |
![]() |
70396e9766 | |
![]() |
df6c5b35fe | |
![]() |
bb8ffee18c | |
![]() |
ad52f7838e | |
![]() |
60cad74286 | |
![]() |
8d58b40f33 | |
![]() |
217b35bce5 | |
![]() |
c57c36adb2 | |
![]() |
59a442cdb5 | |
![]() |
069cd4fbb4 | |
![]() |
a0ad4fa35c | |
![]() |
0e79b543cf | |
![]() |
f37ed3a40a | |
![]() |
319ec50c0d | |
![]() |
2bbfada7af | |
![]() |
92ca90c0ca | |
![]() |
940f9fec4c | |
![]() |
ae5935e7f7 | |
![]() |
4382971443 | |
![]() |
94ca7ad0f8 | |
![]() |
f14c253dea | |
![]() |
b379f331de | |
![]() |
f41e538526 | |
![]() |
b9ad241658 | |
![]() |
75b092bf0e | |
![]() |
0de255cac8 | |
![]() |
044f3d4ef5 | |
![]() |
606f2a88cd | |
![]() |
c9de336234 | |
![]() |
d8204021dc | |
![]() |
879709e686 | |
![]() |
2097e854fc | |
![]() |
abdd86c398 | |
![]() |
778e897f1f | |
![]() |
c666c65c6a | |
![]() |
7cebf598a8 | |
![]() |
e029b8f996 | |
![]() |
e8b06a6a9f | |
![]() |
d31cd0c728 | |
![]() |
2cd357a5bd | |
![]() |
77a022bd93 | |
![]() |
b8b9b7739b | |
![]() |
2d074df209 | |
![]() |
5759ba5162 | |
![]() |
50150423e1 | |
![]() |
50bceee9ab | |
![]() |
0f4b148294 | |
![]() |
1a4cfc2a2d | |
![]() |
28214b4d49 | |
![]() |
bade09b56e | |
![]() |
ed97a7c08e | |
![]() |
b465ba2652 | |
![]() |
c62410ff75 | |
![]() |
ceb04ba06d | |
![]() |
dd6f65f7dd | |
![]() |
6cdf876684 | |
![]() |
42af1f9d63 | |
![]() |
f5a820cb10 | |
![]() |
6e0be5ad35 | |
![]() |
bfca3ebc71 | |
![]() |
5f26e4ed5e | |
![]() |
908e7b42f3 | |
![]() |
2e528d1dd8 | |
![]() |
ad95473aae | |
![]() |
3eda182e9a | |
![]() |
53e30cbe19 | |
![]() |
5367893427 | |
![]() |
9bf65a415b | |
![]() |
002266c1db | |
![]() |
a9ce4d7645 | |
![]() |
8ccc18a0f3 | |
![]() |
35c43eb8a0 | |
![]() |
fa66a640c3 | |
![]() |
63c017a72f | |
![]() |
296442ad8a | |
![]() |
8fb4ef9fe3 | |
![]() |
93c87fcb25 | |
![]() |
7b9082a36c | |
![]() |
cb3be25ff4 | |
![]() |
46d6ad8adc | |
![]() |
9b4d960888 | |
![]() |
99ea63b25a | |
![]() |
7982dd017b | |
![]() |
04bf763890 | |
![]() |
b1855f95c1 | |
![]() |
8c6d8bdd12 | |
![]() |
906a77d167 | |
![]() |
1d1f595e6f | |
![]() |
02b72d79fc | |
![]() |
db9efb9317 | |
![]() |
f4446ec680 | |
![]() |
ea917d6b2b | |
![]() |
11bc1aeea1 | |
![]() |
cf29f97440 | |
![]() |
34b5cd7bfd | |
![]() |
d63f10928d | |
![]() |
3536b32ad2 | |
![]() |
d7917d05c6 | |
![]() |
a279a399db | |
![]() |
4b3c29ded8 | |
![]() |
beb9152d50 | |
![]() |
59ec3d3a75 | |
![]() |
a104299c7a | |
![]() |
5ed20e15cd | |
![]() |
df0c67fe50 | |
![]() |
450ef2d591 | |
![]() |
04371217e6 | |
![]() |
33d9619271 | |
![]() |
a3b730ff10 | |
![]() |
5662bbf2c2 | |
![]() |
ae5b511c83 | |
![]() |
4f9daa0d4a | |
![]() |
702a2325a8 | |
![]() |
d82b6d216d | |
![]() |
4a88f8becb | |
![]() |
f127bf53b3 | |
![]() |
291cf689e2 | |
![]() |
0bfb483090 | |
![]() |
77ac3281fb | |
![]() |
ba43da1b8e | |
![]() |
874b1ff3f4 | |
![]() |
da4a04c411 | |
![]() |
78b23c1d4f | |
![]() |
78c5f8177c | |
![]() |
91f5e253fe | |
![]() |
afbbd17556 | |
![]() |
10a43db742 | |
![]() |
067f018337 | |
![]() |
b1c9bb63d7 | |
![]() |
c42e980442 | |
![]() |
cc37030265 | |
![]() |
ed5a4aa921 | |
![]() |
be609e051a | |
![]() |
56a40d61ae | |
![]() |
c8487d8890 | |
![]() |
2ae973821f | |
![]() |
b06d3932af | |
![]() |
4af1a8cc56 | |
![]() |
6259f95aab | |
![]() |
0f426e6e77 | |
![]() |
8c1a1d21a7 | |
![]() |
64eeeb7494 | |
![]() |
8b963d5960 | |
![]() |
c8cb03f0d9 | |
![]() |
b8b0b809b4 | |
![]() |
d32a1a892a | |
![]() |
9411d6078e | |
![]() |
d38545010a | |
![]() |
c93145cb97 | |
![]() |
3aff9eb2a4 | |
![]() |
fe3cc25855 | |
![]() |
59ff43ec87 | |
![]() |
94c6e5bb38 | |
![]() |
849fe0c2c8 | |
![]() |
f393d75a1e | |
![]() |
eb9e3aa9e6 | |
![]() |
e39fa5eaa9 | |
![]() |
3e97e5528e | |
![]() |
5f7f9e43f9 | |
![]() |
2926518b3d | |
![]() |
df913f2450 | |
![]() |
d7b54b3a53 | |
![]() |
1d9ec85441 | |
![]() |
22838f027a | |
![]() |
3136ec5958 | |
![]() |
8e8fc6a3d1 | |
![]() |
5e9814d171 | |
![]() |
0cf61932b6 | |
![]() |
8254b801ae | |
![]() |
2fd0a2cd4d | |
![]() |
4f71c97854 | |
![]() |
c75840306b | |
![]() |
9ec99fef4a | |
![]() |
e5816f5a13 | |
![]() |
cc4805b1ac | |
![]() |
f9d51484cc | |
![]() |
ef0fee52f4 | |
![]() |
1fcd06f4bc | |
![]() |
303d0ed81b | |
![]() |
70378052dd | |
![]() |
0210f83f06 | |
![]() |
cbc84900b2 | |
![]() |
9986de49d1 | |
![]() |
be1886fb91 | |
![]() |
ed0b5ac939 | |
![]() |
a0f500d1d0 | |
![]() |
b81a11b790 | |
![]() |
ba276d807f | |
![]() |
1218176e09 | |
![]() |
bc5775a988 | |
![]() |
8e979d511c | |
![]() |
d2a1a7f7cf | |
![]() |
42faffc320 | |
![]() |
c2ace30318 | |
![]() |
45eedbb9c6 | |
![]() |
2b684c7bcc | |
![]() |
5d77e1b01e | |
![]() |
9b085b5797 | |
![]() |
23ad37f566 | |
![]() |
cfd4a1297f | |
![]() |
e17f663fa5 | |
![]() |
796c04e7a8 | |
![]() |
dda630ccbd | |
![]() |
68af211130 | |
![]() |
70737a437a | |
![]() |
93c80bc912 | |
![]() |
fa7ec231e3 | |
![]() |
e2a2295c99 | |
![]() |
00aa7b5621 | |
![]() |
7d7c6685d4 | |
![]() |
c39f6a8265 | |
![]() |
8ffd1304a5 | |
![]() |
25c07425a3 | |
![]() |
40eccb10d6 | |
![]() |
4bfc51c052 | |
![]() |
7d6fde5960 | |
![]() |
e837791f94 | |
![]() |
34c3c4e892 | |
![]() |
c45ed4e028 | |
![]() |
64399b6861 | |
![]() |
89befa580e | |
![]() |
cada944350 | |
![]() |
a3b75eb39d | |
![]() |
e10d43cdce | |
![]() |
62030e8942 | |
![]() |
b8cd1c9020 | |
![]() |
4944cc080e | |
![]() |
8753e3583f | |
![]() |
e767f01e0a | |
![]() |
ebd039ecce | |
![]() |
7aa287c6c1 | |
![]() |
49e0488498 | |
![]() |
bede5a5b85 | |
![]() |
27c1f1a4e4 | |
![]() |
30d4eb9250 | |
![]() |
7257fe526b | |
![]() |
90fce21adc | |
![]() |
38e30622f3 | |
![]() |
2c81b56377 | |
![]() |
e5f9e7631d | |
![]() |
27d109ce6d | |
![]() |
cb5fdb3c79 | |
![]() |
be88e906a0 | |
![]() |
188ab71673 | |
![]() |
aa368bb9d0 | |
![]() |
12717baa0b | |
![]() |
e55e1dd1b2 | |
![]() |
a8baff61ec | |
![]() |
efac5c6197 | |
![]() |
fe50a1711b | |
![]() |
a1f5de3f5b | |
![]() |
d39ca41070 | |
![]() |
35b18f9125 | |
![]() |
f2268aa69a | |
![]() |
404e919494 | |
![]() |
0e18bd6e80 | |
![]() |
46d9adb926 | |
![]() |
ac9700dd28 | |
![]() |
1b647035d0 | |
![]() |
611b3f0e07 | |
![]() |
74881e8706 | |
![]() |
783f769a98 | |
![]() |
223bbc05fe | |
![]() |
c6d7c57bbd | |
![]() |
5390203184 | |
![]() |
afa3da6d0d | |
![]() |
159ab81904 | |
![]() |
c1e6092013 | |
![]() |
808efe0f64 | |
![]() |
b8b4c5a34a | |
![]() |
0547b32727 | |
![]() |
611e4f6710 | |
![]() |
e2db038e7c | |
![]() |
3cb36a5619 | |
![]() |
5cc0246351 | |
![]() |
54b5adf868 | |
![]() |
d30c99512a | |
![]() |
887e151be5 | |
![]() |
e16aee99b4 | |
![]() |
749ad73819 | |
![]() |
00d509f27b | |
![]() |
19305c223c | |
![]() |
f89909f60c | |
![]() |
6c6ea50e42 | |
![]() |
3b59cf2ebf | |
![]() |
4dafbf21f6 | |
![]() |
d19128ed65 | |
![]() |
e6c2c2fb07 | |
![]() |
5e94bdb932 | |
![]() |
be793e4735 | |
![]() |
146f082fdc | |
![]() |
76d14de480 | |
![]() |
923fd0a2a6 | |
![]() |
9d7d8edcc3 | |
![]() |
f453bdf055 | |
![]() |
027b237f07 | |
![]() |
73121f3ccc | |
![]() |
236685f714 | |
![]() |
df8c7152fc | |
![]() |
c3d7d68cfc | |
![]() |
f2dc940436 | |
![]() |
a689ae72e3 | |
![]() |
10ea367030 | |
![]() |
3129a8fa42 | |
![]() |
b8505ebd54 | |
![]() |
a3e631cda2 | |
![]() |
b8ef357fef | |
![]() |
dc08fab0e8 | |
![]() |
d0bebe8b93 | |
![]() |
76d32b6e97 | |
![]() |
795b668c4f | |
![]() |
c478e375f6 | |
![]() |
c7db157ecd | |
![]() |
2eac54bf54 | |
![]() |
92fd0e453a | |
![]() |
e1b3263177 | |
![]() |
24c04e715d | |
![]() |
111cbbbe3c | |
![]() |
d7c01a4fe0 | |
![]() |
985f1c4879 | |
![]() |
92b53f23da | |
![]() |
0ce56fc397 | |
![]() |
9a44c6712a | |
![]() |
8227e567a1 | |
![]() |
e8a8416e44 | |
![]() |
74c03377f2 | |
![]() |
255d9e7d1e | |
![]() |
58d0f04056 | |
![]() |
bcb7fe96d5 | |
![]() |
96ffc9b174 | |
![]() |
cde87bce66 | |
![]() |
f84a996671 | |
![]() |
8f8b023429 | |
![]() |
b3d44125f6 | |
![]() |
313c16f944 | |
![]() |
af3a604354 | |
![]() |
2a611e4508 | |
![]() |
485d8dbbdb | |
![]() |
f4e20f8fc9 | |
![]() |
507e6cf770 | |
![]() |
db249454b9 | |
![]() |
c7ad4f0f68 | |
![]() |
59ef14ed9c | |
![]() |
871c8e7790 | |
![]() |
889eb48368 | |
![]() |
59e280dc54 | |
![]() |
55a8488a4f | |
![]() |
02b3292025 | |
![]() |
0e25eb287b | |
![]() |
62f8f889e1 | |
![]() |
e56bee618b | |
![]() |
3f93780d8c | |
![]() |
2f14c7b4f0 | |
![]() |
e28992d586 | |
![]() |
ea76dac760 | |
![]() |
1fecd01405 | |
![]() |
c22735b3f5 | |
![]() |
60d45b5937 | |
![]() |
a93f747afa | |
![]() |
b6cc9177a6 | |
![]() |
90f2fe5a6a | |
![]() |
228b2c1767 | |
![]() |
e35e8847b9 | |
![]() |
bfca73c0e5 | |
![]() |
bbd49044ea | |
![]() |
581a672643 | |
![]() |
11ae04d810 | |
![]() |
d8bdb3c9aa | |
![]() |
2383074e56 | |
![]() |
ef1ce35e00 | |
![]() |
be61a2590a | |
![]() |
c39e12bfba | |
![]() |
4e9f2c8f5d | |
![]() |
2cc3377edc | |
![]() |
2ebc8dcc55 | |
![]() |
e340ab7f1b | |
![]() |
69a9431471 | |
![]() |
d11949ac51 | |
![]() |
93903eb04b | |
![]() |
791aa00914 | |
![]() |
cb77dea1e9 | |
![]() |
2347b9fdd4 | |
![]() |
afb7075f82 | |
![]() |
45fe0787ca | |
![]() |
4f97743652 | |
![]() |
35fb6ee656 | |
![]() |
79be276f43 | |
![]() |
685f29d3f2 | |
![]() |
4ac6d0716a | |
![]() |
657e87c2ea | |
![]() |
ccd973d13e | |
![]() |
9d21372ff0 | |
![]() |
92088a5905 | |
![]() |
b587ebac0c | |
![]() |
a58ee801b2 | |
![]() |
b156e55430 | |
![]() |
a852695950 | |
![]() |
5c59a7fb86 | |
![]() |
e514c4a2ac | |
![]() |
e9febf231f | |
![]() |
7908e2d591 | |
![]() |
9d999920be | |
![]() |
d723a5edf7 | |
![]() |
9357e6610a | |
![]() |
65be76aa06 | |
![]() |
1c60eb3d75 | |
![]() |
d2f12e03c0 | |
![]() |
9ff53f4293 | |
![]() |
a00ce8fe41 | |
![]() |
4b3c6f8330 | |
![]() |
8be02327b2 | |
![]() |
4cd434dbe3 | |
![]() |
1edf284fed | |
![]() |
20cd47ac89 | |
![]() |
c90f4f5794 | |
![]() |
7e73b79b75 | |
![]() |
da87abd9c8 | |
![]() |
f502ba87df | |
![]() |
fc4603c078 | |
![]() |
91514f3ace | |
![]() |
29e0ddefbc | |
![]() |
1d1cdc1009 | |
![]() |
0edeff4786 | |
![]() |
c0552d8877 | |
![]() |
bc9084db79 | |
![]() |
0297c7b83b | |
![]() |
207f38c42a | |
![]() |
f24a76e770 | |
![]() |
bb050d9767 | |
![]() |
552968e5fe | |
![]() |
d725206bcb | |
![]() |
b673ad3e5c | |
![]() |
e5b818e1a2 | |
![]() |
a82d4e1f7a | |
![]() |
e7574a70fb | |
![]() |
980a4c3a4d | |
![]() |
f376aa8072 | |
![]() |
762b0c45dc | |
![]() |
98e92a9743 | |
![]() |
4805531f8b | |
![]() |
68682c4231 | |
![]() |
2cc1c563df | |
![]() |
62ebcd71ef | |
![]() |
e0b64190ab | |
![]() |
d92fd3e42d | |
![]() |
79d7821222 | |
![]() |
6af01b916e | |
![]() |
5dfd864c1a | |
![]() |
69ddd51af1 | |
![]() |
5a6f96212d | |
![]() |
060e02c4c4 | |
![]() |
6054499607 | |
![]() |
29111a2192 | |
![]() |
163d095dca | |
![]() |
963e0de0c3 | |
![]() |
f7e3afde16 | |
![]() |
b52c9c0062 | |
![]() |
69427dc42d | |
![]() |
e7e8771277 | |
![]() |
09905d78cd | |
![]() |
b604c3dbd4 | |
![]() |
3f3e33b2cb | |
![]() |
b39c710ec2 | |
![]() |
1cf672e78d | |
![]() |
2146d9e1fe | |
![]() |
1f38813cb9 | |
![]() |
c62776edaf | |
![]() |
a2e761681e | |
![]() |
6a2731f2da | |
![]() |
98034cb4dd | |
![]() |
59f9f6520d | |
![]() |
c62dd56a4a | |
![]() |
f57f2fa1b7 | |
![]() |
df3ebc5c56 | |
![]() |
b421363661 | |
![]() |
5d87d400f4 | |
![]() |
78b8eb9a1b | |
![]() |
9cbeb3720a | |
![]() |
dc16e59f2c | |
![]() |
e99546e009 | |
![]() |
eacd803a37 | |
![]() |
2fcd92dcd9 | |
![]() |
fd7eacb953 | |
![]() |
c206ee37e0 | |
![]() |
cd3ecc4ad5 | |
![]() |
69114bc6c2 | |
![]() |
78d5f76f70 | |
![]() |
fc8b5d4522 | |
![]() |
58be029ead | |
![]() |
f1e9da9048 | |
![]() |
1737df05c7 | |
![]() |
8cf681ad3b | |
![]() |
3285edc004 | |
![]() |
3ce8dcaa3f | |
![]() |
f0aecaf16f | |
![]() |
24cb45a643 | |
![]() |
69dcc69761 | |
![]() |
365d054e01 | |
![]() |
676df7eb30 | |
![]() |
a840925a50 | |
![]() |
c5489fee90 | |
![]() |
d70adaba7b | |
![]() |
acb6b5a0d2 | |
![]() |
d9c982d850 | |
![]() |
9c0ab450a0 | |
![]() |
624e023590 | |
![]() |
0c9ecb4211 | |
![]() |
ce50aed930 | |
![]() |
c8e42cf6b1 | |
![]() |
3d3f3b96d1 | |
![]() |
7a192d5aaf | |
![]() |
f275e99aba | |
![]() |
b858a34dc2 | |
![]() |
2251b85d65 | |
![]() |
394c242671 | |
![]() |
2e0e9f1c14 | |
![]() |
cb0066d639 | |
![]() |
00b21cf9c5 | |
![]() |
c2dcb507cf | |
![]() |
8b3ae825d9 | |
![]() |
e725064a2a | |
![]() |
9929025820 | |
![]() |
8fbb883ba8 | |
![]() |
168a4a7e1e | |
![]() |
61328eb91a | |
![]() |
04774c8b70 | |
![]() |
da3835c83f | |
![]() |
3e3194fd21 | |
![]() |
06334798a5 | |
![]() |
4bc87c475c | |
![]() |
6c9eb16a95 | |
![]() |
1badbfa81a | |
![]() |
577ef41e45 | |
![]() |
d52008fb55 | |
![]() |
cdcab23c54 | |
![]() |
79f0720d14 | |
![]() |
7780b4f1d7 | |
![]() |
6d9b2a95c3 | |
![]() |
0dd9990f24 | |
![]() |
8b66ea7852 | |
![]() |
c5eb09a72f | |
![]() |
3e7311ee31 | |
![]() |
782d6f59d3 | |
![]() |
2e792da934 | |
![]() |
441b6f7a0d | |
![]() |
4623b73f47 | |
![]() |
2e3003e0f1 | |
![]() |
1d58092176 | |
![]() |
00d50479f5 | |
![]() |
9143d5994d | |
![]() |
69cfbe429b | |
![]() |
0a33f9d027 | |
![]() |
9f61239704 | |
![]() |
30037bb401 | |
![]() |
ff6468d83d | |
![]() |
e9a5670cce | |
![]() |
08ef2c7b8b | |
![]() |
e5d520ab14 | |
![]() |
a20478fff0 | |
![]() |
fa275bf0a2 | |
![]() |
aa4b8f0b6d | |
![]() |
1c1c4e497d | |
![]() |
5a3a34cce7 | |
![]() |
0670272188 | |
![]() |
d56fb22208 | |
![]() |
5df1784b49 | |
![]() |
b7e5ea2941 | |
![]() |
5d94a910b9 | |
![]() |
21cf600242 | |
![]() |
66fbcdcefa | |
![]() |
5afe000ada | |
![]() |
5bb769e659 | |
![]() |
16b3dc1166 | |
![]() |
bc9de20024 | |
![]() |
0aa9a872a3 | |
![]() |
b82973b36b | |
![]() |
b706caf294 | |
![]() |
f87c17b540 | |
![]() |
d4519bda82 | |
![]() |
3814203fa2 | |
![]() |
e9e1daf962 | |
![]() |
650f9659a4 | |
![]() |
7f1b4cef27 | |
![]() |
21e0ecfcce | |
![]() |
d2dda2535b | |
![]() |
0bebd66f05 | |
![]() |
49b508544e | |
![]() |
10c1245125 | |
![]() |
d5ae0e5c53 | |
![]() |
704eceb7c7 | |
![]() |
ef4ae92da4 | |
![]() |
dfdf7455d3 | |
![]() |
d94066a10a | |
![]() |
aa2ee9c409 | |
![]() |
d3fb72733e | |
![]() |
eaef753c36 | |
![]() |
239fd81661 | |
![]() |
20c4029b33 | |
![]() |
b9f644c355 | |
![]() |
bad79965c0 | |
![]() |
ce2552712f | |
![]() |
c3b044a37b | |
![]() |
bd578a799e | |
![]() |
9bb0868628 | |
![]() |
01207ef97b | |
![]() |
eaa0bfd120 | |
![]() |
660a1ce99d | |
![]() |
6fd04e33f5 | |
![]() |
0e12503a8d | |
![]() |
5f125047f5 | |
![]() |
812e8ef314 | |
![]() |
4307aecefd | |
![]() |
c3a2cf6220 | |
![]() |
042a84c30f | |
![]() |
04af31df13 | |
![]() |
aa7def425d | |
![]() |
28d664bae2 | |
![]() |
367ffa8e80 | |
![]() |
6b9844ae82 | |
![]() |
787dcd0e86 | |
![]() |
ef99037335 | |
![]() |
6ea9d2a6d9 | |
![]() |
ae79516fd2 | |
![]() |
56eefe34d5 | |
![]() |
d60ff1e616 | |
![]() |
3a008c8b4c | |
![]() |
d34a1e9293 | |
![]() |
8a204f2ac1 | |
![]() |
77239da7ed | |
![]() |
02de92a53d | |
![]() |
37026fa94f | |
![]() |
81d3f5b2c6 | |
![]() |
2ded751237 | |
![]() |
54c542c795 | |
![]() |
c67f2130f2 | |
![]() |
c6b1102b2b | |
![]() |
f3237a1bf7 | |
![]() |
5c69500c52 | |
![]() |
9ae7ac04a2 | |
![]() |
cc919a3593 | |
![]() |
1567c5beb0 | |
![]() |
9c9a2b8494 | |
![]() |
da13ec736c | |
![]() |
c1928f874e | |
![]() |
c1da7449fe | |
![]() |
a76415c4f6 | |
![]() |
6e73cfa2cf | |
![]() |
6c7b7741d5 | |
![]() |
c8f9ffdc1f | |
![]() |
88fc67b369 | |
![]() |
d5247cb567 | |
![]() |
975c7429e5 | |
![]() |
d8032f47ca | |
![]() |
bb6a95bae8 | |
![]() |
5326cc80ed | |
![]() |
e96886b612 | |
![]() |
9ca5684b34 | |
![]() |
b010d34640 | |
![]() |
8722e6aecc | |
![]() |
5d4c85cd84 | |
![]() |
5b48b06d4a | |
![]() |
652e977b3c | |
![]() |
c6195fcf50 | |
![]() |
f2c372d9ff | |
![]() |
00c2aeb1ab | |
![]() |
f87ee2d28b | |
![]() |
de5e4491f7 | |
![]() |
94a01d23c1 | |
![]() |
a3e81c5039 | |
![]() |
f1410c5d16 | |
![]() |
fe4c7cd2dc | |
![]() |
e126393cbf | |
![]() |
b3c7901cf2 | |
![]() |
dd2e35345f | |
![]() |
c18fc6a4bb | |
![]() |
91ddbbcc3f | |
![]() |
94b0ab983d | |
![]() |
786e30056b | |
![]() |
17ab3c6362 | |
![]() |
24337ecec7 | |
![]() |
8907e5afb3 | |
![]() |
2adfefe297 | |
![]() |
5af01c041b | |
![]() |
b60b19a29a | |
![]() |
15f919e60f | |
![]() |
cd091b4f75 | |
![]() |
f2619ce17a | |
![]() |
fbf4afc3c5 | |
![]() |
46877e979b | |
![]() |
d7faab4195 | |
![]() |
82a2219a16 | |
![]() |
9f52b4fba8 | |
![]() |
85d90c2391 | |
![]() |
11d3df2775 | |
![]() |
c08522bc1e | |
![]() |
51a6ada015 | |
![]() |
eba74c1ca8 | |
![]() |
d003f77021 | |
![]() |
54499175d5 | |
![]() |
2ff33f98ef | |
![]() |
e5a3574d89 | |
![]() |
a30e8818fd | |
![]() |
69c7f858af | |
![]() |
88b1d9ba88 | |
![]() |
6311b582ec | |
![]() |
5397402396 | |
![]() |
dd62280e04 | |
![]() |
b76c701b1c | |
![]() |
6243cf0b0c | |
![]() |
9da4896f57 | |
![]() |
07eec31a8a | |
![]() |
47757a0983 | |
![]() |
205b97f732 | |
![]() |
ae8f59979d | |
![]() |
9893cc700b | |
![]() |
26977fef9c | |
![]() |
f0aeaadc48 | |
![]() |
7bb9d5d8f6 | |
![]() |
ccf607ee2c | |
![]() |
985a3e3062 | |
![]() |
8e47503f7d | |
![]() |
f31e9e6a15 | |
![]() |
ceb208f1eb | |
![]() |
33992a2c54 | |
![]() |
7feb444e31 | |
![]() |
4afcb0542f | |
![]() |
a73fd07c49 | |
![]() |
9b6511b3e7 | |
![]() |
4678df2229 | |
![]() |
72d340bd4b | |
![]() |
6561d989d6 | |
![]() |
e98fb0db48 | |
![]() |
6b97983303 | |
![]() |
191b435a48 | |
![]() |
ed23ad906a | |
![]() |
415d27a4c9 | |
![]() |
4118fcfdc6 | |
![]() |
25cdc2a04b | |
![]() |
b14e51d7c4 | |
![]() |
03138f8345 | |
![]() |
529211b9ac | |
![]() |
d360661143 | |
![]() |
92c00ee21a | |
![]() |
333eb34300 | |
![]() |
de93d1c0a3 | |
![]() |
9c1d5e49dd | |
![]() |
c8f9e12de1 | |
![]() |
06e0a7f2ed | |
![]() |
8541d2efc1 | |
![]() |
1878fded5a | |
![]() |
0cbe626aed | |
![]() |
d8b6ecd185 | |
![]() |
ee02079661 | |
![]() |
f7a7b7c8e0 | |
![]() |
da340c92a1 | |
![]() |
80be84c401 | |
![]() |
8e44c80dd0 | |
![]() |
2a7a662c03 | |
![]() |
8ae58c8066 | |
![]() |
393e482889 | |
![]() |
65cfece0a3 | |
![]() |
d469f4158e | |
![]() |
74dbbf6d9d | |
![]() |
dd9f96211b | |
![]() |
3a4c7f60e2 | |
![]() |
67328ba73f | |
![]() |
1de9e9dd01 | |
![]() |
411e5800d1 | |
![]() |
b6689d178f | |
![]() |
dc015e7a6f | |
![]() |
f72558737c | |
![]() |
6f6dbc24c2 | |
![]() |
86c85f3b45 | |
![]() |
9bd0d1ba1b | |
![]() |
98ba300f7c | |
![]() |
9639a977a3 | |
![]() |
c7bfaf51fd | |
![]() |
2561ff94ec | |
![]() |
146d89bd89 | |
![]() |
fd13a661cf | |
![]() |
11e4a295ed | |
![]() |
9a32895a1a | |
![]() |
31d48ad529 | |
![]() |
ad53523e6b | |
![]() |
fad73b5ad1 | |
![]() |
fbaa615cc8 | |
![]() |
68baa4dcaf | |
![]() |
bee7fa630b | |
![]() |
dbb6725a47 | |
![]() |
def95aa22b | |
![]() |
866fea7648 | |
![]() |
2ac4bde102 | |
![]() |
8b0e15e402 | |
![]() |
0fef19f86f | |
![]() |
29c5c37f82 | |
![]() |
668d3be390 | |
![]() |
22dabcb3ea | |
![]() |
ce0c27e802 | |
![]() |
4c845b54a7 | |
![]() |
6aae3ba2ed | |
![]() |
ec888bc87f | |
![]() |
8ae0e78786 | |
![]() |
451c8ecaf5 | |
![]() |
c61b558423 | |
![]() |
ba1d24d054 | |
![]() |
7bfabd7865 | |
![]() |
d45d925529 | |
![]() |
9e16f33c31 | |
![]() |
e57e19c9f1 | |
![]() |
52cfeee2b1 | |
![]() |
9ffda0187f | |
![]() |
b7f3f48d38 | |
![]() |
2b46cbab7a | |
![]() |
f78c30c9ff | |
![]() |
3fa262f9ca | |
![]() |
8cfb22f0b8 | |
![]() |
17a0513962 | |
![]() |
59e4db98f7 | |
![]() |
0cb28f5f40 | |
![]() |
497f631b7c | |
![]() |
f57f617ba3 | |
![]() |
a945892c52 | |
![]() |
242df0ffe9 | |
![]() |
a389d78b42 | |
![]() |
b24321a8fc | |
![]() |
28d9e09504 | |
![]() |
ab2a469aff | |
![]() |
3b4aae6d4c | |
![]() |
1488b0118c | |
![]() |
342784b237 | |
![]() |
9f38599011 | |
![]() |
4484578c1f | |
![]() |
5f85105801 | |
![]() |
9017d6afc3 | |
![]() |
56d0de8453 | |
![]() |
f9163b5cc5 | |
![]() |
0bf7a121e7 | |
![]() |
3adbe65a58 | |
![]() |
c781240459 | |
![]() |
2f7a939067 | |
![]() |
5e442fcbca | |
![]() |
6514659733 | |
![]() |
94254ec05b | |
![]() |
0d0e26d6af | |
![]() |
cffb52ab28 | |
![]() |
4e8dfb48b7 | |
![]() |
a153d758c3 | |
![]() |
dbd8173635 | |
![]() |
28a10b1664 | |
![]() |
fa359246c1 | |
![]() |
7272ef25d4 | |
![]() |
a68cc8fde2 | |
![]() |
35bf805504 | |
![]() |
ece1c6c6dc | |
![]() |
a64850a84b | |
![]() |
b15e81baf2 | |
![]() |
d0e507eba4 | |
![]() |
841fdea124 | |
![]() |
0a9cbe3080 | |
![]() |
24dfa41722 | |
![]() |
8f2a4f7b19 | |
![]() |
82a4e6ef68 | |
![]() |
b07df487f0 | |
![]() |
b6d77c164e | |
![]() |
21780e2126 | |
![]() |
8f7b0ac498 | |
![]() |
366827390e | |
![]() |
0e1d27c836 | |
![]() |
6fbb6f6846 | |
![]() |
eff149e676 | |
![]() |
21a5751575 | |
![]() |
a4eac75b25 | |
![]() |
edd28be090 | |
![]() |
a9fdf9f1f9 | |
![]() |
953492df88 | |
![]() |
2b1231b980 | |
![]() |
8a4c66dc75 | |
![]() |
0edc5b5992 | |
![]() |
5b7bb89f37 | |
![]() |
976099f5fb | |
![]() |
d4fb3e83f6 | |
![]() |
90fd2b26d3 | |
![]() |
0515c5528f | |
![]() |
c108262771 | |
![]() |
9ec7393ba5 | |
![]() |
8ac8d14abd | |
![]() |
c3b7d76102 | |
![]() |
e248cd6c66 | |
![]() |
f476f4343b | |
![]() |
2a4e37869e | |
![]() |
802c760406 | |
![]() |
755b59b7fe | |
![]() |
cbebc59115 | |
![]() |
8f66bd9ddf | |
![]() |
4ff04ab1f3 | |
![]() |
cd3cc41f90 | |
![]() |
a74c828e19 | |
![]() |
a5266f68ec | |
![]() |
30855e76e5 | |
![]() |
1d9ce709f4 | |
![]() |
c9ee5addb4 | |
![]() |
511d1f732a | |
![]() |
64367d834b | |
![]() |
cf22692c74 | |
![]() |
e284a83f73 | |
![]() |
a0f8e4f328 | |
![]() |
90ba2977fe | |
![]() |
811edb32a2 | |
![]() |
19c6d1127f | |
![]() |
3000a8f286 | |
![]() |
82850b5894 | |
![]() |
63a2a05574 | |
![]() |
3f13aed3de | |
![]() |
eace8f2fcb | |
![]() |
30eb54e86b | |
![]() |
a9c55f7568 | |
![]() |
d3db53626b | |
![]() |
45b3c2aa3c | |
![]() |
3e599e5d8e | |
![]() |
d65e84e46b | |
![]() |
e3cb49db8e | |
![]() |
688701eedb | |
![]() |
b444c82a42 | |
![]() |
280fcd8c52 | |
![]() |
4665837cf0 | |
![]() |
d7b0456bb0 | |
![]() |
ce50055138 | |
![]() |
e5b14a38ed | |
![]() |
c7888ad1f1 | |
![]() |
e7688fcf9c | |
![]() |
e1ff276d76 | |
![]() |
b4a6be0e7c | |
![]() |
571786b6c5 | |
![]() |
698ba3f271 | |
![]() |
8edbec5929 | |
![]() |
75023f2ca3 | |
![]() |
4a2c5a3161 | |
![]() |
06684e5f73 | |
![]() |
2614d21a15 | |
![]() |
e57c354a6a | |
![]() |
f7b0d1bc9d | |
![]() |
64d1459e7c | |
![]() |
b1150a5f88 | |
![]() |
7d5800a8dc | |
![]() |
2e2f3cb2aa | |
![]() |
2e56810ea2 | |
![]() |
76d242df9b | |
![]() |
76401a302a | |
![]() |
ed8660cb68 | |
![]() |
81433282be | |
![]() |
b1a05c7b59 | |
![]() |
5629cf3219 | |
![]() |
9360cb5b66 | |
![]() |
e0b5d9fae7 | |
![]() |
5e0c3d4051 | |
![]() |
fa0baf2f38 | |
![]() |
84b6d7d720 | |
![]() |
3d2ac97c61 | |
![]() |
f0569d8ae8 | |
![]() |
24d8a9ab00 | |
![]() |
4a4f96d4b5 | |
![]() |
54fda58698 | |
![]() |
dd490de2e1 | |
![]() |
1501f5b89d | |
![]() |
f1c7e716ce | |
![]() |
ee305f2dd0 | |
![]() |
9aad7997ca | |
![]() |
92ef848b30 | |
![]() |
4d61975f2c | |
![]() |
dae3a94670 | |
![]() |
c724d2127e | |
![]() |
fc55b429f5 | |
![]() |
17d79026cd | |
![]() |
bda82834de | |
![]() |
5291adf2c0 | |
![]() |
f33e153e11 | |
![]() |
1a372ce39a | |
![]() |
2241461acb | |
![]() |
a2e3414805 | |
![]() |
494aa71156 | |
![]() |
af3f43ffd5 | |
![]() |
98d1094d73 | |
![]() |
016fbd2c5c | |
![]() |
dfad020c49 | |
![]() |
ee35ecb04d | |
![]() |
a4272c71dc | |
![]() |
ae1ef9d1bb | |
![]() |
80ff1b1657 | |
![]() |
3e518c1876 | |
![]() |
6a092aeb69 | |
![]() |
16444b7da9 | |
![]() |
3ce953cb87 | |
![]() |
8f9e6769cf | |
![]() |
3ad71f75e6 | |
![]() |
42a4bc3382 | |
![]() |
0d5911d942 | |
![]() |
55e2baa089 | |
![]() |
f9d16340e0 | |
![]() |
139f5dc3bd | |
![]() |
b50d6bf1fd | |
![]() |
06f9d762cd | |
![]() |
f7b12470dd | |
![]() |
d51deac222 | |
![]() |
3b6fbff9a5 | |
![]() |
3b42a7425b | |
![]() |
53c217c383 | |
![]() |
227195df42 | |
![]() |
c16a7f623c | |
![]() |
b3657f1892 | |
![]() |
3f71a98e5e | |
![]() |
04cdbe0dc3 | |
![]() |
a60aeed539 | |
![]() |
fe46434687 | |
![]() |
2680fae9b6 | |
![]() |
6ee4439249 | |
![]() |
e9c8446d57 | |
![]() |
b787f28d27 | |
![]() |
38047108a4 | |
![]() |
209331ad33 | |
![]() |
330baa6cc3 | |
![]() |
87a2368e37 | |
![]() |
509ab6f35a | |
![]() |
562a2736ae | |
![]() |
e9318752e6 | |
![]() |
4d0febd380 | |
![]() |
5bc67cb288 | |
![]() |
13df7fa46e | |
![]() |
73a2ae8228 | |
![]() |
34adb6a0c5 | |
![]() |
e843d9fd91 | |
![]() |
1e26408812 | |
![]() |
cae133a306 | |
![]() |
a2ba8fc645 | |
![]() |
274f378c6e | |
![]() |
04f08939c0 | |
![]() |
c7f1e44513 | |
![]() |
e12e4b5b97 | |
![]() |
55fdc83aa5 | |
![]() |
c0674913e2 | |
![]() |
81f96f1a68 | |
![]() |
03ff6f2ddf | |
![]() |
db3f285054 | |
![]() |
30508d833c | |
![]() |
206af96a33 | |
![]() |
4190682a16 | |
![]() |
aedfc8e8c0 | |
![]() |
35c4ef2ee2 | |
![]() |
4688b36cdf | |
![]() |
5007650bd2 | |
![]() |
cf0465dad4 | |
![]() |
b849b08dbc | |
![]() |
7ee0a6aaa4 | |
![]() |
82403167c2 | |
![]() |
47f61ba68a | |
![]() |
cb90d3c90c | |
![]() |
ded1b4d8b3 | |
![]() |
9f22c2c455 | |
![]() |
d12335c4c6 | |
![]() |
d286b7e28c | |
![]() |
35f86ded1a | |
![]() |
12da3c0986 | |
![]() |
fa6d65887d | |
![]() |
e4b8d79444 | |
![]() |
ab99a17c99 | |
![]() |
2e35024df1 | |
![]() |
9915c85b0b | |
![]() |
bcbd48ae58 | |
![]() |
4c1f1d97cd | |
![]() |
8fc8106819 | |
![]() |
829887630d | |
![]() |
fed512689a | |
![]() |
e65cfb836c | |
![]() |
3516a01ab9 | |
![]() |
2479e1189a | |
![]() |
96c527541b | |
![]() |
dbe2baa405 | |
![]() |
9e0bea098e | |
![]() |
2c6a776318 | |
![]() |
eec56b0d6b | |
![]() |
3c451c6ae6 | |
![]() |
2d23212792 | |
![]() |
974760d331 | |
![]() |
ebe2339810 | |
![]() |
f5b9bd30aa | |
![]() |
39857626ce | |
![]() |
e7b03cdc59 | |
![]() |
893656f092 | |
![]() |
963df8f941 | |
![]() |
cff6c15e13 | |
![]() |
978a3bfef3 | |
![]() |
1b4f69b44d | |
![]() |
4f4831fe7f | |
![]() |
82ef34998a | |
![]() |
3fb2064ea4 | |
![]() |
8e8d3af096 | |
![]() |
2d08aa88d8 | |
![]() |
6410f5a717 | |
![]() |
2a40152721 | |
![]() |
dd71a47d3f | |
![]() |
933c00c7ad | |
![]() |
86d1f8f2d7 | |
![]() |
0933dc818e | |
![]() |
ce9ec88ad6 | |
![]() |
017386fec0 | |
![]() |
a56a5e9c3c | |
![]() |
2d693402c5 | |
![]() |
85e9731617 | |
![]() |
726302ef6a | |
![]() |
2e37f7514a | |
![]() |
cb8c84098e | |
![]() |
308cde53b9 | |
![]() |
e29a80d568 | |
![]() |
c93fabb5cc | |
![]() |
cc60b02964 | |
![]() |
590746ddfa | |
![]() |
8e31afe6c2 | |
![]() |
f47dacc5d0 | |
![]() |
0b6aee0ae9 | |
![]() |
c37097a150 | |
![]() |
5bf37cbe0a | |
![]() |
28bdfc972a | |
![]() |
b5567d9d9f | |
![]() |
2887a05ba3 | |
![]() |
4dca1ef848 | |
![]() |
7b041683bb | |
![]() |
beeedd33d1 | |
![]() |
58b60181d7 | |
![]() |
cfad0923cf | |
![]() |
01f374d8e5 | |
![]() |
3b0736fc67 | |
![]() |
33cfd66e41 | |
![]() |
0ae034a157 | |
![]() |
4f8accc31b | |
![]() |
aeefbe9544 | |
![]() |
846ad42a65 | |
![]() |
9afb5f661c | |
![]() |
3897f5bc87 | |
![]() |
024ffe2909 | |
![]() |
9003bc5b72 | |
![]() |
e4c683d6f8 | |
![]() |
f0cde3fc5b | |
![]() |
5cd9f49558 | |
![]() |
6a21766ce3 | |
![]() |
497e735bf4 | |
![]() |
186e1591df | |
![]() |
b44420c14f | |
![]() |
83a8822798 | |
![]() |
dad8a32e0b | |
![]() |
878c9ee8b1 | |
![]() |
d323fc7c27 | |
![]() |
7c0d37fdb9 | |
![]() |
4a0fd756ae | |
![]() |
fb39e1eacc | |
![]() |
51d32bd620 | |
![]() |
f100825ff4 | |
![]() |
50db055841 | |
![]() |
adf22f1f10 | |
![]() |
a8c6280a5e | |
![]() |
f52cc93d9d | |
![]() |
bd13540e23 | |
![]() |
52a7b45d97 | |
![]() |
3bc6e546e0 | |
![]() |
4eb0260eaf | |
![]() |
ff0fd65f9d | |
![]() |
fd62b59acd | |
![]() |
a752119d05 | |
![]() |
61dd362db0 | |
![]() |
33981661c1 | |
![]() |
ae387d1812 | |
![]() |
9fb6688801 | |
![]() |
c388a5441d | |
![]() |
a19cf253ae | |
![]() |
7b5f2948fe | |
![]() |
305a54f646 | |
![]() |
eee221f1d0 | |
![]() |
137535a821 | |
![]() |
ec93d8cf18 | |
![]() |
9b7df302e8 | |
![]() |
25a88ccd04 | |
![]() |
fa842736d2 | |
![]() |
eb1289beca | |
![]() |
5547a40ceb | |
![]() |
ace1303de2 | |
![]() |
5e02709de0 | |
![]() |
83c8d80f3a | |
![]() |
b763e39b32 | |
![]() |
d840561036 | |
![]() |
4afba8eb94 | |
![]() |
370c0b4e94 | |
![]() |
6e3ce4d644 | |
![]() |
4a1d1b6aeb | |
![]() |
731efd8b49 | |
![]() |
497ec04359 | |
![]() |
947a08d1d2 | |
![]() |
77329209a2 | |
![]() |
346e5fa55b | |
![]() |
67c9e9c8fc | |
![]() |
eecd7e084c | |
![]() |
1be5b6aaf3 | |
![]() |
1eb47d0c16 | |
![]() |
a8eefe808f | |
![]() |
6a9cbb3d97 | |
![]() |
aafb683ec7 | |
![]() |
94692162b5 | |
![]() |
218af3fef4 | |
![]() |
9d2a207184 | |
![]() |
dc458ff0db | |
![]() |
51e8c955ff | |
![]() |
ada2785b5d | |
![]() |
0dbaaa5d94 | |
![]() |
28867d07e6 | |
![]() |
8c6a4139e6 | |
![]() |
609ba7e332 | |
![]() |
d122340c13 | |
![]() |
7035b4c8b3 | |
![]() |
db710c4be5 | |
![]() |
75b08b525b | |
![]() |
39090d3732 | |
![]() |
3207f0ea80 | |
![]() |
3f7b913e88 | |
![]() |
e337e1dc40 | |
![]() |
cd90b93550 | |
![]() |
2706e005ff | |
![]() |
837b19cb1e | |
![]() |
59c5e3c16f | |
![]() |
8118297ddc | |
![]() |
c2f26e8e98 | |
![]() |
2061d75b50 | |
![]() |
2263df0242 | |
![]() |
b424f8ac12 | |
![]() |
6b064dd8eb | |
![]() |
c6c1a7fc28 | |
![]() |
b480c5b371 | |
![]() |
0e1043f80c | |
![]() |
f7ae9ab489 | |
![]() |
b32c0fb0d8 | |
![]() |
29d767bd62 | |
![]() |
8cb12c6a74 | |
![]() |
c3da792323 | |
![]() |
9627124d67 | |
![]() |
5534d5e9de | |
![]() |
5914eb5ca5 | |
![]() |
4fb1ff2f9d | |
![]() |
57f3efde63 | |
![]() |
fb330f77e6 | |
![]() |
94032aafb2 | |
![]() |
c3e9533260 | |
![]() |
a18c4d193a | |
![]() |
8f7964f435 | |
![]() |
36f009b0c2 | |
![]() |
76d9ace582 | |
![]() |
f457def201 | |
![]() |
4b23930fce | |
![]() |
38a90bd273 | |
![]() |
0dca9905dd | |
![]() |
7832bbc0a4 | |
![]() |
5158395bcf | |
![]() |
bf2e4d134a | |
![]() |
e0feb580b6 | |
![]() |
092159b071 | |
![]() |
558c471392 | |
![]() |
fae0cea17f | |
![]() |
81ba166b49 | |
![]() |
89128958ed | |
![]() |
ecd0da9fde | |
![]() |
7bc3a5090d | |
![]() |
3d6b65aced | |
![]() |
a35698009c | |
![]() |
dc15d37dcc | |
![]() |
d3a6870097 | |
![]() |
a6568dec75 | |
![]() |
54457b7093 | |
![]() |
a40a13b786 | |
![]() |
57074015c6 | |
![]() |
270eb81f8e | |
![]() |
d22092e3da | |
![]() |
e369c1b971 | |
![]() |
4068258c78 | |
![]() |
8c978ccbf3 | |
![]() |
7895191379 | |
![]() |
7d14a13b7b | |
![]() |
a10f338703 | |
![]() |
e219c3eda1 | |
![]() |
3be3677005 | |
![]() |
6b462a9100 | |
![]() |
1b432eadd8 | |
![]() |
4d1aa97020 | |
![]() |
5b064e399f | |
![]() |
dae835635c | |
![]() |
59797cfea7 | |
![]() |
91368a57ff | |
![]() |
7f5fe91905 | |
![]() |
7802d6e018 | |
![]() |
556092b7d0 | |
![]() |
85b6a3454c | |
![]() |
6d6242c27a | |
![]() |
ad52cf588b | |
![]() |
74bf4042c5 | |
![]() |
0a0bf3123b | |
![]() |
b2af7fdd70 | |
![]() |
238ecc68cf | |
![]() |
6a0c54b40e | |
![]() |
4fa906731d | |
![]() |
23c0dc58fb | |
![]() |
80e82db282 | |
![]() |
ed78f2488b | |
![]() |
b472b56883 | |
![]() |
01d52e37c4 | |
![]() |
1a02e8edba | |
![]() |
2a41cad54f | |
![]() |
a8f9e5676f | |
![]() |
60fab6ee45 | |
![]() |
c6cd3adccb | |
![]() |
440a543a85 | |
![]() |
938429f351 | |
![]() |
007af20a30 | |
![]() |
fc88a1ed1e | |
![]() |
8f304d3456 | |
![]() |
cc24fe6e93 | |
![]() |
28de7c89c7 | |
![]() |
e6ccfa5b39 | |
![]() |
6511693b2e | |
![]() |
12dc9fbeb9 | |
![]() |
862283ff7c | |
![]() |
7fc069da46 | |
![]() |
1ad3100cad | |
![]() |
3597ee7c93 | |
![]() |
ab1b0dda67 | |
![]() |
697c8f5ee1 | |
![]() |
cc34660ab9 | |
![]() |
14b99737e9 | |
![]() |
7befe898d0 | |
![]() |
139da6d720 | |
![]() |
2ecc775fb7 | |
![]() |
886ed55374 | |
![]() |
145ed2e632 | |
![]() |
f199a0f24a | |
![]() |
996a851cf6 | |
![]() |
541525c50f | |
![]() |
1fe1a62fe2 | |
![]() |
ab66986f16 | |
![]() |
b6d0365027 | |
![]() |
3c28acd85e | |
![]() |
f7bda457fa | |
![]() |
58a54adbb4 | |
![]() |
04d3e0335b | |
![]() |
8b05d36121 | |
![]() |
50ce2384d9 | |
![]() |
9441cf080b | |
![]() |
d2d3ddb72a | |
![]() |
c77837a9ea | |
![]() |
33aa6da15c | |
![]() |
4c40e754f4 | |
![]() |
ac6ce3b72c | |
![]() |
93ef6766ef | |
![]() |
d2991dae03 | |
![]() |
81209e0ded | |
![]() |
944137ad45 | |
![]() |
6ff4c560e4 | |
![]() |
daad1521d4 | |
![]() |
a08f56db42 | |
![]() |
4736012d0a | |
![]() |
eca2f972bc | |
![]() |
a5e7db793b | |
![]() |
1c0ca72877 | |
![]() |
b4eac25678 | |
![]() |
b15106c753 | |
![]() |
2f98f1faaf | |
![]() |
e21a3497c7 | |
![]() |
8f4758d9d4 | |
![]() |
2ac6cddf19 | |
![]() |
a28fc7bfa8 | |
![]() |
2dffd44985 | |
![]() |
884f784c1c | |
![]() |
d6f731c4fc | |
![]() |
7d037cfe91 | |
![]() |
498b7a922d | |
![]() |
0b3f5f7c37 | |
![]() |
38e13f2337 | |
![]() |
a1ccf85c66 | |
![]() |
5aeff20f8b | |
![]() |
f92b5b3f32 | |
![]() |
54f8b47455 | |
![]() |
0f1aaa65bc |
|
@ -10,10 +10,19 @@ CASSANDRA_TAG=3.11
|
|||
MINIO_TAG=RELEASE.2023-03-20T20-16-18Z
|
||||
OPENTS_TAG=9aa7f88
|
||||
KINESIS_TAG=2.1
|
||||
HSTREAMDB_TAG=v0.16.1
|
||||
HSTREAMDB_TAG=v0.19.3
|
||||
HSTREAMDB_ZK_TAG=3.8.1
|
||||
|
||||
MS_IMAGE_ADDR=mcr.microsoft.com/mssql/server
|
||||
SQLSERVER_TAG=2019-CU19-ubuntu-20.04
|
||||
|
||||
|
||||
# Password for the 'elastic' user (at least 6 characters)
|
||||
ELASTIC_PASSWORD="emqx123"
|
||||
# Password for the 'kibana_system' user (at least 6 characters)
|
||||
KIBANA_PASSWORD="emqx123"
|
||||
# Version of Elastic products
|
||||
ELASTIC_TAG=8.11.4
|
||||
LICENSE=basic
|
||||
|
||||
TARGET=emqx/emqx
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
version: '3.9'
|
||||
|
||||
services:
|
||||
azurite:
|
||||
container_name: azurite
|
||||
image: mcr.microsoft.com/azure-storage/azurite:3.30.0
|
||||
restart: always
|
||||
expose:
|
||||
- "10000"
|
||||
# ports:
|
||||
# - "10000:10000"
|
||||
networks:
|
||||
- emqx_bridge
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:10000"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 4
|
||||
command:
|
||||
- azurite-blob
|
||||
- "--blobHost"
|
||||
- 0.0.0.0
|
||||
- "-d"
|
||||
- debug.log
|
|
@ -0,0 +1,30 @@
|
|||
version: '3.9'
|
||||
|
||||
services:
|
||||
couchbase:
|
||||
container_name: couchbase
|
||||
hostname: couchbase
|
||||
image: ghcr.io/emqx/couchbase:1.0.0
|
||||
restart: always
|
||||
expose:
|
||||
- 8091-8093
|
||||
# ports:
|
||||
# - "8091-8093:8091-8093"
|
||||
networks:
|
||||
- emqx_bridge
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8093/admin/ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 4
|
||||
environment:
|
||||
- CLUSTER=localhost
|
||||
- USER=admin
|
||||
- PASS=public
|
||||
- PORT=8091
|
||||
- RAMSIZEMB=2048
|
||||
- RAMSIZEINDEXMB=512
|
||||
- RAMSIZEFTSMB=512
|
||||
- BUCKETS=mqtt
|
||||
- BUCKETSIZES=100
|
||||
- AUTOREBALANCE=true
|
|
@ -0,0 +1,111 @@
|
|||
version: "3.9"
|
||||
|
||||
# hint: run the following if the container fails to start locally
|
||||
# sysctl -w vm.max_map_count=262144
|
||||
services:
|
||||
setup:
|
||||
image: public.ecr.aws/elastic/elasticsearch:${ELASTIC_TAG}
|
||||
volumes:
|
||||
- ./elastic:/usr/share/elasticsearch/config/certs
|
||||
user: "0"
|
||||
command: >
|
||||
bash -c '
|
||||
if [ x${ELASTIC_PASSWORD} == x ]; then
|
||||
echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
|
||||
exit 1;
|
||||
elif [ x${KIBANA_PASSWORD} == x ]; then
|
||||
echo "Set the KIBANA_PASSWORD environment variable in the .env file";
|
||||
exit 1;
|
||||
fi;
|
||||
echo "Setting file permissions"
|
||||
chown -R root:root config/certs;
|
||||
find . -type d -exec chmod 750 \{\} \;;
|
||||
find . -type f -exec chmod 640 \{\} \;;
|
||||
echo "Waiting for Elasticsearch availability";
|
||||
until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
|
||||
echo "Setting kibana_system password";
|
||||
until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
|
||||
echo "All done!";
|
||||
'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "[ -f config/certs/ca/ca.crt ]"]
|
||||
interval: 1s
|
||||
timeout: 5s
|
||||
retries: 120
|
||||
|
||||
es01:
|
||||
depends_on:
|
||||
setup:
|
||||
condition: service_healthy
|
||||
image: public.ecr.aws/elastic/elasticsearch:${ELASTIC_TAG}
|
||||
container_name: elasticsearch
|
||||
hostname: elasticsearch
|
||||
volumes:
|
||||
- ./elastic:/usr/share/elasticsearch/config/certs
|
||||
- esdata01:/usr/share/elasticsearch/data
|
||||
ports:
|
||||
- 9200:9200
|
||||
environment:
|
||||
- node.name=es01
|
||||
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
|
||||
- bootstrap.memory_lock=true
|
||||
- discovery.type=single-node
|
||||
- xpack.security.enabled=true
|
||||
- xpack.security.http.ssl.enabled=true
|
||||
- xpack.security.http.ssl.key=certs/es01/es01.key
|
||||
- xpack.security.http.ssl.certificate=certs/es01/es01.crt
|
||||
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
|
||||
- xpack.license.self_generated.type=${LICENSE}
|
||||
mem_limit: 4G
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 120
|
||||
restart: always
|
||||
networks:
|
||||
- emqx_bridge
|
||||
|
||||
kibana:
|
||||
depends_on:
|
||||
es01:
|
||||
condition: service_healthy
|
||||
image: public.ecr.aws/elastic/kibana:${ELASTIC_TAG}
|
||||
volumes:
|
||||
- ./elastic:/usr/share/kibana/config/certs
|
||||
- kibanadata:/usr/share/kibana/data
|
||||
ports:
|
||||
- 5601:5601
|
||||
environment:
|
||||
- SERVERNAME=kibana
|
||||
- ELASTICSEARCH_HOSTS=https://es01:9200
|
||||
- ELASTICSEARCH_USERNAME=kibana_system
|
||||
- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
|
||||
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
|
||||
mem_limit: 1073741824
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 120
|
||||
restart: always
|
||||
networks:
|
||||
- emqx_bridge
|
||||
|
||||
volumes:
|
||||
esdata01:
|
||||
driver: local
|
||||
kibanadata:
|
||||
driver: local
|
|
@ -4,7 +4,7 @@ services:
|
|||
greptimedb:
|
||||
container_name: greptimedb
|
||||
hostname: greptimedb
|
||||
image: greptime/greptimedb:v0.4.4
|
||||
image: greptime/greptimedb:v0.7.1
|
||||
expose:
|
||||
- "4000"
|
||||
- "4001"
|
||||
|
|
|
@ -1,24 +1,53 @@
|
|||
version: '3.9'
|
||||
|
||||
services:
|
||||
iotdb:
|
||||
container_name: iotdb
|
||||
hostname: iotdb
|
||||
image: apache/iotdb:1.1.0-standalone
|
||||
iotdb_1_3_0:
|
||||
container_name: iotdb130
|
||||
hostname: iotdb130
|
||||
image: apache/iotdb:1.3.0-standalone
|
||||
restart: always
|
||||
environment:
|
||||
- enable_rest_service=true
|
||||
- cn_internal_address=iotdb
|
||||
- cn_internal_address=iotdb130
|
||||
- cn_internal_port=10710
|
||||
- cn_consensus_port=10720
|
||||
- cn_target_config_node_list=iotdb:10710
|
||||
- dn_rpc_address=iotdb
|
||||
- dn_internal_address=iotdb
|
||||
- cn_seed_config_node=iotdb130:10710
|
||||
- dn_rpc_address=iotdb130
|
||||
- dn_internal_address=iotdb130
|
||||
- dn_rpc_port=6667
|
||||
- dn_mpp_data_exchange_port=10740
|
||||
- dn_schema_region_consensus_port=10750
|
||||
- dn_data_region_consensus_port=10760
|
||||
- dn_target_config_node_list=iotdb:10710
|
||||
- dn_seed_config_node=iotdb130:10710
|
||||
# volumes:
|
||||
# - ./data:/iotdb/data
|
||||
# - ./logs:/iotdb/logs
|
||||
expose:
|
||||
- "18080"
|
||||
# IoTDB's REST interface, uncomment for local testing
|
||||
# ports:
|
||||
# - "18080:18080"
|
||||
networks:
|
||||
- emqx_bridge
|
||||
|
||||
iotdb_1_1_0:
|
||||
container_name: iotdb110
|
||||
hostname: iotdb110
|
||||
image: apache/iotdb:1.1.0-standalone
|
||||
restart: always
|
||||
environment:
|
||||
- enable_rest_service=true
|
||||
- cn_internal_address=iotdb110
|
||||
- cn_internal_port=10710
|
||||
- cn_consensus_port=10720
|
||||
- cn_target_config_node_list=iotdb110:10710
|
||||
- dn_rpc_address=iotdb110
|
||||
- dn_internal_address=iotdb110
|
||||
- dn_rpc_port=6667
|
||||
- dn_mpp_data_exchange_port=10740
|
||||
- dn_schema_region_consensus_port=10750
|
||||
- dn_data_region_consensus_port=10760
|
||||
- dn_target_config_node_list=iotdb110:10710
|
||||
# volumes:
|
||||
# - ./data:/iotdb/data
|
||||
# - ./logs:/iotdb/logs
|
||||
|
|
|
@ -18,7 +18,7 @@ services:
|
|||
- /tmp/emqx-ci/emqx-shared-secret:/var/lib/secret
|
||||
kdc:
|
||||
hostname: kdc.emqx.net
|
||||
image: ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04
|
||||
image: ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu22.04
|
||||
container_name: kdc.emqx.net
|
||||
expose:
|
||||
- 88 # kdc
|
||||
|
|
|
@ -10,7 +10,7 @@ services:
|
|||
nofile: 1024
|
||||
image: openldap
|
||||
#ports:
|
||||
# - 389:389
|
||||
# - "389:389"
|
||||
volumes:
|
||||
- ./certs/ca.crt:/etc/certs/ca.crt
|
||||
restart: always
|
||||
|
|
|
@ -9,10 +9,12 @@ services:
|
|||
expose:
|
||||
- "15672"
|
||||
- "5672"
|
||||
- "5671"
|
||||
# We don't want to take ports from the host
|
||||
# ports:
|
||||
#ports:
|
||||
# - "15672:15672"
|
||||
# - "5672:5672"
|
||||
# - "5671:5671"
|
||||
volumes:
|
||||
- ./certs/ca.crt:/opt/certs/ca.crt
|
||||
- ./certs/server.crt:/opt/certs/server.crt
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
version: '3.9'
|
||||
|
||||
services:
|
||||
mqnamesrvssl:
|
||||
image: apache/rocketmq:4.9.4
|
||||
container_name: rocketmq_namesrv_ssl
|
||||
# ports:
|
||||
# - 9876:9876
|
||||
volumes:
|
||||
- ./rocketmq/logs_ssl:/opt/logs
|
||||
- ./rocketmq/store_ssl:/opt/store
|
||||
environment:
|
||||
JAVA_OPT: "-Dtls.server.mode=enforcing"
|
||||
command: ./mqnamesrv
|
||||
networks:
|
||||
- emqx_bridge
|
||||
|
||||
mqbrokerssl:
|
||||
image: apache/rocketmq:4.9.4
|
||||
container_name: rocketmq_broker_ssl
|
||||
# ports:
|
||||
# - 10909:10909
|
||||
# - 10911:10911
|
||||
volumes:
|
||||
- ./rocketmq/logs_ssl:/opt/logs
|
||||
- ./rocketmq/store_ssl:/opt/store
|
||||
- ./rocketmq/conf_ssl/broker.conf:/etc/rocketmq/broker.conf
|
||||
- ./rocketmq/conf_ssl/plain_acl.yml:/home/rocketmq/rocketmq-4.9.4/conf/plain_acl.yml
|
||||
environment:
|
||||
NAMESRV_ADDR: "rocketmq_namesrv_ssl:9876"
|
||||
JAVA_OPTS: " -Duser.home=/opt -Drocketmq.broker.diskSpaceWarningLevelRatio=0.99"
|
||||
JAVA_OPT_EXT: "-server -Xms512m -Xmx512m -Xmn512m -Dtls.server.mode=enforcing"
|
||||
command: ./mqbroker -c /etc/rocketmq/broker.conf
|
||||
depends_on:
|
||||
- mqnamesrvssl
|
||||
networks:
|
||||
- emqx_bridge
|
||||
|
||||
networks:
|
||||
emqx_bridge:
|
||||
driver: bridge
|
|
@ -39,6 +39,10 @@ services:
|
|||
- 19042:9042
|
||||
# Cassandra TLS
|
||||
- 19142:9142
|
||||
# Cassandra No Auth
|
||||
- 19043:9043
|
||||
# Cassandra TLS No Auth
|
||||
- 19143:9143
|
||||
# S3
|
||||
- 19000:19000
|
||||
# S3 TLS
|
||||
|
|
|
@ -3,7 +3,7 @@ version: '3.9'
|
|||
services:
|
||||
erlang:
|
||||
container_name: erlang
|
||||
image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04}
|
||||
image: ${DOCKER_CT_RUNNER_IMAGE:-ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu22.04}
|
||||
env_file:
|
||||
- credentials.env
|
||||
- conf.env
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDSjCCAjKgAwIBAgIVAIrN275DCtGnotTPpxwvQ5751N4OMA0GCSqGSIb3DQEB
|
||||
CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu
|
||||
ZXJhdGVkIENBMB4XDTI0MDExNjAyMzIyMFoXDTI3MDExNTAyMzIyMFowNDEyMDAG
|
||||
A1UEAxMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5lcmF0ZWQgQ0Ew
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCy0nwiEurUkIPFMLV1weVM
|
||||
pPk/AlwZUzqjkeL44gsY53XI9Q05w/sL9u6PzwrXgTCFWNXzI9+MoAtp8phPkn14
|
||||
cmg5/3sLe9YcFVFjYK/MoljlUbPDj+4dgk8l+w5FRSi0+JN5krUm7rYk9lojAkeS
|
||||
fX8RU7ekKGbjBXIFtPxX5GNadu9RidR5GkHM3XroAIoris8bFOzMgFn9iybYnkhq
|
||||
0S+Hpv0A8FVxzle0KNbPpsIkxXH2DnP2iPTDym9xJNl9Iv9MPtj9XaamH7TmXcSt
|
||||
MbjkAudKsCw4bRuhHonM16DIUr8sX5UcRcAWyJ1x1qpZaOzMdh2VdYAHNuOsZwzJ
|
||||
AgMBAAGjUzBRMB0GA1UdDgQWBBTAyDlp8NZfPe8NCGVlHJSVclGOhTAfBgNVHSME
|
||||
GDAWgBTAyDlp8NZfPe8NCGVlHJSVclGOhTAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQAeIUXRKmC53iirY4P49YspLafspAMf4ndMFQAp+Oc223Vs
|
||||
hQC4axNoYnUdzWDH6LioAN7P826xNPqtXvTZF9fmeX7K8Nm9Kdj+for+QQI3j6+X
|
||||
zq98VVkACb8b/Mc9Nac/WBbv/1IKyKgNNta7//WNPgAFolOfti/C0NLsPcKhrM9L
|
||||
mGbvRX8ZjH8pVJ0YTy4/xfDcF7G/Lxl4Yvb0ZXpuQbvE1+Y0h5aoTNshT/skJxC4
|
||||
iyVseYr21s3pptKcr6H9KZuSdZe5pbEo+81nT15w+50aswFLk9GCYh5UsQ+1jkRK
|
||||
cKgxP93i6x8BVbQJGKi1A1jhauSKX2IpWZQsHy4p
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAstJ8IhLq1JCDxTC1dcHlTKT5PwJcGVM6o5Hi+OILGOd1yPUN
|
||||
OcP7C/buj88K14EwhVjV8yPfjKALafKYT5J9eHJoOf97C3vWHBVRY2CvzKJY5VGz
|
||||
w4/uHYJPJfsORUUotPiTeZK1Ju62JPZaIwJHkn1/EVO3pChm4wVyBbT8V+RjWnbv
|
||||
UYnUeRpBzN166ACKK4rPGxTszIBZ/Ysm2J5IatEvh6b9APBVcc5XtCjWz6bCJMVx
|
||||
9g5z9oj0w8pvcSTZfSL/TD7Y/V2mph+05l3ErTG45ALnSrAsOG0boR6JzNegyFK/
|
||||
LF+VHEXAFsidcdaqWWjszHYdlXWABzbjrGcMyQIDAQABAoIBAAZOLXYanmjpIRpX
|
||||
h7h7oikYEplWDRcQBBvvKZaOyuchhznTKTiZmF0xQ3Ny8J4Ndj9ndODWSZxI6uod
|
||||
FaGNp+qytwnfgDBVGSVDm6tyRfSkX1fTsA/j3/iupvmO/w9yezdZYgLaCVTyex31
|
||||
yVMdchZgYjYDUpEBYzJbV2xL18+GBRmmPjdXumlpcJqcclxjOQJSu/1WCGVfn/e/
|
||||
64NQpAm7NSKLqeUl32g0/DvUpmYRfmf7ZjVUjePaJQU6sw5/N+3V9F1hYs8VSWz0
|
||||
OMzYIfUcvixw+VWx5bu0nWt98FirhsQPjCTThD+DHP6koXGrdXpeMOQE1YZmoV5T
|
||||
vP0X+FECgYEA5dsKVDQFL67muqz3CNRVM0xDWACCoa8789hYoxvhd1iO3e4kwXBa
|
||||
ABPcZckioq+HiQ4UIxC2AhQ1FuTeIUTq7LZ0HtAAdKFi48U4LzmPhNUpG1E/HbJ3
|
||||
GQbi4u1cAzGYuhdywktgBhn9bJ4XB7+X3815Y9qKkuRcwtXgKGDy8HkCgYEAxyly
|
||||
vc7NBkLfIAmkOsm6VXfvfBTEUBUGi6+k1rarTUxWFIgRuk4FHywwWUTdxWBKJz3n
|
||||
HNNJb/g7CcufdhLTuWVHQtJDxYf2cJjoi+Kf7/i/Qs9Nyhokj5Mnh6KlZQOWXpZd
|
||||
Gwn/O13NeDxt1TIVO2xp6zY4FhVEPvaHuxsMCtECgYA7/eR/P6iO3nZoCJbdXhXy
|
||||
spftEw0FSCg8p53SzIcXUCzRrcM4HavP0181zb5VebzFP8Bvun/WoRGOLSPwyP0L
|
||||
1T8Pf7huuGSIEERuxvY3dC8raxQvGxJMnOiA0/Ss/Lfg8hfIsEWashPb0pMuOYpZ
|
||||
JlblgfejCSlQzOOZhlxB+QKBgQCKmizRLV9/0QAJAsy5YPR9UJdpCebJOKiyg806
|
||||
5Ct5AvwRE9UKjAuCczU+mu+f0fApOSpi5CQCeYVUvtG90UJpjrM2LLCfgoyeNbv4
|
||||
xgG6dqlcbHrdgK4bATUMbsOd9g4qy4gGLkHi5df9qkhhi5Y9Iajg2X3U2H4DN3yk
|
||||
WSFbUQKBgQCLz333qWOuT3OBv+EYxHDQUS4YG+dReUos+v0iPJzu+spnfibBF5IC
|
||||
RjHIhPsdN1byNB0naXOkkz4tUlLGXv6umFgDtQvy/2rxvxQmUGp/WY1VM2+164Xe
|
||||
NEWdMEU6UckCoMO77kw8JosKhmXCYaSW5bWwnXuEpOj9WWpwjKtxlA==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDQDCCAiigAwIBAgIUe90yOBN1KBxOEr2jro3epamZksIwDQYJKoZIhvcNAQEL
|
||||
BQAwNDEyMDAGA1UEAxMpRWxhc3RpYyBDZXJ0aWZpY2F0ZSBUb29sIEF1dG9nZW5l
|
||||
cmF0ZWQgQ0EwHhcNMjQwMTE2MDIzMjIyWhcNMjcwMTE1MDIzMjIyWjAPMQ0wCwYD
|
||||
VQQDEwRlczAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxGEL71pV
|
||||
j8qoUxEuL7qjRSeS1eHxeKhu2jqEZb7iA1o/7b/26QuYAkoYL+WuJNfYjg5F/O8W
|
||||
VVuAYIlN6a/mC6wT2t3pX4YSrdp+i3gtAC/LX+8mAeqMQPD+4jitOwjOsYzbuFCb
|
||||
nYl86dnFPl/+Pmj20mtZ+Wt7oIPD88j6+r5qgv59pHICxS7Cq304LDTRQbNoT8HO
|
||||
4c9VGGGtWIdtrqiYrz1OVefkffMrvFt77v6dKHn8g5tSyfQUDCoEKtTOc3Pe5zCB
|
||||
vIMs6HaapoSkl8XdpFHQ712PCZRebAMCrVcPYQ3r8e9GYmLY/NhxEn3dWTqRhHeg
|
||||
UD13O8o1aBWonwIDAQABo28wbTAdBgNVHQ4EFgQUXvGJtSf2/mLOK17AzUridtCV
|
||||
xWwwHwYDVR0jBBgwFoAUwMg5afDWXz3vDQhlZRyUlXJRjoUwIAYDVR0RBBkwF4IJ
|
||||
bG9jYWxob3N0hwR/AAABggRlczAxMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQAD
|
||||
ggEBACaNq3ZqrbsGvbEtrf6kJGIsTokTFHeVJUSYmt1ZZzDFLSepXAC/J8gphV45
|
||||
B+YSlkDPNTwMYlf7TUYY872zkdqOXN9r0NUx8MzVAX0+rux0RJba5GGUvJGZDNMX
|
||||
WM5z9ry1KjQSQ1bSoRQOD3QArmBmhvikHjLc97Vqt56N0wA/ztXWOpNZX/TXmast
|
||||
aXlUbcfQE73Cdq9tW1ATXwbQ2Gf7vVAUT3zjZSZbNdgPuBicGJHf85Fhjm2ND4+R
|
||||
sjLIOQ2YgVxNHYbueScc6lJM5RNK194K7WrEQnRyGHT3NaDUm0FFNl//aQeq1ZVw
|
||||
6gaUYlkTFauXwEYMDK901cWFaBE=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAxGEL71pVj8qoUxEuL7qjRSeS1eHxeKhu2jqEZb7iA1o/7b/2
|
||||
6QuYAkoYL+WuJNfYjg5F/O8WVVuAYIlN6a/mC6wT2t3pX4YSrdp+i3gtAC/LX+8m
|
||||
AeqMQPD+4jitOwjOsYzbuFCbnYl86dnFPl/+Pmj20mtZ+Wt7oIPD88j6+r5qgv59
|
||||
pHICxS7Cq304LDTRQbNoT8HO4c9VGGGtWIdtrqiYrz1OVefkffMrvFt77v6dKHn8
|
||||
g5tSyfQUDCoEKtTOc3Pe5zCBvIMs6HaapoSkl8XdpFHQ712PCZRebAMCrVcPYQ3r
|
||||
8e9GYmLY/NhxEn3dWTqRhHegUD13O8o1aBWonwIDAQABAoIBADJ3A/Om4az5dcce
|
||||
96EBU9q+IDBBh2Wr1wzSk9p3sqoM47fLqH5b4dzYwJ1yZw2FwFtFFLw6jqExyexE
|
||||
7JY8gyAFwPZyJ3pKQHuX1gQuRlYxchB9quU8Kn230LA+w1mT2lXrLj2PzWWvAsAv
|
||||
m837KiFMpP0O5EjB07u8kLsRr1mG6QQ24Kc8oxd7xLXIiPzSvsOpYwo9hmIWENd5
|
||||
kyA7oSa9EmN3TRTkKOHI7cFQ3DqIGdO71waUofKOdx39DyHS2YKWxDE/LUjkS9zw
|
||||
1AyZG09l4uowyLRqwYhivEq9Za6rdc64yheuHatAM9kC2AOcVcsCPZquIe90k4t1
|
||||
L7e9CAECgYEA1W483xTW8ngzxv9MMuPiW+PwVGRpyQrbO6OZOxdWEYfhrZlk5wlW
|
||||
XK2T85jqooJwMWPTk1F49vZ9WN2KuLkL65GlkEtkFbxmOiFJjXuWwycbFSk05hPs
|
||||
4AESBYHieaSPcwYhvLeG6g4PFyeqmbAGnKsJaj2ylPwDBOc7LgVlqAECgYEA64wo
|
||||
gZwaj5SlP8M/OqGH04UVYr1kP/Eq6eiDfMyV5exy+pyzofZyNKUfJfw6sGgyRRHx
|
||||
OVxlnPMsZ8zbdOXsvUEIeavpwDfQcp5eAURL65I6GMLsx2QpfiN2mDe1MqQW0jct
|
||||
UleFaURgS84KHLE0+tBBg906jOHGjsE7Q3lyUJ8CgYBYYPev4K9JZGD8bEcfY6Ie
|
||||
Lvsb1yC+8VHrFkmjYHxxcfUPr89KpGEwq2fynUW72YufyBiajkgq69Ln84U4DNhU
|
||||
ydDnOXDOV191fsc4YQ8C7LSYRKH1DBcwgwD1at1fRbdpCAb8YHrrfLre+bv5PBzg
|
||||
zyps5fOHIfwWEbI90lpQAQKBgQDoMMqBMTtxi+r1lucOScrVtFuncOCQs5BE8cIj
|
||||
1JxzAQk6iBv/LSvZP2gcDq5f1Oaw9YXfsHguJfwA+ozeiAQ9bw0Gu3N52sstIXWz
|
||||
M/rO5d9FJ2k3CEJqqFSwqkGBAQXKBUA06jeF1DREpX+MVxbNo1rhvMOJusn7UPm1
|
||||
gtMwKwKBgQCfRzFO10ITwrw8rcRZwO9Axgqf11V7xn6qpgRxj4h0HOErVTCN1H0b
|
||||
vE3Pz7cxS/g9vFRP37TuqBLfGVzPt9LAEFwCWPeZJLROBLHyu8XrhTbQx+sI2/pe
|
||||
SBEJAQAHtYasFTE0sBEKNEY2rIt1c29XZhyhhtNKD9gRN/gB355wLg==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,7 @@
|
|||
instances:
|
||||
- name: es01
|
||||
dns:
|
||||
- es01
|
||||
- localhost
|
||||
ip:
|
||||
- 127.0.0.1
|
|
@ -49,6 +49,9 @@ echo "+++++++ Creating Kafka Topics ++++++++"
|
|||
# there seem to be a race condition when creating the topics (too early)
|
||||
env KAFKA_CREATE_TOPICS="$KAFKA_CREATE_TOPICS_NG" KAFKA_PORT="$PORT1" create-topics.sh
|
||||
|
||||
# create a topic with max.message.bytes=100
|
||||
/opt/kafka/bin/kafka-topics.sh --create --bootstrap-server "${SERVER}:${PORT1}" --topic max-100-bytes --partitions 1 --replication-factor 1 --config max.message.bytes=100
|
||||
|
||||
echo "+++++++ Wait until Kafka ports are down ++++++++"
|
||||
|
||||
bash -c 'while printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' $SERVER $PORT1
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
# LDAP authentication
|
||||
|
||||
To run manual tests with the default docker-compose files.
|
||||
|
||||
Expose openldap container port by uncommenting the `ports` config in `docker-compose-ldap.yaml `
|
||||
|
||||
To start openldap:
|
||||
|
||||
```
|
||||
docker-compose -f ./.ci/docker-compose-file/docker-compose.yaml -f ./.ci/docker-compose-file/docker-compose-ldap.yaml up -docker
|
||||
```
|
||||
|
||||
## LDAP database
|
||||
|
||||
LDAP database is populated from below files:
|
||||
```
|
||||
apps/emqx_ldap/test/data/emqx.io.ldif /usr/local/etc/openldap/schema/emqx.io.ldif
|
||||
apps/emqx_ldap/test/data/emqx.schema /usr/local/etc/openldap/schema/emqx.schema
|
||||
```
|
||||
|
||||
## Minimal EMQX config
|
||||
|
||||
```
|
||||
authentication = [
|
||||
{
|
||||
backend = ldap
|
||||
base_dn = "uid=${username},ou=testdevice,dc=emqx,dc=io"
|
||||
filter = "(& (objectClass=mqttUser) (uid=${username}))"
|
||||
mechanism = password_based
|
||||
method {
|
||||
is_superuser_attribute = isSuperuser
|
||||
password_attribute = userPassword
|
||||
type = hash
|
||||
}
|
||||
password = public
|
||||
pool_size = 8
|
||||
query_timeout = "5s"
|
||||
request_timeout = "10s"
|
||||
server = "localhost:1389"
|
||||
username = "cn=root,dc=emqx,dc=io"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Example ldapsearch command
|
||||
|
||||
```
|
||||
ldapsearch -x -H ldap://localhost:389 -D "cn=root,dc=emqx,dc=io" -W -b "uid=mqttuser0007,ou=testdevice,dc=emqx,dc=io" "(&(objectClass=mqttUser)(uid=mqttuser0007))"
|
||||
```
|
||||
|
||||
## Example mqttx command
|
||||
|
||||
The client password hashes are generated from their username.
|
||||
|
||||
```
|
||||
# disabled user
|
||||
mqttx pub -t 't/1' -h localhost -p 1883 -m x -u mqttuser0006 -P mqttuser0006
|
||||
|
||||
# enabled super-user
|
||||
mqttx pub -t 't/1' -h localhost -p 1883 -m x -u mqttuser0007 -P mqttuser0007
|
||||
```
|
|
@ -9,3 +9,4 @@ accounts:
|
|||
defaultGroupPerm: PUB|SUB
|
||||
topicPerms:
|
||||
- TopicTest=PUB|SUB
|
||||
- Topic2=PUB|SUB
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
brokerClusterName=DefaultClusterSSL
|
||||
brokerName=broker-a
|
||||
brokerId=0
|
||||
|
||||
brokerIP1=rocketmq_broker_ssl
|
||||
|
||||
defaultTopicQueueNums=4
|
||||
autoCreateTopicEnable=true
|
||||
autoCreateSubscriptionGroup=true
|
||||
|
||||
listenPort=10911
|
||||
deleteWhen=04
|
||||
|
||||
fileReservedTime=120
|
||||
mapedFileSizeCommitLog=1073741824
|
||||
mapedFileSizeConsumeQueue=300000
|
||||
diskMaxUsedSpaceRatio=100
|
||||
maxMessageSize=65536
|
||||
|
||||
brokerRole=ASYNC_MASTER
|
||||
|
||||
flushDiskType=ASYNC_FLUSH
|
||||
|
||||
aclEnable=true
|
|
@ -0,0 +1,12 @@
|
|||
globalWhiteRemoteAddresses:
|
||||
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress:
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: PUB|SUB
|
||||
topicPerms:
|
||||
- TopicTest=PUB|SUB
|
||||
- Topic2=PUB|SUB
|
|
@ -96,6 +96,18 @@
|
|||
"upstream": "cassandra:9142",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "cassa_no_auth_tcp",
|
||||
"listen": "0.0.0.0:9043",
|
||||
"upstream": "cassandra_noauth:9042",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "cassa_no_auth_tls",
|
||||
"listen": "0.0.0.0:9143",
|
||||
"upstream": "cassandra_noauth:9142",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "sqlserver",
|
||||
"listen": "0.0.0.0:1433",
|
||||
|
@ -127,9 +139,15 @@
|
|||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "iotdb",
|
||||
"name": "iotdb110",
|
||||
"listen": "0.0.0.0:18080",
|
||||
"upstream": "iotdb:18080",
|
||||
"upstream": "iotdb110:18080",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "iotdb130",
|
||||
"listen": "0.0.0.0:28080",
|
||||
"upstream": "iotdb130:18080",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
|
@ -191,5 +209,23 @@
|
|||
"listen": "0.0.0.0:636",
|
||||
"upstream": "ldap:636",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "elasticsearch",
|
||||
"listen": "0.0.0.0:9200",
|
||||
"upstream": "elasticsearch:9200",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "azurite_plain",
|
||||
"listen": "0.0.0.0:10000",
|
||||
"upstream": "azurite:10000",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "couchbase",
|
||||
"listen": "0.0.0.0:8093",
|
||||
"upstream": "couchbase:8093",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
%% -*- mode: erlang -*-
|
||||
{application, http_server,
|
||||
[{description, "An HTTP server application"},
|
||||
{vsn, "0.2.0"},
|
||||
{registered, []},
|
||||
% {mod, {http_server_app, []}},
|
||||
{modules, []},
|
||||
{applications,
|
||||
[kernel,
|
||||
stdlib,
|
||||
minirest
|
||||
]},
|
||||
{env,[]},
|
||||
{modules, []},
|
||||
{application, http_server, [
|
||||
{description, "An HTTP server application"},
|
||||
{vsn, "0.2.0"},
|
||||
{registered, []},
|
||||
% {mod, {http_server_app, []}},
|
||||
{modules, []},
|
||||
{applications, [
|
||||
kernel,
|
||||
stdlib,
|
||||
minirest
|
||||
]},
|
||||
{env, []},
|
||||
{modules, []},
|
||||
|
||||
{licenses, ["Apache 2.0"]},
|
||||
{links, []}
|
||||
]}.
|
||||
{licenses, ["Apache 2.0"]},
|
||||
{links, []}
|
||||
]}.
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
## Default
|
||||
* @emqx/emqx-review-board
|
||||
|
||||
# emqx-review-board members
|
||||
## HJianBo
|
||||
## id
|
||||
## ieQu1
|
||||
## keynslug
|
||||
## qzhuyan
|
||||
## savonarola
|
||||
## terry-xiaoyu
|
||||
## thalesmg
|
||||
## zhongwencool
|
||||
## zmstone
|
||||
|
||||
## apps
|
||||
/apps/emqx/ @emqx/emqx-review-board @lafirest
|
||||
/apps/emqx_connector/ @emqx/emqx-review-board
|
||||
/apps/emqx_auth/ @emqx/emqx-review-board @JimMoen @savonarola
|
||||
/apps/emqx_auth/ @emqx/emqx-review-board @JimMoen
|
||||
/apps/emqx_connector/ @emqx/emqx-review-board @JimMoen
|
||||
/apps/emqx_dashboard/ @emqx/emqx-review-board @JimMoen @lafirest
|
||||
/apps/emqx_dashboard_rbac/ @emqx/emqx-review-board @lafirest
|
||||
/apps/emqx_dashboard_sso/ @emqx/emqx-review-board @JimMoen @lafirest
|
||||
/apps/emqx_exhook/ @emqx/emqx-review-board @JimMoen @HJianBo
|
||||
/apps/emqx_ft/ @emqx/emqx-review-board @savonarola @keynslug
|
||||
/apps/emqx_exhook/ @emqx/emqx-review-board @JimMoen
|
||||
/apps/emqx_gateway/ @emqx/emqx-review-board @lafirest
|
||||
/apps/emqx_management/ @emqx/emqx-review-board @lafirest @sstrigler
|
||||
/apps/emqx_management/ @emqx/emqx-review-board @lafirest
|
||||
/apps/emqx_opentelemetry @emqx/emqx-review-board @SergeTupchiy
|
||||
/apps/emqx_plugins/ @emqx/emqx-review-board @JimMoen
|
||||
/apps/emqx_prometheus/ @emqx/emqx-review-board @JimMoen
|
||||
/apps/emqx_psk/ @emqx/emqx-review-board @lafirest
|
||||
|
@ -20,7 +31,7 @@
|
|||
/apps/emqx_rule_engine/ @emqx/emqx-review-board @kjellwinblad
|
||||
/apps/emqx_slow_subs/ @emqx/emqx-review-board @lafirest
|
||||
/apps/emqx_statsd/ @emqx/emqx-review-board @JimMoen
|
||||
/apps/emqx_durable_storage/ @emqx/emqx-review-board @ieQu1 @keynslug
|
||||
/apps/emqx_durable_storage/ @emqx/emqx-review-board @keynslug
|
||||
|
||||
## CI
|
||||
/deploy/ @emqx/emqx-review-board @Rory-Z
|
||||
|
|
|
@ -33,7 +33,7 @@ runs:
|
|||
HOMEBREW_NO_INSTALL_UPGRADE: 1
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||
run: |
|
||||
brew install curl zip unzip coreutils openssl@1.1
|
||||
brew install curl zip unzip coreutils openssl@1.1 unixodbc
|
||||
echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH
|
||||
echo "/usr/local/bin" >> $GITHUB_PATH
|
||||
echo "emqx_name=${emqx_name}" >> $GITHUB_OUTPUT
|
||||
|
@ -51,12 +51,12 @@ runs:
|
|||
echo "SELF_HOSTED=false" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
esac
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
id: cache
|
||||
if: steps.prepare.outputs.SELF_HOSTED != 'true'
|
||||
with:
|
||||
path: ${{ steps.prepare.outputs.OTP_INSTALL_PATH }}
|
||||
key: otp-install-${{ inputs.otp }}-${{ inputs.os }}-static-ssl-disable-hipe-disable-jit
|
||||
key: otp-install-${{ inputs.otp }}-${{ inputs.os }}-static-ssl-disable-hipe-disable-jit-20240524-1
|
||||
- name: build erlang
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
|
@ -80,9 +80,10 @@ runs:
|
|||
git clone --depth 1 --branch OTP-${{ inputs.otp }} https://github.com/emqx/otp.git "$OTP_SOURCE_PATH"
|
||||
cd "$OTP_SOURCE_PATH"
|
||||
if [ "$(arch)" = arm64 ]; then
|
||||
export CFLAGS="-O2 -g -I$(brew --prefix unixodbc)/include"
|
||||
export LDFLAGS="-L$(brew --prefix unixodbc)/lib"
|
||||
WITH_ODBC="--with-odbc=$(brew --prefix unixodbc)"
|
||||
ODBCHOME="$(brew --prefix unixodbc)"
|
||||
export CFLAGS="-O2 -g -I${ODBCHOME}/include"
|
||||
export LDFLAGS="-L${ODBCHOME}/lib"
|
||||
WITH_ODBC="--with-odbc=${ODBCHOME}"
|
||||
else
|
||||
WITH_ODBC=""
|
||||
fi
|
||||
|
|
|
@ -1,37 +1,21 @@
|
|||
name: 'Prepare jmeter'
|
||||
|
||||
inputs:
|
||||
version-emqx:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
with:
|
||||
name: emqx-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
shell: bash
|
||||
env:
|
||||
PKG_VSN: ${{ inputs.version-emqx }}
|
||||
run: |
|
||||
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
|
||||
with:
|
||||
repository: emqx/emqx-fvt
|
||||
ref: broker-autotest-v5
|
||||
path: scripts
|
||||
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
|
||||
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
|
||||
with:
|
||||
java-version: '8.0.282' # The JDK version to make available on the path.
|
||||
java-package: jdk # (jre, jdk, or jdk+fx) - defaults to jdk
|
||||
architecture: x64 # (x64 or x86) - defaults to x64
|
||||
# https://github.com/actions/setup-java/blob/main/docs/switching-to-v2.md
|
||||
distribution: 'zulu'
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
|
||||
with:
|
||||
name: apache-jmeter.tgz
|
||||
- name: install jmeter
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
*/.github/*
|
|
@ -11,29 +11,48 @@ on:
|
|||
ref:
|
||||
required: false
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
IS_CI: "yes"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
init:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
BUILDER_VSN: ${{ steps.env.outputs.BUILDER_VSN }}
|
||||
OTP_VSN: ${{ steps.env.outputs.OTP_VSN }}
|
||||
ELIXIR_VSN: ${{ steps.env.outputs.ELIXIR_VSN }}
|
||||
BUILDER: ${{ steps.env.outputs.BUILDER }}
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source ./env.sh
|
||||
echo "BUILDER_VSN=$EMQX_BUILDER_VSN" | tee -a "$GITHUB_OUTPUT"
|
||||
echo "OTP_VSN=$OTP_VSN" | tee -a "$GITHUB_OUTPUT"
|
||||
echo "ELIXIR_VSN=$ELIXIR_VSN" | tee -a "$GITHUB_OUTPUT"
|
||||
echo "BUILDER=$EMQX_BUILDER" | tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
sanity-checks:
|
||||
runs-on: ubuntu-22.04
|
||||
container: "ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04"
|
||||
needs: init
|
||||
container: ${{ needs.init.outputs.BUILDER }}
|
||||
outputs:
|
||||
ct-matrix: ${{ steps.matrix.outputs.ct-matrix }}
|
||||
ct-host: ${{ steps.matrix.outputs.ct-host }}
|
||||
ct-docker: ${{ steps.matrix.outputs.ct-docker }}
|
||||
version-emqx: ${{ steps.matrix.outputs.version-emqx }}
|
||||
version-emqx-enterprise: ${{ steps.matrix.outputs.version-emqx-enterprise }}
|
||||
builder: "ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04"
|
||||
builder_vsn: "5.3-2"
|
||||
otp_vsn: "26.2.1-2"
|
||||
elixir_vsn: "1.15.7"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
@ -78,7 +97,8 @@ jobs:
|
|||
MIX_ENV: emqx-enterprise
|
||||
PROFILE: emqx-enterprise
|
||||
run: |
|
||||
mix local.hex --force --if-missing && mix local.rebar --force --if-missing
|
||||
# mix local.hex --force --if-missing && mix local.rebar --force --if-missing
|
||||
mix local.hex 2.0.6 --force --if-missing && mix local.rebar --force --if-missing
|
||||
- name: Check formatting
|
||||
env:
|
||||
MIX_ENV: emqx-enterprise
|
||||
|
@ -91,35 +111,20 @@ jobs:
|
|||
- name: Generate CT Matrix
|
||||
id: matrix
|
||||
run: |
|
||||
APPS="$(./scripts/find-apps.sh --ci)"
|
||||
MATRIX="$(echo "${APPS}" | jq -c '
|
||||
[
|
||||
(.[] | select(.profile == "emqx") | . + {
|
||||
builder: "5.3-2",
|
||||
otp: "26.2.1-2",
|
||||
elixir: "1.15.7"
|
||||
}),
|
||||
(.[] | select(.profile == "emqx-enterprise") | . + {
|
||||
builder: "5.3-2",
|
||||
otp: ["26.2.1-2"][],
|
||||
elixir: "1.15.7"
|
||||
})
|
||||
]
|
||||
')"
|
||||
MATRIX="$(./scripts/find-apps.sh --ci)"
|
||||
echo "${MATRIX}" | jq
|
||||
CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')"
|
||||
CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile}) | unique')"
|
||||
CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')"
|
||||
CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')"
|
||||
echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT
|
||||
echo "ct-host=${CT_HOST}" | tee -a $GITHUB_OUTPUT
|
||||
echo "ct-docker=${CT_DOCKER}" | tee -a $GITHUB_OUTPUT
|
||||
echo "version-emqx=$(./pkg-vsn.sh emqx)" | tee -a $GITHUB_OUTPUT
|
||||
echo "version-emqx-enterprise=$(./pkg-vsn.sh emqx-enterprise)" | tee -a $GITHUB_OUTPUT
|
||||
|
||||
compile:
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral-xl","linux","x64"]') }}
|
||||
container: ${{ needs.sanity-checks.outputs.builder }}
|
||||
container: ${{ needs.init.outputs.BUILDER }}
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -127,8 +132,11 @@ jobs:
|
|||
- emqx
|
||||
- emqx-enterprise
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Work around https://github.com/actions/checkout/issues/766
|
||||
|
@ -144,61 +152,55 @@ jobs:
|
|||
echo "PROFILE=${PROFILE}" | tee -a .env
|
||||
echo "PKG_VSN=$(./pkg-vsn.sh ${PROFILE})" | tee -a .env
|
||||
zip -ryq -x@.github/workflows/.zipignore $PROFILE.zip .
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
path: ${{ matrix.profile }}.zip
|
||||
retention-days: 1
|
||||
retention-days: 7
|
||||
|
||||
run_emqx_app_tests:
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
- compile
|
||||
uses: ./.github/workflows/run_emqx_app_tests.yaml
|
||||
with:
|
||||
builder: ${{ needs.sanity-checks.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
before_ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
|
||||
after_ref: ${{ github.sha }}
|
||||
|
||||
run_test_cases:
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
- compile
|
||||
uses: ./.github/workflows/run_test_cases.yaml
|
||||
with:
|
||||
builder: ${{ needs.sanity-checks.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }}
|
||||
ct-host: ${{ needs.sanity-checks.outputs.ct-host }}
|
||||
ct-docker: ${{ needs.sanity-checks.outputs.ct-docker }}
|
||||
|
||||
static_checks:
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
- compile
|
||||
uses: ./.github/workflows/static_checks.yaml
|
||||
with:
|
||||
builder: ${{ needs.sanity-checks.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
ct-matrix: ${{ needs.sanity-checks.outputs.ct-matrix }}
|
||||
|
||||
build_slim_packages:
|
||||
needs:
|
||||
- sanity-checks
|
||||
uses: ./.github/workflows/build_slim_packages.yaml
|
||||
with:
|
||||
builder: ${{ needs.sanity-checks.outputs.builder }}
|
||||
builder_vsn: ${{ needs.sanity-checks.outputs.builder_vsn }}
|
||||
otp_vsn: ${{ needs.sanity-checks.outputs.otp_vsn }}
|
||||
elixir_vsn: ${{ needs.sanity-checks.outputs.elixir_vsn }}
|
||||
|
||||
build_docker_for_test:
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
uses: ./.github/workflows/build_docker_for_test.yaml
|
||||
with:
|
||||
otp_vsn: ${{ needs.sanity-checks.outputs.otp_vsn }}
|
||||
elixir_vsn: ${{ needs.sanity-checks.outputs.elixir_vsn }}
|
||||
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
|
||||
version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }}
|
||||
|
||||
spellcheck:
|
||||
needs:
|
||||
|
@ -208,41 +210,35 @@ jobs:
|
|||
|
||||
run_conf_tests:
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
- compile
|
||||
uses: ./.github/workflows/run_conf_tests.yaml
|
||||
with:
|
||||
builder: ${{ needs.sanity-checks.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
|
||||
check_deps_integrity:
|
||||
needs:
|
||||
- init
|
||||
- sanity-checks
|
||||
uses: ./.github/workflows/check_deps_integrity.yaml
|
||||
with:
|
||||
builder: ${{ needs.sanity-checks.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
|
||||
run_jmeter_tests:
|
||||
needs:
|
||||
- sanity-checks
|
||||
- build_docker_for_test
|
||||
uses: ./.github/workflows/run_jmeter_tests.yaml
|
||||
with:
|
||||
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
|
||||
|
||||
run_docker_tests:
|
||||
needs:
|
||||
- sanity-checks
|
||||
- build_docker_for_test
|
||||
uses: ./.github/workflows/run_docker_tests.yaml
|
||||
with:
|
||||
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
|
||||
version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }}
|
||||
|
||||
run_helm_tests:
|
||||
needs:
|
||||
- sanity-checks
|
||||
- build_docker_for_test
|
||||
uses: ./.github/workflows/run_helm_tests.yaml
|
||||
with:
|
||||
version-emqx: ${{ needs.sanity-checks.outputs.version-emqx }}
|
||||
version-emqx-enterprise: ${{ needs.sanity-checks.outputs.version-emqx-enterprise }}
|
||||
|
|
|
@ -8,37 +8,64 @@ on:
|
|||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
- 'e*'
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release-5[0-9]'
|
||||
- 'ci/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
IS_CI: 'yes'
|
||||
|
||||
jobs:
|
||||
init:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
BUILDER_VSN: ${{ steps.env.outputs.BUILDER_VSN }}
|
||||
OTP_VSN: ${{ steps.env.outputs.OTP_VSN }}
|
||||
ELIXIR_VSN: ${{ steps.env.outputs.ELIXIR_VSN }}
|
||||
BUILDER: ${{ steps.env.outputs.BUILDER }}
|
||||
BUILD_FROM: ${{ steps.env.outputs.BUILD_FROM }}
|
||||
RUN_FROM: ${{ steps.env.outputs.BUILD_FROM }}
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
echo "BUILDER_VSN=$EMQX_BUILDER_VSN" >> "$GITHUB_OUTPUT"
|
||||
echo "OTP_VSN=$OTP_VSN" >> "$GITHUB_OUTPUT"
|
||||
echo "ELIXIR_VSN=$ELIXIR_VSN" >> "$GITHUB_OUTPUT"
|
||||
echo "BUILDER=$EMQX_BUILDER" >> "$GITHUB_OUTPUT"
|
||||
echo "BUILD_FROM=$EMQX_DOCKER_BUILD_FROM" >> "$GITHUB_OUTPUT"
|
||||
echo "RUN_FROM=$EMQX_DOCKER_RUN_FROM" >> "$GITHUB_OUTPUT"
|
||||
|
||||
prepare:
|
||||
runs-on: ubuntu-22.04
|
||||
container: 'ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04'
|
||||
needs: init
|
||||
container: ${{ needs.init.outputs.BUILDER }}
|
||||
outputs:
|
||||
profile: ${{ steps.parse-git-ref.outputs.profile }}
|
||||
release: ${{ steps.parse-git-ref.outputs.release }}
|
||||
latest: ${{ steps.parse-git-ref.outputs.latest }}
|
||||
version: ${{ steps.parse-git-ref.outputs.version }}
|
||||
ct-matrix: ${{ steps.matrix.outputs.ct-matrix }}
|
||||
ct-host: ${{ steps.matrix.outputs.ct-host }}
|
||||
ct-docker: ${{ steps.matrix.outputs.ct-docker }}
|
||||
builder: 'ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04'
|
||||
builder_vsn: '5.3-2'
|
||||
otp_vsn: '26.2.1-2'
|
||||
elixir_vsn: '1.15.7'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
@ -46,38 +73,22 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
- name: Detect emqx profile and version
|
||||
- name: Detect emqx profile
|
||||
id: parse-git-ref
|
||||
run: |
|
||||
JSON="$(./scripts/parse-git-ref.sh $GITHUB_REF)"
|
||||
PROFILE=$(echo "$JSON" | jq -cr '.profile')
|
||||
RELEASE=$(echo "$JSON" | jq -cr '.release')
|
||||
LATEST=$(echo "$JSON" | jq -cr '.latest')
|
||||
VERSION="$(./pkg-vsn.sh "$PROFILE")"
|
||||
echo "profile=$PROFILE" | tee -a $GITHUB_OUTPUT
|
||||
echo "release=$RELEASE" | tee -a $GITHUB_OUTPUT
|
||||
echo "latest=$LATEST" | tee -a $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" | tee -a $GITHUB_OUTPUT
|
||||
- name: Build matrix
|
||||
id: matrix
|
||||
run: |
|
||||
APPS="$(./scripts/find-apps.sh --ci)"
|
||||
MATRIX="$(echo "${APPS}" | jq -c '
|
||||
[
|
||||
(.[] | select(.profile == "emqx") | . + {
|
||||
builder: "5.3-2",
|
||||
otp: "26.2.1-2",
|
||||
elixir: "1.15.7"
|
||||
}),
|
||||
(.[] | select(.profile == "emqx-enterprise") | . + {
|
||||
builder: "5.3-2",
|
||||
otp: ["26.2.1-2"][],
|
||||
elixir: "1.15.7"
|
||||
})
|
||||
]
|
||||
')"
|
||||
MATRIX="$(./scripts/find-apps.sh --ci)"
|
||||
echo "${MATRIX}" | jq
|
||||
CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile, builder, otp, elixir}) | unique')"
|
||||
CT_MATRIX="$(echo "${MATRIX}" | jq -c 'map({profile}) | unique')"
|
||||
CT_HOST="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "host"))')"
|
||||
CT_DOCKER="$(echo "${MATRIX}" | jq -c 'map(select(.runner == "docker"))')"
|
||||
echo "ct-matrix=${CT_MATRIX}" | tee -a $GITHUB_OUTPUT
|
||||
|
@ -87,47 +98,44 @@ jobs:
|
|||
build_packages:
|
||||
if: needs.prepare.outputs.release == 'true'
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
uses: ./.github/workflows/build_packages.yaml
|
||||
with:
|
||||
profile: ${{ needs.prepare.outputs.profile }}
|
||||
publish: ${{ needs.prepare.outputs.release }}
|
||||
otp_vsn: ${{ needs.prepare.outputs.otp_vsn }}
|
||||
elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
|
||||
builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
|
||||
publish: true
|
||||
otp_vsn: ${{ needs.init.outputs.OTP_VSN }}
|
||||
elixir_vsn: ${{ needs.init.outputs.ELIXIR_VSN }}
|
||||
builder_vsn: ${{ needs.init.outputs.BUILDER_VSN }}
|
||||
secrets: inherit
|
||||
|
||||
build_and_push_docker_images:
|
||||
if: needs.prepare.outputs.release == 'true'
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
uses: ./.github/workflows/build_and_push_docker_images.yaml
|
||||
with:
|
||||
profile: ${{ needs.prepare.outputs.profile }}
|
||||
version: ${{ needs.prepare.outputs.version }}
|
||||
publish: ${{ needs.prepare.outputs.release }}
|
||||
publish: true
|
||||
latest: ${{ needs.prepare.outputs.latest }}
|
||||
otp_vsn: ${{ needs.prepare.outputs.otp_vsn }}
|
||||
elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
|
||||
builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
|
||||
build_from: ${{ needs.init.outputs.BUILD_FROM }}
|
||||
run_from: ${{ needs.init.outputs.RUN_FROM }}
|
||||
secrets: inherit
|
||||
|
||||
build_slim_packages:
|
||||
if: needs.prepare.outputs.release != 'true'
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
uses: ./.github/workflows/build_slim_packages.yaml
|
||||
with:
|
||||
builder: ${{ needs.prepare.outputs.builder }}
|
||||
builder_vsn: ${{ needs.prepare.outputs.builder_vsn }}
|
||||
otp_vsn: ${{ needs.prepare.outputs.otp_vsn }}
|
||||
elixir_vsn: ${{ needs.prepare.outputs.elixir_vsn }}
|
||||
|
||||
compile:
|
||||
if: needs.prepare.outputs.release != 'true'
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
container: ${{ needs.prepare.outputs.builder }}
|
||||
container: ${{ needs.init.outputs.BUILDER }}
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -135,8 +143,11 @@ jobs:
|
|||
- emqx
|
||||
- emqx-enterprise
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
@ -152,7 +163,7 @@ jobs:
|
|||
echo "PROFILE=${PROFILE}" | tee -a .env
|
||||
echo "PKG_VSN=$(./pkg-vsn.sh ${PROFILE})" | tee -a .env
|
||||
zip -ryq -x@.github/workflows/.zipignore $PROFILE.zip .
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
path: ${{ matrix.profile }}.zip
|
||||
|
@ -160,22 +171,23 @@ jobs:
|
|||
|
||||
run_emqx_app_tests:
|
||||
needs:
|
||||
- prepare
|
||||
- init
|
||||
- compile
|
||||
uses: ./.github/workflows/run_emqx_app_tests.yaml
|
||||
with:
|
||||
builder: ${{ needs.prepare.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
before_ref: ${{ github.event.before }}
|
||||
after_ref: ${{ github.sha }}
|
||||
|
||||
run_test_cases:
|
||||
if: needs.prepare.outputs.release != 'true'
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
- compile
|
||||
uses: ./.github/workflows/run_test_cases.yaml
|
||||
with:
|
||||
builder: ${{ needs.prepare.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
ct-matrix: ${{ needs.prepare.outputs.ct-matrix }}
|
||||
ct-host: ${{ needs.prepare.outputs.ct-host }}
|
||||
ct-docker: ${{ needs.prepare.outputs.ct-docker }}
|
||||
|
@ -183,18 +195,20 @@ jobs:
|
|||
run_conf_tests:
|
||||
if: needs.prepare.outputs.release != 'true'
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
- compile
|
||||
uses: ./.github/workflows/run_conf_tests.yaml
|
||||
with:
|
||||
builder: ${{ needs.prepare.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
|
||||
static_checks:
|
||||
if: needs.prepare.outputs.release != 'true'
|
||||
needs:
|
||||
- init
|
||||
- prepare
|
||||
- compile
|
||||
uses: ./.github/workflows/static_checks.yaml
|
||||
with:
|
||||
builder: ${{ needs.prepare.outputs.builder }}
|
||||
builder: ${{ needs.init.outputs.BUILDER }}
|
||||
ct-matrix: ${{ needs.prepare.outputs.ct-matrix }}
|
||||
|
|
|
@ -10,22 +10,16 @@ on:
|
|||
profile:
|
||||
required: true
|
||||
type: string
|
||||
version:
|
||||
required: true
|
||||
type: string
|
||||
latest:
|
||||
required: true
|
||||
type: string
|
||||
publish:
|
||||
required: true
|
||||
type: string
|
||||
otp_vsn:
|
||||
type: boolean
|
||||
build_from:
|
||||
required: true
|
||||
type: string
|
||||
elixir_vsn:
|
||||
required: true
|
||||
type: string
|
||||
builder_vsn:
|
||||
run_from:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
|
@ -45,8 +39,6 @@ on:
|
|||
required: false
|
||||
type: string
|
||||
default: 'emqx'
|
||||
version:
|
||||
required: true
|
||||
latest:
|
||||
required: false
|
||||
type: boolean
|
||||
|
@ -55,25 +47,22 @@ on:
|
|||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
otp_vsn:
|
||||
build_from:
|
||||
required: false
|
||||
type: string
|
||||
default: '26.2.1-2'
|
||||
elixir_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '1.15.7'
|
||||
builder_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '5.3-2'
|
||||
default: ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-debian12
|
||||
run_from:
|
||||
default: public.ecr.aws/debian/debian:stable-20240612-slim
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
build:
|
||||
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.arch)) || 'ubuntu-22.04' }}
|
||||
container: ${{ inputs.build_from }}
|
||||
outputs:
|
||||
PKG_VSN: ${{ steps.build.outputs.PKG_VSN }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -81,54 +70,141 @@ jobs:
|
|||
profile:
|
||||
- ${{ inputs.profile }}
|
||||
- ${{ inputs.profile }}-elixir
|
||||
registry:
|
||||
- 'docker.io'
|
||||
- 'public.ecr.aws'
|
||||
exclude:
|
||||
- profile: emqx-enterprise
|
||||
registry: 'public.ecr.aws'
|
||||
- profile: emqx-enterprise-elixir
|
||||
registry: 'public.ecr.aws'
|
||||
arch:
|
||||
- x64
|
||||
- arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
- run: git config --global --add safe.directory "$PWD"
|
||||
- name: build release tarball
|
||||
id: build
|
||||
run: |
|
||||
make ${{ matrix.profile }}-tgz
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: "${{ matrix.profile }}-${{ matrix.arch }}.tar.gz"
|
||||
path: "_packages/emqx*/emqx-*.tar.gz"
|
||||
retention-days: 7
|
||||
overwrite: true
|
||||
if-no-files-found: error
|
||||
|
||||
- uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
||||
- uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
docker:
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
needs:
|
||||
- build
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
- name: Login to hub.docker.com
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
if: matrix.registry == 'docker.io'
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
profile:
|
||||
- ["${{ inputs.profile }}", "${{ inputs.profile == 'emqx' && 'docker.io,public.ecr.aws' || 'docker.io' }}"]
|
||||
- ["${{ inputs.profile }}-elixir", "${{ inputs.profile == 'emqx' && 'docker.io,public.ecr.aws' || 'docker.io' }}"]
|
||||
|
||||
- name: Login to AWS ECR
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
if: matrix.registry == 'public.ecr.aws'
|
||||
with:
|
||||
registry: public.ecr.aws
|
||||
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
ecr: true
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
pattern: "${{ matrix.profile[0] }}-*.tar.gz"
|
||||
path: _packages
|
||||
merge-multiple: true
|
||||
|
||||
- name: Build docker image
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
DOCKER_REGISTRY: ${{ matrix.registry }}
|
||||
DOCKER_ORG: ${{ github.repository_owner }}
|
||||
DOCKER_LATEST: ${{ inputs.latest }}
|
||||
DOCKER_PUSH: ${{ inputs.publish == 'true' || inputs.publish || github.repository_owner != 'emqx' }}
|
||||
DOCKER_BUILD_NOCACHE: true
|
||||
DOCKER_PLATFORMS: linux/amd64,linux/arm64
|
||||
EMQX_RUNNER: 'debian:11-slim'
|
||||
EMQX_DOCKERFILE: 'deploy/docker/Dockerfile'
|
||||
PKG_VSN: ${{ inputs.version }}
|
||||
EMQX_BUILDER_VSN: ${{ inputs.builder_vsn }}
|
||||
EMQX_OTP_VSN: ${{ inputs.otp_vsn }}
|
||||
EMQX_ELIXIR_VSN: ${{ inputs.elixir_vsn }}
|
||||
run: |
|
||||
./build ${PROFILE} docker
|
||||
- name: Move artifacts to root directory
|
||||
env:
|
||||
PROFILE: ${{ inputs.profile }}
|
||||
run: |
|
||||
ls -lR _packages/$PROFILE
|
||||
mv _packages/$PROFILE/*.tar.gz ./
|
||||
|
||||
- name: Enable containerd image store on Docker Engine
|
||||
run: |
|
||||
echo "$(sudo cat /etc/docker/daemon.json | jq '. += {"features": {"containerd-snapshotter": true}}')" > daemon.json
|
||||
sudo mv daemon.json /etc/docker/daemon.json
|
||||
sudo systemctl restart docker
|
||||
|
||||
- uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
|
||||
- uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1
|
||||
|
||||
- name: Login to hub.docker.com
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
if: inputs.publish && contains(matrix.profile[1], 'docker.io')
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
|
||||
- name: Login to AWS ECR
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
if: inputs.publish && contains(matrix.profile[1], 'public.ecr.aws')
|
||||
with:
|
||||
registry: public.ecr.aws
|
||||
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
ecr: true
|
||||
|
||||
- name: Build docker image for smoke test
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile[0] }}
|
||||
DOCKER_REGISTRY: ${{ matrix.profile[1] }}
|
||||
DOCKER_ORG: ${{ github.repository_owner }}
|
||||
DOCKER_LATEST: ${{ inputs.latest }}
|
||||
DOCKER_PUSH: false
|
||||
DOCKER_BUILD_NOCACHE: true
|
||||
BUILD_FROM: ${{ inputs.build_from }}
|
||||
RUN_FROM: ${{ inputs.run_from }}
|
||||
PKG_VSN: ${{ needs.build.outputs.PKG_VSN }}
|
||||
EMQX_SOURCE_TYPE: tgz
|
||||
run: |
|
||||
./build ${PROFILE} docker
|
||||
echo "Built tags:"
|
||||
echo "==========="
|
||||
cat .emqx_docker_image_tags
|
||||
echo "==========="
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$(head -n 1 .emqx_docker_image_tags)" >> $GITHUB_ENV
|
||||
|
||||
- name: smoke test
|
||||
timeout-minutes: 1
|
||||
run: |
|
||||
for tag in $(cat .emqx_docker_image_tags); do
|
||||
CID=$(docker run -d -p 18083:18083 $tag)
|
||||
HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
|
||||
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
|
||||
docker rm -f $CID
|
||||
done
|
||||
- name: dashboard tests
|
||||
working-directory: ./scripts/ui-tests
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
set -eu
|
||||
docker compose up --abort-on-container-exit --exit-code-from selenium
|
||||
docker compose rm -fsv
|
||||
- name: test node_dump
|
||||
run: |
|
||||
CID=$(docker run -d -P $_EMQX_DOCKER_IMAGE_TAG)
|
||||
docker exec -t -u root -w /root $CID bash -c 'apt-get -y update && apt-get -y install net-tools'
|
||||
docker exec -t -u root $CID node_dump
|
||||
docker rm -f $CID
|
||||
|
||||
- name: Build and push docker image
|
||||
if: inputs.publish || github.repository_owner != 'emqx'
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile[0] }}
|
||||
DOCKER_REGISTRY: ${{ matrix.profile[1] }}
|
||||
DOCKER_ORG: ${{ github.repository_owner }}
|
||||
DOCKER_LATEST: ${{ inputs.latest }}
|
||||
DOCKER_PUSH: true
|
||||
DOCKER_BUILD_NOCACHE: false
|
||||
DOCKER_PLATFORMS: linux/amd64,linux/arm64
|
||||
DOCKER_LOAD: false
|
||||
BUILD_FROM: ${{ inputs.build_from }}
|
||||
RUN_FROM: ${{ inputs.run_from }}
|
||||
PKG_VSN: ${{ needs.build.outputs.PKG_VSN }}
|
||||
EMQX_SOURCE_TYPE: tgz
|
||||
run: |
|
||||
./build ${PROFILE} docker
|
||||
|
|
|
@ -6,19 +6,6 @@ concurrency:
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
otp_vsn:
|
||||
required: true
|
||||
type: string
|
||||
elixir_vsn:
|
||||
required: true
|
||||
type: string
|
||||
version-emqx:
|
||||
required: true
|
||||
type: string
|
||||
version-emqx-enterprise:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -28,9 +15,6 @@ jobs:
|
|||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
env:
|
||||
EMQX_NAME: ${{ matrix.profile }}
|
||||
PKG_VSN: ${{ startsWith(matrix.profile, 'emqx-enterprise') && inputs.version-emqx-enterprise || inputs.version-emqx }}
|
||||
OTP_VSN: ${{ inputs.otp_vsn }}
|
||||
ELIXIR_VSN: ${{ inputs.elixir_vsn }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -42,22 +26,32 @@ jobs:
|
|||
- emqx-enterprise-elixir
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- name: build and export to Docker
|
||||
id: build
|
||||
run: |
|
||||
make ${EMQX_NAME}-docker
|
||||
echo "EMQX_IMAGE_TAG=$(cat .docker_image_tag)" >> $GITHUB_ENV
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$(head -n 1 .emqx_docker_image_tags)" >> $GITHUB_ENV
|
||||
- name: smoke test
|
||||
run: |
|
||||
CID=$(docker run -d --rm -P $EMQX_IMAGE_TAG)
|
||||
CID=$(docker run -d --rm -P $_EMQX_DOCKER_IMAGE_TAG)
|
||||
HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' $CID)
|
||||
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
|
||||
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT || {
|
||||
docker logs $CID
|
||||
exit 1
|
||||
}
|
||||
docker stop $CID
|
||||
- name: export docker image
|
||||
if: always()
|
||||
run: |
|
||||
docker save $EMQX_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
docker save $_EMQX_DOCKER_IMAGE_TAG | gzip > $EMQX_NAME-docker-$PKG_VSN.tar.gz
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: "${{ env.EMQX_NAME }}-docker"
|
||||
path: "${{ env.EMQX_NAME }}-docker-${{ env.PKG_VSN }}.tar.gz"
|
||||
|
|
|
@ -12,7 +12,7 @@ on:
|
|||
type: string
|
||||
publish:
|
||||
required: true
|
||||
type: string
|
||||
type: boolean
|
||||
otp_vsn:
|
||||
required: true
|
||||
type: string
|
||||
|
@ -46,7 +46,8 @@ on:
|
|||
ref:
|
||||
required: false
|
||||
profile:
|
||||
required: false
|
||||
required: true
|
||||
default: 'emqx'
|
||||
publish:
|
||||
required: false
|
||||
type: boolean
|
||||
|
@ -54,7 +55,7 @@ on:
|
|||
otp_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '26.2.1-2'
|
||||
default: '26.2.5-3'
|
||||
elixir_vsn:
|
||||
required: false
|
||||
type: string
|
||||
|
@ -62,7 +63,7 @@ on:
|
|||
builder_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '5.3-2'
|
||||
default: '5.3-9'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -74,15 +75,14 @@ jobs:
|
|||
matrix:
|
||||
profile:
|
||||
- ${{ inputs.profile }}
|
||||
os:
|
||||
- macos-13
|
||||
- macos-14
|
||||
otp:
|
||||
- ${{ inputs.otp_vsn }}
|
||||
os:
|
||||
- macos-12
|
||||
- macos-12-arm64
|
||||
- macos-13
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
@ -95,107 +95,94 @@ jobs:
|
|||
apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }}
|
||||
apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }}
|
||||
apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }}
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: ${{ matrix.profile }}-${{ matrix.otp }}-${{ matrix.os }}
|
||||
name: ${{ matrix.profile }}-${{ matrix.os }}-${{ matrix.otp }}
|
||||
path: _packages/${{ matrix.profile }}/
|
||||
retention-days: 7
|
||||
compression-level: 0
|
||||
|
||||
linux:
|
||||
runs-on: [self-hosted, ephemeral, linux, "${{ matrix.arch }}"]
|
||||
# always run in builder container because the host might have the wrong OTP version etc.
|
||||
# otherwise buildx.sh does not run docker if arch and os matches the target arch and os.
|
||||
container:
|
||||
image: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-${{ matrix.os }}"
|
||||
|
||||
runs-on: [self-hosted, ephemeral, linux, "${{ matrix.arch == 'arm64' && 'arm64' || 'x64' }}"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
profile:
|
||||
- ${{ inputs.profile }}
|
||||
otp:
|
||||
- ${{ inputs.otp_vsn }}
|
||||
arch:
|
||||
- x64
|
||||
- arm64
|
||||
os:
|
||||
- ubuntu24.04
|
||||
- ubuntu22.04
|
||||
- ubuntu20.04
|
||||
- ubuntu18.04
|
||||
- debian12
|
||||
- debian11
|
||||
- debian10
|
||||
- el9
|
||||
- el8
|
||||
- el7
|
||||
- amzn2
|
||||
- amzn2023
|
||||
arch:
|
||||
- amd64
|
||||
- arm64
|
||||
with_elixir:
|
||||
- 'no'
|
||||
otp:
|
||||
- ${{ inputs.otp_vsn }}
|
||||
builder:
|
||||
- ${{ inputs.builder_vsn }}
|
||||
elixir:
|
||||
- ${{ inputs.elixir_vsn }}
|
||||
with_elixir:
|
||||
- 'no'
|
||||
include:
|
||||
- profile: emqx
|
||||
otp: ${{ inputs.otp_vsn }}
|
||||
arch: x64
|
||||
- profile: ${{ inputs.profile }}
|
||||
os: ubuntu22.04
|
||||
arch: amd64
|
||||
with_elixir: 'yes'
|
||||
otp: ${{ inputs.otp_vsn }}
|
||||
builder: ${{ inputs.builder_vsn }}
|
||||
elixir: ${{ inputs.elixir_vsn }}
|
||||
with_elixir: 'yes'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: fix workdir
|
||||
run: |
|
||||
set -eu
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
# Align path for CMake caches
|
||||
if [ ! "$PWD" = "/emqx" ]; then
|
||||
ln -s $PWD /emqx
|
||||
cd /emqx
|
||||
fi
|
||||
echo "pwd is $PWD"
|
||||
|
||||
- name: build emqx packages
|
||||
- name: build tgz
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
OS: ${{ matrix.os }}
|
||||
IS_ELIXIR: ${{ matrix.with_elixir }}
|
||||
ACLOCAL_PATH: "/usr/share/aclocal:/usr/local/share/aclocal"
|
||||
BUILDER: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-${{ matrix.os }}"
|
||||
BUILDER_SYSTEM: force_docker
|
||||
run: |
|
||||
set -eu
|
||||
if [ "${IS_ELIXIR:-}" == 'yes' ]; then
|
||||
make "${PROFILE}-elixir-tgz"
|
||||
else
|
||||
make "${PROFILE}-tgz"
|
||||
make "${PROFILE}-pkg"
|
||||
fi
|
||||
- name: test emqx packages
|
||||
./scripts/buildx.sh \
|
||||
--profile $PROFILE \
|
||||
--arch $ARCH \
|
||||
--builder $BUILDER \
|
||||
--elixir $IS_ELIXIR \
|
||||
--pkgtype tgz
|
||||
- name: build pkg
|
||||
if: matrix.with_elixir == 'no'
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
OS: ${{ matrix.os }}
|
||||
IS_ELIXIR: ${{ matrix.with_elixir }}
|
||||
BUILDER: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-${{ matrix.os }}"
|
||||
BUILDER_SYSTEM: force_docker
|
||||
run: |
|
||||
set -eu
|
||||
if [ "${IS_ELIXIR:-}" == 'yes' ]; then
|
||||
./scripts/pkg-tests.sh "${PROFILE}-elixir-tgz"
|
||||
else
|
||||
./scripts/pkg-tests.sh "${PROFILE}-tgz"
|
||||
./scripts/pkg-tests.sh "${PROFILE}-pkg"
|
||||
fi
|
||||
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
./scripts/buildx.sh \
|
||||
--profile $PROFILE \
|
||||
--arch $ARCH \
|
||||
--builder $BUILDER \
|
||||
--elixir $IS_ELIXIR \
|
||||
--pkgtype pkg
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: ${{ matrix.profile }}-${{ matrix.otp }}-${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.with_elixir == 'yes' && 'elixir' || 'erlang' }}
|
||||
name: ${{ matrix.profile }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.with_elixir == 'yes' && '-elixir' || '' }}-${{ matrix.builder }}-${{ matrix.otp }}-${{ matrix.elixir }}
|
||||
path: _packages/${{ matrix.profile }}/
|
||||
retention-days: 7
|
||||
|
||||
|
@ -204,30 +191,19 @@ jobs:
|
|||
needs:
|
||||
- mac
|
||||
- linux
|
||||
if: inputs.publish == 'true' || inputs.publish
|
||||
if: inputs.publish
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
profile:
|
||||
- ${{ inputs.profile }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
pattern: ${{ matrix.profile }}-*
|
||||
pattern: "${{ matrix.profile }}-*"
|
||||
path: packages/${{ matrix.profile }}
|
||||
- name: install dos2unix
|
||||
run: sudo apt-get update -y && sudo apt install -y dos2unix
|
||||
- name: get packages
|
||||
run: |
|
||||
set -eu
|
||||
cd packages/${{ matrix.profile }}
|
||||
# fix the .sha256 file format
|
||||
for var in $(ls | grep emqx | grep -v sha256); do
|
||||
dos2unix $var.sha256
|
||||
echo "$(cat $var.sha256) $var" | sha256sum -c || exit 1
|
||||
done
|
||||
cd -
|
||||
- uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
merge-multiple: true
|
||||
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
|
@ -235,6 +211,9 @@ jobs:
|
|||
- name: upload to aws s3
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
REF_NAME: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.ref_name }}
|
||||
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
|
||||
AWS_CLOUDFRONT_ID: ${{ secrets.AWS_CLOUDFRONT_ID }}
|
||||
run: |
|
||||
set -eu
|
||||
if [ $PROFILE = 'emqx' ]; then
|
||||
|
@ -245,5 +224,5 @@ jobs:
|
|||
echo "unknown profile $PROFILE"
|
||||
exit 1
|
||||
fi
|
||||
aws s3 cp --recursive packages/$PROFILE s3://${{ secrets.AWS_S3_BUCKET }}/$s3dir/${{ github.ref_name }}
|
||||
aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_ID }} --paths "/$s3dir/${{ github.ref_name }}/*"
|
||||
aws s3 cp --recursive packages/$PROFILE s3://$AWS_S3_BUCKET/$s3dir/$REF_NAME
|
||||
aws cloudfront create-invalidation --distribution-id "$AWS_CLOUDFRONT_ID" --paths "/$s3dir/$REF_NAME/*"
|
||||
|
|
|
@ -16,64 +16,52 @@ jobs:
|
|||
linux:
|
||||
if: github.repository_owner == 'emqx'
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
container:
|
||||
image: "ghcr.io/emqx/emqx-builder/${{ matrix.profile[2] }}-${{ matrix.os }}"
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
profile:
|
||||
- ['emqx', 'master', '5.3-2:1.15.7-26.2.1-2']
|
||||
- ['emqx-enterprise', 'release-55', '5.3-2:1.15.7-25.3.2-2']
|
||||
- ['emqx', 'master']
|
||||
- ['emqx', 'release-57']
|
||||
- ['emqx', 'release-58']
|
||||
os:
|
||||
- debian10
|
||||
- ubuntu22.04
|
||||
- amzn2023
|
||||
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile[0] }}
|
||||
OS: ${{ matrix.os }}
|
||||
BUILDER_SYSTEM: force_docker
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ matrix.profile[1] }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: fix workdir
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
set -eu
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
# Align path for CMake caches
|
||||
if [ ! "$PWD" = "/emqx" ]; then
|
||||
ln -s $PWD /emqx
|
||||
cd /emqx
|
||||
fi
|
||||
echo "pwd is $PWD"
|
||||
|
||||
- name: build emqx packages
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile[0] }}
|
||||
ACLOCAL_PATH: "/usr/share/aclocal:/usr/local/share/aclocal"
|
||||
source env.sh
|
||||
BUILDER="ghcr.io/emqx/emqx-builder/${EMQX_BUILDER_VSN}:${ELIXIR_VSN}-${OTP_VSN}-${OS}"
|
||||
echo "BUILDER=$BUILDER" >> "$GITHUB_ENV"
|
||||
- name: build tgz
|
||||
run: |
|
||||
set -eu
|
||||
make "${PROFILE}-tgz"
|
||||
make "${PROFILE}-pkg"
|
||||
- name: test emqx packages
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile[0] }}
|
||||
./scripts/buildx.sh --profile "$PROFILE" --pkgtype tgz --builder "$BUILDER"
|
||||
- name: build pkg
|
||||
run: |
|
||||
set -eu
|
||||
./scripts/pkg-tests.sh "${PROFILE}-tgz"
|
||||
./scripts/pkg-tests.sh "${PROFILE}-pkg"
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
./scripts/buildx.sh --profile "$PROFILE" --pkgtype pkg --builder "$BUILDER"
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: ${{ matrix.profile[0] }}-${{ matrix.os }}
|
||||
name: ${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.os }}
|
||||
path: _packages/${{ matrix.profile[0] }}/
|
||||
retention-days: 7
|
||||
- name: Send notification to Slack
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
|
@ -92,33 +80,36 @@ jobs:
|
|||
- emqx
|
||||
branch:
|
||||
- master
|
||||
otp:
|
||||
- 26.2.1-2
|
||||
os:
|
||||
- macos-12-arm64
|
||||
- macos-14-arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ matrix.branch }}
|
||||
fetch-depth: 0
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
echo "OTP_VSN=$OTP_VSN" >> "$GITHUB_OUTPUT"
|
||||
- uses: ./.github/actions/package-macos
|
||||
with:
|
||||
profile: ${{ matrix.profile }}
|
||||
otp: ${{ matrix.otp }}
|
||||
otp: ${{ steps.env.outputs.OTP_VSN }}
|
||||
os: ${{ matrix.os }}
|
||||
apple_id_password: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }}
|
||||
apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }}
|
||||
apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }}
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: ${{ matrix.profile }}-${{ matrix.os }}
|
||||
path: _packages/${{ matrix.profile }}/
|
||||
retention-days: 7
|
||||
- name: Send notification to Slack
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
|
|
|
@ -6,97 +6,50 @@ concurrency:
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
builder:
|
||||
required: true
|
||||
type: string
|
||||
builder_vsn:
|
||||
required: true
|
||||
type: string
|
||||
otp_vsn:
|
||||
required: true
|
||||
type: string
|
||||
elixir_vsn:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
required: false
|
||||
builder:
|
||||
required: false
|
||||
type: string
|
||||
default: 'ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04'
|
||||
builder_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '5.3-2'
|
||||
otp_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '26.2.1-2'
|
||||
elixir_vsn:
|
||||
required: false
|
||||
type: string
|
||||
default: '1.15.7'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.profile[4])) || 'ubuntu-22.04' }}
|
||||
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON(format('["self-hosted","ephemeral","linux","{0}"]', matrix.profile[2])) || 'ubuntu-22.04' }}
|
||||
env:
|
||||
EMQX_NAME: ${{ matrix.profile[0] }}
|
||||
PROFILE: ${{ matrix.profile[0] }}
|
||||
ELIXIR: ${{ matrix.profile[1] == 'elixir' && 'yes' || 'no' }}
|
||||
ARCH: ${{ matrix.profile[2] == 'x64' && 'amd64' || 'arm64' }}
|
||||
BUILDER_SYSTEM: force_docker
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
profile:
|
||||
- ["emqx", "26.2.1-2", "ubuntu22.04", "elixir", "x64"]
|
||||
- ["emqx", "26.2.1-2", "ubuntu22.04", "elixir", "arm64"]
|
||||
- ["emqx-enterprise", "26.2.1-2", "ubuntu22.04", "erlang", "x64"]
|
||||
|
||||
container: "ghcr.io/emqx/emqx-builder/${{ inputs.builder_vsn }}:${{ inputs.elixir_vsn }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}"
|
||||
- ["emqx", "elixir", "x64"]
|
||||
- ["emqx", "elixir", "arm64"]
|
||||
- ["emqx-enterprise", "erlang", "x64"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Work around https://github.com/actions/checkout/issues/766
|
||||
- name: build tgz
|
||||
run: |
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
echo "CODE_PATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV
|
||||
- name: build and test tgz package
|
||||
if: matrix.profile[3] == 'erlang'
|
||||
./scripts/buildx.sh --profile $PROFILE --pkgtype tgz --elixir $ELIXIR --arch $ARCH
|
||||
- name: build pkg
|
||||
run: |
|
||||
make ${EMQX_NAME}-tgz
|
||||
./scripts/pkg-tests.sh ${EMQX_NAME}-tgz
|
||||
- name: build and test deb/rpm packages
|
||||
if: matrix.profile[3] == 'erlang'
|
||||
run: |
|
||||
make ${EMQX_NAME}-pkg
|
||||
./scripts/pkg-tests.sh ${EMQX_NAME}-pkg
|
||||
- name: build and test tgz package (Elixir)
|
||||
if: matrix.profile[3] == 'elixir'
|
||||
run: |
|
||||
make ${EMQX_NAME}-elixir-tgz
|
||||
./scripts/pkg-tests.sh ${EMQX_NAME}-elixir-tgz
|
||||
- name: build and test deb/rpm packages (Elixir)
|
||||
if: matrix.profile[3] == 'elixir'
|
||||
run: |
|
||||
make ${EMQX_NAME}-elixir-pkg
|
||||
./scripts/pkg-tests.sh ${EMQX_NAME}-elixir-pkg
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
./scripts/buildx.sh --profile $PROFILE --pkgtype pkg --elixir $ELIXIR --arch $ARCH
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: "${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}-${{ matrix.profile[3] }}-${{ matrix.profile[4] }}"
|
||||
name: "${{ matrix.profile[0] }}-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}"
|
||||
path: _packages/${{ matrix.profile[0] }}/*
|
||||
retention-days: 7
|
||||
compression-level: 0
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: "${{ matrix.profile[0] }}-schema-dump-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}-${{ matrix.profile[3] }}-${{ matrix.profile[4] }}"
|
||||
name: "${{ matrix.profile[0] }}-schema-dump-${{ matrix.profile[1] }}-${{ matrix.profile[2] }}"
|
||||
path: |
|
||||
scripts/spellcheck
|
||||
_build/docgen/${{ matrix.profile[0] }}/schema-en.json
|
||||
|
@ -108,27 +61,30 @@ jobs:
|
|||
matrix:
|
||||
profile:
|
||||
- emqx
|
||||
otp:
|
||||
- ${{ inputs.otp_vsn }}
|
||||
os:
|
||||
- macos-12-arm64
|
||||
- macos-14-arm64
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
EMQX_NAME: ${{ matrix.profile }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
echo "OTP_VSN=$OTP_VSN" >> "$GITHUB_OUTPUT"
|
||||
- uses: ./.github/actions/package-macos
|
||||
with:
|
||||
profile: ${{ matrix.profile }}
|
||||
otp: ${{ matrix.otp }}
|
||||
otp: ${{ steps.env.outputs.OTP_VSN }}
|
||||
os: ${{ matrix.os }}
|
||||
apple_id_password: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
apple_developer_identity: ${{ secrets.APPLE_DEVELOPER_IDENTITY }}
|
||||
apple_developer_id_bundle: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }}
|
||||
apple_developer_id_bundle_password: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }}
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: ${{ matrix.os }}
|
||||
path: _packages/**/*
|
||||
|
|
|
@ -14,32 +14,33 @@ jobs:
|
|||
check_deps_integrity:
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
container: ${{ inputs.builder }}
|
||||
env:
|
||||
MIX_ENV: ${{ matrix.profile }}
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
strategy:
|
||||
matrix:
|
||||
profile:
|
||||
- emqx-enterprise
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
- run: make ensure-rebar3
|
||||
- run: ./scripts/check-deps-integrity.escript
|
||||
- name: Setup mix
|
||||
env:
|
||||
MIX_ENV: emqx-enterprise
|
||||
PROFILE: emqx-enterprise
|
||||
run: |
|
||||
mix local.hex --force
|
||||
# mix local.hex --force
|
||||
mix local.hex 2.0.6 --force
|
||||
mix local.rebar --force
|
||||
mix deps.get
|
||||
- name: print mix dependency tree
|
||||
run: mix deps.tree
|
||||
- run: ./scripts/check-elixir-deps-discrepancies.exs
|
||||
env:
|
||||
MIX_ENV: emqx-enterprise
|
||||
PROFILE: emqx-enterprise
|
||||
- run: ./scripts/check-elixir-applications.exs
|
||||
env:
|
||||
MIX_ENV: emqx-enterprise
|
||||
PROFILE: emqx-enterprise
|
||||
- name: Upload produced lock files
|
||||
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: produced_lock_files
|
||||
name: ${{ matrix.profile }}_produced_lock_files
|
||||
path: |
|
||||
mix.lock
|
||||
rebar.lock
|
||||
|
|
|
@ -10,36 +10,31 @@ permissions:
|
|||
|
||||
jobs:
|
||||
analyze:
|
||||
if: github.repository == 'emqx/emqx'
|
||||
name: Analyze
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 360
|
||||
permissions:
|
||||
actions: read
|
||||
security-events: write
|
||||
container:
|
||||
image: ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branch:
|
||||
- master
|
||||
- release-55
|
||||
- release-57
|
||||
- release-58
|
||||
language:
|
||||
- cpp
|
||||
- python
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ matrix.branch }}
|
||||
|
||||
- name: Ensure git safe dir
|
||||
run: |
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
make ensure-rebar3
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.15.5
|
||||
with:
|
||||
|
@ -50,14 +45,7 @@ jobs:
|
|||
env:
|
||||
PROFILE: emqx-enterprise
|
||||
run: |
|
||||
make emqx-enterprise-compile
|
||||
|
||||
- name: Fetch deps
|
||||
if: matrix.language == 'python'
|
||||
env:
|
||||
PROFILE: emqx-enterprise
|
||||
run: |
|
||||
make deps-emqx-enterprise
|
||||
./scripts/buildx.sh --profile emqx-enterprise --pkgtype rel
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.15.5
|
||||
|
|
|
@ -7,9 +7,6 @@ on:
|
|||
# run hourly
|
||||
- cron: "0 * * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -17,22 +14,30 @@ permissions:
|
|||
jobs:
|
||||
rerun-failed-jobs:
|
||||
if: github.repository_owner == 'emqx'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: read
|
||||
actions: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ref:
|
||||
- master
|
||||
- release-57
|
||||
- release-58
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref || 'master' }}
|
||||
ref: ${{ matrix.ref }}
|
||||
|
||||
- name: run script
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPO: ${{ github.repository }}
|
||||
run: |
|
||||
gh api --method GET -f head_sha=$(git rev-parse HEAD) -f status=completed -f exclude_pull_requests=true /repos/emqx/emqx/actions/runs > runs.json
|
||||
for id in $(jq -r '.workflow_runs[] | select((."conclusion" != "success") and .run_attempt < 3) | .id' runs.json); do
|
||||
echo "rerun https://github.com/emqx/emqx/actions/runs/$id"
|
||||
gh api --method POST /repos/emqx/emqx/actions/runs/$id/rerun-failed-jobs
|
||||
gh api --method GET -f head_sha=$(git rev-parse HEAD) -f status=completed -f exclude_pull_requests=true /repos/${GITHUB_REPO}/actions/runs > runs.json
|
||||
for id in $(jq -r '.workflow_runs[] | select((."conclusion" == "failure") and (."name" != "Keep master green") and .run_attempt < 3) | .id' runs.json); do
|
||||
echo "rerun https://github.com/${GITHUB_REPO}/actions/runs/$id"
|
||||
gh api --method POST /repos/${GITHUB_REPO}/actions/runs/$id/rerun-failed-jobs || true
|
||||
done
|
||||
|
|
|
@ -26,13 +26,13 @@ jobs:
|
|||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'emqx'
|
||||
container: ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-ubuntu20.04
|
||||
container: ghcr.io/emqx/emqx-builder/5.3-9:1.15.7-26.2.5-3-ubuntu20.04
|
||||
outputs:
|
||||
BENCH_ID: ${{ steps.prepare.outputs.BENCH_ID }}
|
||||
PACKAGE_FILE: ${{ steps.package_file.outputs.PACKAGE_FILE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
|
@ -52,7 +52,7 @@ jobs:
|
|||
id: package_file
|
||||
run: |
|
||||
echo "PACKAGE_FILE=$(find _packages/emqx -name 'emqx-*.deb' | head -n 1 | xargs basename)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: emqx-ubuntu20.04
|
||||
path: _packages/emqx/${{ steps.package_file.outputs.PACKAGE_FILE }}
|
||||
|
@ -66,23 +66,23 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_PERF_TEST }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
|
||||
aws-region: eu-west-1
|
||||
- name: Checkout tf-emqx-performance-test
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: emqx/tf-emqx-performance-test
|
||||
path: tf-emqx-performance-test
|
||||
ref: v0.2.3
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: emqx-ubuntu20.04
|
||||
path: tf-emqx-performance-test/
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0
|
||||
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
- name: run scenario
|
||||
|
@ -105,7 +105,7 @@ jobs:
|
|||
terraform destroy -auto-approve
|
||||
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
|
||||
- name: Send notification to Slack
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
with:
|
||||
payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
|
||||
- name: terraform destroy
|
||||
|
@ -113,13 +113,13 @@ jobs:
|
|||
working-directory: ./tf-emqx-performance-test
|
||||
run: |
|
||||
terraform destroy -auto-approve
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: metrics
|
||||
path: |
|
||||
"./tf-emqx-performance-test/*.tar.gz"
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: terraform
|
||||
|
@ -137,23 +137,23 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_PERF_TEST }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
|
||||
aws-region: eu-west-1
|
||||
- name: Checkout tf-emqx-performance-test
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: emqx/tf-emqx-performance-test
|
||||
path: tf-emqx-performance-test
|
||||
ref: v0.2.3
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: emqx-ubuntu20.04
|
||||
path: tf-emqx-performance-test/
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0
|
||||
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
- name: run scenario
|
||||
|
@ -176,7 +176,7 @@ jobs:
|
|||
terraform destroy -auto-approve
|
||||
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
|
||||
- name: Send notification to Slack
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
with:
|
||||
payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
|
||||
- name: terraform destroy
|
||||
|
@ -184,13 +184,13 @@ jobs:
|
|||
working-directory: ./tf-emqx-performance-test
|
||||
run: |
|
||||
terraform destroy -auto-approve
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: metrics
|
||||
path: |
|
||||
"./tf-emqx-performance-test/*.tar.gz"
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: terraform
|
||||
|
@ -209,23 +209,23 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_PERF_TEST }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
|
||||
aws-region: eu-west-1
|
||||
- name: Checkout tf-emqx-performance-test
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: emqx/tf-emqx-performance-test
|
||||
path: tf-emqx-performance-test
|
||||
ref: v0.2.3
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: emqx-ubuntu20.04
|
||||
path: tf-emqx-performance-test/
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0
|
||||
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
- name: run scenario
|
||||
|
@ -249,7 +249,7 @@ jobs:
|
|||
terraform destroy -auto-approve
|
||||
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
|
||||
- name: Send notification to Slack
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
with:
|
||||
payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
|
||||
- name: terraform destroy
|
||||
|
@ -257,13 +257,13 @@ jobs:
|
|||
working-directory: ./tf-emqx-performance-test
|
||||
run: |
|
||||
terraform destroy -auto-approve
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: metrics
|
||||
path: |
|
||||
"./tf-emqx-performance-test/*.tar.gz"
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: terraform
|
||||
|
@ -283,23 +283,23 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_PERF_TEST }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PERF_TEST }}
|
||||
aws-region: eu-west-1
|
||||
- name: Checkout tf-emqx-performance-test
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: emqx/tf-emqx-performance-test
|
||||
path: tf-emqx-performance-test
|
||||
ref: v0.2.3
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: emqx-ubuntu20.04
|
||||
path: tf-emqx-performance-test/
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v3.0.0
|
||||
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
- name: run scenario
|
||||
|
@ -322,7 +322,7 @@ jobs:
|
|||
terraform destroy -auto-approve
|
||||
aws s3 sync --exclude '*' --include '*.tar.gz' s3://$TF_VAR_s3_bucket_name/$TF_VAR_bench_id .
|
||||
- name: Send notification to Slack
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
with:
|
||||
payload-file-path: "./tf-emqx-performance-test/slack-payload.json"
|
||||
- name: terraform destroy
|
||||
|
@ -330,13 +330,13 @@ jobs:
|
|||
working-directory: ./tf-emqx-performance-test
|
||||
run: |
|
||||
terraform destroy -auto-approve
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: success()
|
||||
with:
|
||||
name: metrics
|
||||
path: |
|
||||
"./tf-emqx-performance-test/*.tar.gz"
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: terraform
|
||||
|
|
|
@ -8,7 +8,7 @@ on:
|
|||
tag:
|
||||
type: string
|
||||
required: true
|
||||
publish_release_artefacts:
|
||||
publish_release_artifacts:
|
||||
type: boolean
|
||||
required: true
|
||||
default: false
|
||||
|
@ -31,12 +31,12 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
- name: Detect profile
|
||||
|
@ -67,14 +67,15 @@ jobs:
|
|||
BUCKET=${{ secrets.AWS_S3_BUCKET }}
|
||||
OUTPUT_DIR=${{ steps.profile.outputs.s3dir }}
|
||||
aws s3 cp --recursive s3://$BUCKET/$OUTPUT_DIR/${{ env.ref_name }} packages
|
||||
- uses: emqx/upload-assets@8d2083b4dbe3151b0b735572eaa153b6acb647fe # 0.5.0
|
||||
- uses: emqx/upload-assets@974befcf0e72a1811360a81c798855efb66b0551 # 0.5.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
asset_paths: '["packages/*"]'
|
||||
tag_name: "${{ env.ref_name }}"
|
||||
skip_existing: true
|
||||
- name: update to emqx.io
|
||||
if: startsWith(env.ref_name, 'v') && ((github.event_name == 'release' && !github.event.release.prerelease) || inputs.publish_release_artefacts)
|
||||
if: github.event_name == 'release' || inputs.publish_release_artifacts
|
||||
run: |
|
||||
set -eux
|
||||
curl -w %{http_code} \
|
||||
|
@ -85,7 +86,7 @@ jobs:
|
|||
-d "{\"repo\":\"emqx/emqx\", \"tag\": \"${{ env.ref_name }}\" }" \
|
||||
${{ secrets.EMQX_IO_RELEASE_API }}
|
||||
- name: Push to packagecloud.io
|
||||
if: (github.event_name == 'release' && !github.event.release.prerelease) || inputs.publish_release_artefacts
|
||||
if: (github.event_name == 'release' && !github.event.release.prerelease) || inputs.publish_release_artifacts
|
||||
env:
|
||||
PROFILE: ${{ steps.profile.outputs.profile }}
|
||||
VERSION: ${{ steps.profile.outputs.version }}
|
||||
|
@ -105,14 +106,12 @@ jobs:
|
|||
push "debian/bullseye" "packages/$PROFILE-$VERSION-debian11-arm64.deb"
|
||||
push "debian/bookworm" "packages/$PROFILE-$VERSION-debian12-amd64.deb"
|
||||
push "debian/bookworm" "packages/$PROFILE-$VERSION-debian12-arm64.deb"
|
||||
push "ubuntu/bionic" "packages/$PROFILE-$VERSION-ubuntu18.04-amd64.deb"
|
||||
push "ubuntu/bionic" "packages/$PROFILE-$VERSION-ubuntu18.04-arm64.deb"
|
||||
push "ubuntu/focal" "packages/$PROFILE-$VERSION-ubuntu20.04-amd64.deb"
|
||||
push "ubuntu/focal" "packages/$PROFILE-$VERSION-ubuntu20.04-arm64.deb"
|
||||
push "ubuntu/jammy" "packages/$PROFILE-$VERSION-ubuntu22.04-amd64.deb"
|
||||
push "ubuntu/jammy" "packages/$PROFILE-$VERSION-ubuntu22.04-arm64.deb"
|
||||
push "el/7" "packages/$PROFILE-$VERSION-el7-amd64.rpm"
|
||||
push "el/7" "packages/$PROFILE-$VERSION-el7-arm64.rpm"
|
||||
push "ubuntu/noble" "packages/$PROFILE-$VERSION-ubuntu24.04-amd64.deb"
|
||||
push "ubuntu/noble" "packages/$PROFILE-$VERSION-ubuntu24.04-arm64.deb"
|
||||
push "el/8" "packages/$PROFILE-$VERSION-el8-amd64.rpm"
|
||||
push "el/8" "packages/$PROFILE-$VERSION-el8-arm64.rpm"
|
||||
push "el/9" "packages/$PROFILE-$VERSION-el9-amd64.rpm"
|
||||
|
@ -132,7 +131,7 @@ jobs:
|
|||
checks: write
|
||||
actions: write
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: trigger re-run of app versions check on open PRs
|
||||
shell: bash
|
||||
env:
|
||||
|
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
- emqx
|
||||
- emqx-enterprise
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
- name: extract artifact
|
||||
|
@ -39,10 +39,10 @@ jobs:
|
|||
- name: print erlang log
|
||||
if: failure()
|
||||
run: |
|
||||
cat _build/${{ matrix.profile }}/rel/emqx/logs/erlang.log.*
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
cat _build/${{ matrix.profile }}/rel/emqx/log/erlang.log.*
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: conftest-logs-${{ matrix.profile }}
|
||||
path: _build/${{ matrix.profile }}/rel/emqx/logs
|
||||
path: _build/${{ matrix.profile }}/rel/emqx/log
|
||||
retention-days: 7
|
||||
|
|
|
@ -6,13 +6,6 @@ concurrency:
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
version-emqx:
|
||||
required: true
|
||||
type: string
|
||||
version-emqx-enterprise:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -32,19 +25,24 @@ jobs:
|
|||
|
||||
env:
|
||||
EMQX_NAME: ${{ matrix.profile[0] }}
|
||||
PKG_VSN: ${{ matrix.profile[0] == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
|
||||
EMQX_IMAGE_OLD_VERSION_TAG: ${{ matrix.profile[1] }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ env.EMQX_NAME }}-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
run: |
|
||||
EMQX_IMAGE_TAG=$(docker load < /tmp/${EMQX_NAME}-docker-${PKG_VSN}.tar.gz 2>/dev/null | sed 's/Loaded image: //g')
|
||||
echo "EMQX_IMAGE_TAG=$EMQX_IMAGE_TAG" >> $GITHUB_ENV
|
||||
_EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/${EMQX_NAME}-docker-${PKG_VSN}.tar.gz 2>/dev/null | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$_EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- name: dashboard tests
|
||||
working-directory: ./scripts/ui-tests
|
||||
run: |
|
||||
|
@ -52,9 +50,11 @@ jobs:
|
|||
docker compose up --abort-on-container-exit --exit-code-from selenium
|
||||
- name: test two nodes cluster with proto_dist=inet_tls in docker
|
||||
run: |
|
||||
./scripts/test/start-two-nodes-in-docker.sh -P $EMQX_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG
|
||||
## -d 1 means only put node 1 (latest version) behind haproxy
|
||||
./scripts/test/start-two-nodes-in-docker.sh -d 1 -P $_EMQX_DOCKER_IMAGE_TAG $EMQX_IMAGE_OLD_VERSION_TAG
|
||||
HTTP_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "18083/tcp") 0).HostPort}}' haproxy)
|
||||
./scripts/test/emqx-smoke-test.sh localhost $HTTP_PORT
|
||||
## -c menas 'cleanup'
|
||||
./scripts/test/start-two-nodes-in-docker.sh -c
|
||||
- name: cleanup
|
||||
if: always()
|
||||
|
@ -69,8 +69,6 @@ jobs:
|
|||
shell: bash
|
||||
env:
|
||||
EMQX_NAME: ${{ matrix.profile }}
|
||||
PKG_VSN: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
|
||||
_EMQX_TEST_DB_BACKEND: ${{ matrix.cluster_db_backend }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -79,12 +77,20 @@ jobs:
|
|||
- emqx
|
||||
- emqx-enterprise
|
||||
- emqx-elixir
|
||||
cluster_db_backend:
|
||||
- mnesia
|
||||
- rlog
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
if [ "$EMQX_NAME" = "emqx-enterprise" ]; then
|
||||
_EMQX_TEST_DB_BACKEND='rlog'
|
||||
else
|
||||
_EMQX_TEST_DB_BACKEND='mnesia'
|
||||
fi
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ env.EMQX_NAME }}-docker
|
||||
path: /tmp
|
||||
|
@ -113,4 +119,4 @@ jobs:
|
|||
- name: test node_dump
|
||||
run: |
|
||||
docker exec -t -u root node1.emqx.io bash -c 'apt-get -y update && apt-get -y install net-tools'
|
||||
docker exec node1.emqx.io node_dump
|
||||
docker exec -t -u root node1.emqx.io node_dump
|
||||
|
|
|
@ -27,19 +27,21 @@ permissions:
|
|||
contents: read
|
||||
|
||||
jobs:
|
||||
run_emqx_app_tests:
|
||||
prepare_matrix:
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
container: ${{ inputs.builder }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
outputs:
|
||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||
skip: ${{ steps.matrix.outputs.skip }}
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: run
|
||||
- name: prepare test matrix
|
||||
id: matrix
|
||||
env:
|
||||
BEFORE_REF: ${{ inputs.before_ref }}
|
||||
AFTER_REF: ${{ inputs.after_ref }}
|
||||
|
@ -48,19 +50,54 @@ jobs:
|
|||
changed_files="$(git diff --name-only ${BEFORE_REF} ${AFTER_REF} apps/emqx)"
|
||||
if [ "$changed_files" = '' ]; then
|
||||
echo "nothing changed in apps/emqx, ignored."
|
||||
echo 'matrix=[]' | tee -a $GITHUB_OUTPUT
|
||||
echo 'skip=true' | tee -a $GITHUB_OUTPUT
|
||||
exit 0
|
||||
else
|
||||
echo 'skip=false' | tee -a $GITHUB_OUTPUT
|
||||
echo 'matrix=[{"type": "eunit_proper_and_static"},{"type": "1_3"},{"type": "2_3"},{"type": "3_3"}]' | tee -a $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
run_emqx_app_tests:
|
||||
if: needs.prepare_matrix.outputs.skip != 'true'
|
||||
needs:
|
||||
- prepare_matrix
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
container: ${{ inputs.builder }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.prepare_matrix.outputs.matrix) }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: run
|
||||
run: |
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
make ensure-rebar3
|
||||
cp rebar3 apps/emqx/
|
||||
cd apps/emqx
|
||||
./rebar3 xref
|
||||
./rebar3 dialyzer
|
||||
./rebar3 eunit -v --name 'eunit@127.0.0.1'
|
||||
./rebar3 as standalone_test ct --name 'test@127.0.0.1' -v --readable=true
|
||||
./rebar3 proper -d test/props
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
if [[ ${{ matrix.type }} == "eunit_proper_and_static" ]]; then
|
||||
./rebar3 xref
|
||||
./rebar3 dialyzer
|
||||
./rebar3 eunit -v --name 'eunit@127.0.0.1'
|
||||
./rebar3 proper -d test/props
|
||||
else
|
||||
export SUITEGROUP=${{ matrix.type }}
|
||||
SUITES=$(../../scripts/find-suites.sh apps/emqx | \
|
||||
sed -e 's|apps/emqx/test/||g' | \
|
||||
sed -Ee 's|,?apps/emqx/integration_test/.*||g' | \
|
||||
sed -e 's/\.erl//g')
|
||||
echo "Suites: $SUITES"
|
||||
./rebar3 as standalone_test ct --name 'test@127.0.0.1' -v --readable=true --suite="$SUITES"
|
||||
fi
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: logs-emqx-app-tests
|
||||
name: logs-emqx-app-tests-${{ matrix.type }}
|
||||
path: apps/emqx/_build/test/logs
|
||||
retention-days: 7
|
||||
|
|
|
@ -6,13 +6,6 @@ concurrency:
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
version-emqx:
|
||||
required: true
|
||||
type: string
|
||||
version-emqx-enterprise:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -25,7 +18,6 @@ jobs:
|
|||
shell: bash
|
||||
env:
|
||||
EMQX_NAME: ${{ matrix.profile }}
|
||||
EMQX_TAG: ${{ matrix.profile == 'emqx-enterprise' && inputs.version-emqx-enterprise || inputs.version-emqx }}
|
||||
REPOSITORY: "emqx/${{ matrix.profile }}"
|
||||
|
||||
strategy:
|
||||
|
@ -42,10 +34,17 @@ jobs:
|
|||
- ssl1.3
|
||||
- ssl1.2
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
path: source
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
cd source
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh "$EMQX_NAME")
|
||||
echo "EMQX_TAG=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: "${{ env.EMQX_NAME }}-docker"
|
||||
path: /tmp
|
||||
|
@ -165,7 +164,7 @@ jobs:
|
|||
fi
|
||||
sleep 1;
|
||||
done
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: emqx/paho.mqtt.testing
|
||||
ref: develop-5.0
|
||||
|
|
|
@ -2,10 +2,6 @@ name: JMeter integration tests
|
|||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
version-emqx:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -16,7 +12,7 @@ jobs:
|
|||
steps:
|
||||
- name: Cache Jmeter
|
||||
id: cache-jmeter
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: /tmp/apache-jmeter.tgz
|
||||
key: apache-jmeter-5.4.3.tgz
|
||||
|
@ -35,7 +31,7 @@ jobs:
|
|||
else
|
||||
wget --no-verbose --no-check-certificate -O /tmp/apache-jmeter.tgz $ARCHIVE_URL
|
||||
fi
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: apache-jmeter.tgz
|
||||
path: /tmp/apache-jmeter.tgz
|
||||
|
@ -55,10 +51,23 @@ jobs:
|
|||
|
||||
needs: jmeter_artifact
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
version-emqx: ${{ inputs.version-emqx }}
|
||||
name: emqx-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
shell: bash
|
||||
run: |
|
||||
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- name: docker compose up
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
|
@ -86,7 +95,7 @@ jobs:
|
|||
echo "check logs failed"
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: always()
|
||||
with:
|
||||
name: jmeter_logs-advanced_feat-${{ matrix.scripts_type }}
|
||||
|
@ -111,10 +120,23 @@ jobs:
|
|||
|
||||
needs: jmeter_artifact
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
version-emqx: ${{ inputs.version-emqx }}
|
||||
name: emqx-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
shell: bash
|
||||
run: |
|
||||
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- name: docker compose up
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
|
@ -153,7 +175,7 @@ jobs:
|
|||
if: failure()
|
||||
run: |
|
||||
docker compose -f .ci/docker-compose-file/docker-compose-emqx-cluster.yaml logs --no-color > ./jmeter_logs/emqx.log
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: always()
|
||||
with:
|
||||
name: jmeter_logs-pgsql_authn_authz-${{ matrix.scripts_type }}_${{ matrix.pgsql_tag }}
|
||||
|
@ -175,10 +197,23 @@ jobs:
|
|||
|
||||
needs: jmeter_artifact
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
version-emqx: ${{ inputs.version-emqx }}
|
||||
name: emqx-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
shell: bash
|
||||
run: |
|
||||
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- name: docker compose up
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
|
@ -213,7 +248,7 @@ jobs:
|
|||
echo "check logs failed"
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: always()
|
||||
with:
|
||||
name: jmeter_logs-mysql_authn_authz-${{ matrix.scripts_type }}_${{ matrix.mysql_tag }}
|
||||
|
@ -231,10 +266,23 @@ jobs:
|
|||
|
||||
needs: jmeter_artifact
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
version-emqx: ${{ inputs.version-emqx }}
|
||||
name: emqx-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
shell: bash
|
||||
run: |
|
||||
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- name: docker compose up
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
|
@ -265,7 +313,7 @@ jobs:
|
|||
echo "check logs failed"
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: always()
|
||||
with:
|
||||
name: jmeter_logs-JWT_authn-${{ matrix.scripts_type }}
|
||||
|
@ -284,10 +332,23 @@ jobs:
|
|||
|
||||
needs: jmeter_artifact
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up environment
|
||||
id: env
|
||||
run: |
|
||||
source env.sh
|
||||
PKG_VSN=$(docker run --rm -v $(pwd):$(pwd) -w $(pwd) -u $(id -u) "$EMQX_BUILDER" ./pkg-vsn.sh emqx)
|
||||
echo "PKG_VSN=$PKG_VSN" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
version-emqx: ${{ inputs.version-emqx }}
|
||||
name: emqx-docker
|
||||
path: /tmp
|
||||
- name: load docker image
|
||||
shell: bash
|
||||
run: |
|
||||
EMQX_DOCKER_IMAGE_TAG=$(docker load < /tmp/emqx-docker-${PKG_VSN}.tar.gz | sed 's/Loaded image: //g')
|
||||
echo "_EMQX_DOCKER_IMAGE_TAG=$EMQX_DOCKER_IMAGE_TAG" >> $GITHUB_ENV
|
||||
- uses: ./.github/actions/prepare-jmeter
|
||||
- name: docker compose up
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
|
@ -309,7 +370,7 @@ jobs:
|
|||
echo "check logs failed"
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: always()
|
||||
with:
|
||||
name: jmeter_logs-built_in_database_authn_authz-${{ matrix.scripts_type }}
|
||||
|
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: emqx-enterprise
|
||||
- name: extract artifact
|
||||
|
@ -45,7 +45,7 @@ jobs:
|
|||
run: |
|
||||
export PROFILE='emqx-enterprise'
|
||||
make emqx-enterprise-tgz
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
name: Upload built emqx and test scenario
|
||||
with:
|
||||
name: relup_tests_emqx_built
|
||||
|
@ -72,10 +72,10 @@ jobs:
|
|||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: erlef/setup-beam@a34c98fd51e370b4d4981854aba1eb817ce4e483 # v1.17.0
|
||||
- uses: erlef/setup-beam@b9c58b0450cd832ccdb3c17cc156a47065d2114f # v1.18.1
|
||||
with:
|
||||
otp-version: 26.2.1
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
otp-version: 26.2.5
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
repository: hawk/lux
|
||||
ref: lux-2.8.1
|
||||
|
@ -88,7 +88,7 @@ jobs:
|
|||
./configure
|
||||
make
|
||||
echo "$(pwd)/bin" >> $GITHUB_PATH
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
name: Download built emqx and test scenario
|
||||
with:
|
||||
name: relup_tests_emqx_built
|
||||
|
@ -111,7 +111,7 @@ jobs:
|
|||
docker logs node2.emqx.io | tee lux_logs/emqx2.log
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
name: Save debug data
|
||||
if: failure()
|
||||
with:
|
||||
|
|
|
@ -20,9 +20,6 @@ on:
|
|||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
IS_CI: "yes"
|
||||
|
||||
|
@ -38,37 +35,41 @@ jobs:
|
|||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04"
|
||||
container: ${{ inputs.builder }}
|
||||
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
ENABLE_COVER_COMPILE: 1
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
|
||||
- name: extract artifact
|
||||
run: |
|
||||
unzip -o -q ${{ matrix.profile }}.zip
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
# produces eunit.coverdata
|
||||
- name: eunit
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
ENABLE_COVER_COMPILE: 1
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}
|
||||
run: make eunit
|
||||
- run: make eunit
|
||||
|
||||
# produces proper.coverdata
|
||||
- name: proper
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
ENABLE_COVER_COMPILE: 1
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}
|
||||
run: make proper
|
||||
- run: make proper
|
||||
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
with:
|
||||
name: coverdata-${{ matrix.profile }}-${{ matrix.otp }}
|
||||
path: _build/test/cover
|
||||
retention-days: 7
|
||||
- run: make cover
|
||||
|
||||
- name: send to coveralls
|
||||
if: github.repository == 'emqx/emqx'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: make coveralls
|
||||
|
||||
- run: cat rebar3.crashdump
|
||||
if: failure()
|
||||
|
||||
ct_docker:
|
||||
runs-on: ${{ github.repository_owner == 'emqx' && fromJSON('["self-hosted","ephemeral","linux","x64"]') || 'ubuntu-22.04' }}
|
||||
|
@ -82,19 +83,24 @@ jobs:
|
|||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
- name: extract artifact
|
||||
run: |
|
||||
unzip -o -q ${{ matrix.profile }}.zip
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
# produces $PROFILE-<app-name>-<otp-vsn>-sg<suitegroup>.coverdata
|
||||
- name: run common tests
|
||||
env:
|
||||
DOCKER_CT_RUNNER_IMAGE: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04"
|
||||
DOCKER_CT_RUNNER_IMAGE: ${{ inputs.builder }}
|
||||
MONGO_TAG: "5"
|
||||
MYSQL_TAG: "8"
|
||||
PGSQL_TAG: "13"
|
||||
|
@ -103,23 +109,34 @@ jobs:
|
|||
TDENGINE_TAG: "3.0.2.4"
|
||||
OPENTS_TAG: "9aa7f88"
|
||||
MINIO_TAG: "RELEASE.2023-03-20T20-16-18Z"
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
SUITEGROUP: ${{ matrix.suitegroup }}
|
||||
ENABLE_COVER_COMPILE: 1
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
|
||||
run: ./scripts/ct/run.sh --ci --app ${{ matrix.app }}
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
with:
|
||||
name: coverdata-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
|
||||
path: _build/test/cover
|
||||
retention-days: 7
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-sg${{ matrix.suitegroup }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./scripts/ct/run.sh --ci --app ${{ matrix.app }} --keep-up
|
||||
|
||||
- name: make cover
|
||||
run: |
|
||||
docker exec -e PROFILE="$PROFILE" -t erlang make cover
|
||||
|
||||
- name: send to coveralls
|
||||
if: github.repository == 'emqx/emqx'
|
||||
run: |
|
||||
ls _build/test/cover/*.coverdata || exit 0
|
||||
docker exec -e PROFILE="$PROFILE" -t erlang make coveralls
|
||||
|
||||
- name: rebar3.crashdump
|
||||
if: failure()
|
||||
run: cat rebar3.crashdump
|
||||
|
||||
- name: compress logs
|
||||
if: failure()
|
||||
run: tar -czf logs.tar.gz _build/test/logs
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
|
||||
name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-sg${{ matrix.suitegroup }}
|
||||
path: logs.tar.gz
|
||||
compression-level: 0
|
||||
retention-days: 7
|
||||
|
@ -132,13 +149,22 @@ jobs:
|
|||
matrix:
|
||||
include: ${{ fromJson(inputs.ct-host) }}
|
||||
|
||||
container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04"
|
||||
container: ${{ inputs.builder }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
SUITEGROUP: ${{ matrix.suitegroup }}
|
||||
ENABLE_COVER_COMPILE: 1
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-sg${{ matrix.suitegroup }}
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
- name: extract artifact
|
||||
|
@ -148,26 +174,29 @@ jobs:
|
|||
|
||||
# produces $PROFILE-<app-name>-<otp-vsn>-sg<suitegroup>.coverdata
|
||||
- name: run common tests
|
||||
run: make "${{ matrix.app }}-ct"
|
||||
|
||||
- run: make cover
|
||||
|
||||
- name: send to coveralls
|
||||
if: github.repository == 'emqx/emqx'
|
||||
env:
|
||||
PROFILE: ${{ matrix.profile }}
|
||||
SUITEGROUP: ${{ matrix.suitegroup }}
|
||||
ENABLE_COVER_COMPILE: 1
|
||||
CT_COVER_EXPORT_PREFIX: ${{ matrix.profile }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
make "${{ matrix.app }}-ct"
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
with:
|
||||
name: coverdata-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
|
||||
path: _build/test/cover
|
||||
if-no-files-found: warn # do not fail if no coverdata found
|
||||
retention-days: 7
|
||||
ls _build/test/cover/*.coverdata || exit 0
|
||||
make coveralls
|
||||
|
||||
- run: cat rebar3.crashdump
|
||||
if: failure()
|
||||
|
||||
- name: compress logs
|
||||
if: failure()
|
||||
run: tar -czf logs.tar.gz _build/test/logs
|
||||
- uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
|
||||
- uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
if: failure()
|
||||
with:
|
||||
name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-${{ matrix.otp }}-sg${{ matrix.suitegroup }}
|
||||
name: logs-${{ matrix.profile }}-${{ matrix.prefix }}-sg${{ matrix.suitegroup }}
|
||||
path: logs.tar.gz
|
||||
compression-level: 0
|
||||
retention-days: 7
|
||||
|
@ -180,61 +209,18 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Coveralls finished
|
||||
if: github.repository == 'emqx/emqx'
|
||||
uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63 # v2.3.0
|
||||
with:
|
||||
parallel-finished: true
|
||||
git-branch: ${{ github.ref }}
|
||||
git-commit: ${{ github.sha }}
|
||||
|
||||
- run: echo "All tests passed"
|
||||
|
||||
make_cover:
|
||||
needs:
|
||||
- eunit_and_proper
|
||||
- ct
|
||||
- ct_docker
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
container: ${{ inputs.builder }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
profile:
|
||||
- emqx-enterprise
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
- name: extract artifact
|
||||
run: |
|
||||
unzip -o -q ${{ matrix.profile }}.zip
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
name: download coverdata
|
||||
with:
|
||||
pattern: coverdata-${{ matrix.profile }}-*
|
||||
path: _build/test/cover
|
||||
merge-multiple: true
|
||||
|
||||
- name: make cover
|
||||
env:
|
||||
PROFILE: emqx-enterprise
|
||||
run: make cover
|
||||
|
||||
- name: send to coveralls
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PROFILE: emqx-enterprise
|
||||
run: make coveralls
|
||||
|
||||
- name: get coveralls logs
|
||||
if: failure()
|
||||
run: cat rebar3.crashdump
|
||||
|
||||
# do this in a separate job
|
||||
upload_coverdata:
|
||||
needs: make_cover
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Coveralls Finished
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
curl -v -k https://coveralls.io/webhook \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"repo_name\":\"$GITHUB_REPOSITORY\",\"repo_token\":\"$GITHUB_TOKEN\",\"payload\":{\"build_num\":$GITHUB_RUN_ID,\"status\":\"done\"}}" || true
|
||||
|
||||
|
|
|
@ -10,27 +10,27 @@ on:
|
|||
push:
|
||||
branches:
|
||||
- master
|
||||
- 'release-5[0-9]'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
if: github.repository == 'emqx/emqx'
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
@ -40,7 +40,7 @@ jobs:
|
|||
publish_results: true
|
||||
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
|
||||
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
|
@ -48,6 +48,6 @@ jobs:
|
|||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@8e0b1c74b1d5a0077b04d064c76ee714d3da7637 # v2.22.1
|
||||
uses: github/codeql-action/upload-sarif@7e187e1c529d80bac7b87a16e7a792427f65cf02 # v2.22.1
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
- emqx-enterprise
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
pattern: "${{ matrix.profile }}-schema-dump-*-x64"
|
||||
merge-multiple: true
|
||||
|
|
|
@ -13,8 +13,8 @@ permissions:
|
|||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository_owner == 'emqx'
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
if: github.repository == 'emqx/emqx'
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: none
|
||||
|
|
|
@ -28,21 +28,21 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(inputs.ct-matrix) }}
|
||||
container: "ghcr.io/emqx/emqx-builder/${{ matrix.builder }}:${{ matrix.elixir }}-${{ matrix.otp }}-ubuntu22.04"
|
||||
container: "${{ inputs.builder }}"
|
||||
steps:
|
||||
- uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
|
||||
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: ${{ matrix.profile }}
|
||||
- name: extract artifact
|
||||
run: |
|
||||
unzip -o -q ${{ matrix.profile }}.zip
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: "emqx_dialyzer_${{ matrix.otp }}_plt"
|
||||
key: rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}-${{ hashFiles('rebar.*', 'apps/*/rebar.*') }}
|
||||
path: "emqx_dialyzer_${{ matrix.profile }}_plt"
|
||||
key: rebar3-dialyzer-plt-${{ matrix.profile }}-${{ hashFiles('rebar.*', 'apps/*/rebar.*') }}
|
||||
restore-keys: |
|
||||
rebar3-dialyzer-plt-${{ matrix.profile }}-${{ matrix.otp }}-
|
||||
rebar3-dialyzer-plt-${{ matrix.profile }}-
|
||||
- run: cat .env | tee -a $GITHUB_ENV
|
||||
- name: run static checks
|
||||
run: make static_checks
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
name: Sync release branch
|
||||
|
||||
concurrency:
|
||||
group: sync-release-branch-${{ github.event_name }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
create-pr:
|
||||
runs-on: ${{ endsWith(github.repository, '/emqx') && 'ubuntu-22.04' || fromJSON('["self-hosted","ephemeral","linux","x64"]') }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branch:
|
||||
- release-57
|
||||
|
||||
env:
|
||||
SYNC_BRANCH: ${{ matrix.branch }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: create new branch
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
NEW_BRANCH_NAME=sync-${SYNC_BRANCH}-$(date +"%Y%m%d-%H%M%S")
|
||||
echo "NEW_BRANCH_NAME=${NEW_BRANCH_NAME}" >> $GITHUB_ENV
|
||||
git config --global user.name "${GITHUB_ACTOR}"
|
||||
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
|
||||
git checkout -b ${NEW_BRANCH_NAME}
|
||||
git merge origin/${SYNC_BRANCH} 2>&1 | tee merge.log
|
||||
git push origin ${NEW_BRANCH_NAME}:${NEW_BRANCH_NAME}
|
||||
|
||||
- name: create pull request
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
for pr in $(gh pr list --state open --base master --label sync-release-branch --search "Sync ${SYNC_BRANCH} in:title" --repo ${{ github.repository }} --json number --jq '.[] | .number'); do
|
||||
gh pr close $pr --repo ${{ github.repository }} --delete-branch || true
|
||||
done
|
||||
gh pr create --title "Sync ${SYNC_BRANCH}" --body "Sync ${SYNC_BRANCH}" --base master --head ${NEW_BRANCH_NAME} --label sync-release-branch --repo ${{ github.repository }}
|
||||
|
||||
- name: Send notification to Slack
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
awk '{printf "%s\\n", $0}' merge.log > merge.log.1
|
||||
cat <<EOF > payload.json
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "Automatic sync of ${SYNC_BRANCH} branch failed: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "\`\`\`$(cat merge.log.1)\`\`\`"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
curl -X POST -H 'Content-type: application/json' --data @payload.json "$SLACK_WEBHOOK_URL"
|
|
@ -18,12 +18,12 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
|
||||
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
- name: Detect profile
|
||||
|
|
|
@ -72,4 +72,10 @@ ct_run*/
|
|||
apps/emqx_conf/etc/emqx.conf.all.rendered*
|
||||
rebar-git-cache.tar
|
||||
# build docker image locally
|
||||
.dockerignore
|
||||
.docker_image_tag
|
||||
.emqx_docker_image_tags
|
||||
.git/
|
||||
apps/emqx_utils/src/emqx_variform_parser.erl
|
||||
apps/emqx_utils/src/emqx_variform_scan.erl
|
||||
default-profile.mk
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
erlang 26.2.1-2
|
||||
erlang 26.2.5-3
|
||||
elixir 1.15.7-otp-26
|
||||
|
|
56
Makefile
56
Makefile
|
@ -6,23 +6,17 @@ endif
|
|||
REBAR = $(CURDIR)/rebar3
|
||||
BUILD = $(CURDIR)/build
|
||||
SCRIPTS = $(CURDIR)/scripts
|
||||
export EMQX_RELUP ?= true
|
||||
export EMQX_DEFAULT_BUILDER = ghcr.io/emqx/emqx-builder/5.3-2:1.15.7-26.2.1-2-debian11
|
||||
export EMQX_DEFAULT_RUNNER = public.ecr.aws/debian/debian:11-slim
|
||||
export EMQX_REL_FORM ?= tgz
|
||||
export QUICER_DOWNLOAD_FROM_RELEASE = 1
|
||||
ifeq ($(OS),Windows_NT)
|
||||
export REBAR_COLOR=none
|
||||
FIND=/usr/bin/find
|
||||
else
|
||||
FIND=find
|
||||
endif
|
||||
include env.sh
|
||||
|
||||
# Dashboard version
|
||||
# from https://github.com/emqx/emqx-dashboard5
|
||||
export EMQX_DASHBOARD_VERSION ?= v1.6.1
|
||||
export EMQX_EE_DASHBOARD_VERSION ?= e1.5.0-beta.3
|
||||
export EMQX_DASHBOARD_VERSION ?= v1.10.0-beta.1
|
||||
export EMQX_EE_DASHBOARD_VERSION ?= e1.8.0-beta.1
|
||||
|
||||
export EMQX_RELUP ?= true
|
||||
export EMQX_REL_FORM ?= tgz
|
||||
|
||||
-include default-profile.mk
|
||||
PROFILE ?= emqx
|
||||
REL_PROFILES := emqx emqx-enterprise
|
||||
PKG_PROFILES := emqx-pkg emqx-enterprise-pkg
|
||||
|
@ -34,6 +28,8 @@ CT_COVER_EXPORT_PREFIX ?= $(PROFILE)
|
|||
|
||||
export REBAR_GIT_CLONE_OPTIONS += --depth=1
|
||||
|
||||
ELIXIR_COMMON_DEPS := ensure-hex ensure-mix-rebar3 ensure-mix-rebar
|
||||
|
||||
.PHONY: default
|
||||
default: $(REBAR) $(PROFILE)
|
||||
|
||||
|
@ -53,7 +49,8 @@ $(REBAR): .prepare ensure-rebar3
|
|||
|
||||
.PHONY: ensure-hex
|
||||
ensure-hex:
|
||||
@mix local.hex --if-missing --force
|
||||
# @mix local.hex --if-missing --force
|
||||
@mix local.hex 2.0.6 --if-missing --force
|
||||
|
||||
.PHONY: ensure-mix-rebar3
|
||||
ensure-mix-rebar3: $(REBAR)
|
||||
|
@ -63,8 +60,12 @@ ensure-mix-rebar3: $(REBAR)
|
|||
ensure-mix-rebar: $(REBAR)
|
||||
@mix local.rebar --if-missing --force
|
||||
|
||||
|
||||
.PHONY: elixir-common-deps
|
||||
elixir-common-deps: $(ELIXIR_COMMON_DEPS)
|
||||
|
||||
.PHONY: mix-deps-get
|
||||
mix-deps-get: $(ELIXIR_COMMON_DEPS)
|
||||
mix-deps-get: elixir-common-deps
|
||||
@mix deps.get
|
||||
|
||||
.PHONY: eunit
|
||||
|
@ -194,8 +195,8 @@ $(PROFILES:%=clean-%):
|
|||
@if [ -d _build/$(@:clean-%=%) ]; then \
|
||||
rm -f rebar.lock; \
|
||||
rm -rf _build/$(@:clean-%=%)/rel; \
|
||||
$(FIND) _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -o -name '*.o' -o -name '*.d' -type f | xargs rm -f; \
|
||||
$(FIND) _build/$(@:clean-%=%) -type l -delete; \
|
||||
find _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -o -name '*.o' -o -name '*.d' -type f | xargs rm -f; \
|
||||
find _build/$(@:clean-%=%) -type l -delete; \
|
||||
fi
|
||||
|
||||
.PHONY: clean-all
|
||||
|
@ -243,7 +244,7 @@ $(foreach zt,$(ALL_ZIPS),$(eval $(call download-relup-packages,$(zt))))
|
|||
## relup target is to create relup instructions
|
||||
.PHONY: $(REL_PROFILES:%=%-relup)
|
||||
define gen-relup-target
|
||||
$1-relup: $1-relup-downloads $(COMMON_DEPS)
|
||||
$1-relup: $(COMMON_DEPS)
|
||||
@$(BUILD) $1 relup
|
||||
endef
|
||||
ALL_TGZS = $(REL_PROFILES)
|
||||
|
@ -252,7 +253,7 @@ $(foreach zt,$(ALL_TGZS),$(eval $(call gen-relup-target,$(zt))))
|
|||
## tgz target is to create a release package .tar.gz with relup
|
||||
.PHONY: $(REL_PROFILES:%=%-tgz)
|
||||
define gen-tgz-target
|
||||
$1-tgz: $1-relup
|
||||
$1-tgz: $(COMMON_DEPS)
|
||||
@$(BUILD) $1 tgz
|
||||
endef
|
||||
ALL_TGZS = $(REL_PROFILES)
|
||||
|
@ -315,10 +316,19 @@ $(foreach tt,$(ALL_ELIXIR_TGZS),$(eval $(call gen-elixir-tgz-target,$(tt))))
|
|||
|
||||
.PHONY: fmt
|
||||
fmt: $(REBAR)
|
||||
@$(SCRIPTS)/erlfmt -w 'apps/*/{src,include,priv,test,integration_test}/**/*.{erl,hrl,app.src,eterm}'
|
||||
@$(SCRIPTS)/erlfmt -w '**/*.escript' --exclude-files '_build/**'
|
||||
@$(SCRIPTS)/erlfmt -w '**/rebar.config' --exclude-files '_build/**'
|
||||
@$(SCRIPTS)/erlfmt -w 'rebar.config.erl'
|
||||
@find . \( -name '*.app.src' -o \
|
||||
-name '*.erl' -o \
|
||||
-name '*.hrl' -o \
|
||||
-name 'rebar.config' -o \
|
||||
-name '*.eterm' -o \
|
||||
-name '*.escript' \) \
|
||||
-not -path '*/_build/*' \
|
||||
-not -path '*/deps/*' \
|
||||
-not -path '*/_checkouts/*' \
|
||||
-type f \
|
||||
| xargs $(SCRIPTS)/erlfmt -w
|
||||
@$(SCRIPTS)/erlfmt -w 'apps/emqx/rebar.config.script'
|
||||
@$(SCRIPTS)/erlfmt -w 'elvis.config'
|
||||
@$(SCRIPTS)/erlfmt -w 'bin/nodetool'
|
||||
@mix format
|
||||
|
||||
|
|
2
NOTICE
2
NOTICE
|
@ -1,5 +1,5 @@
|
|||
EMQX, highly scalable, highly available distributed MQTT messaging platform for IoT.
|
||||
Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
|
||||
This product contains code developed at EMQ Technologies Co., Ltd.
|
||||
Visit https://www.emqx.come to learn more.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
简体中文 | [English](./README.md) | [Русский](./README-RU.md)
|
||||
|
||||
# EMQX
|
||||
|
||||
[](https://github.com/emqx/emqx/releases)
|
||||
[](https://github.com/emqx/emqx/actions/workflows/_push-entrypoint.yaml)
|
||||
[](https://coveralls.io/github/emqx/emqx?branch=master)
|
||||
[](https://hub.docker.com/r/emqx/emqx)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/emqx/emqx)
|
||||
[](https://slack-invite.emqx.io/)
|
||||
[](https://discord.gg/xYGf3fQnES)
|
||||
[](https://twitter.com/EMQTech)
|
||||
|
@ -85,7 +88,7 @@ EMQX Cloud 文档:[docs.emqx.com/zh/cloud/latest/](https://docs.emqx.com/zh/cl
|
|||
|
||||
`master` 分支是最新的 5 版本,`main-v4.4` 是 4.4 版本。
|
||||
|
||||
EMQX 4.4 版本需要 OTP 24;5 版本则可以使用 OTP 24 和 25 构建。
|
||||
EMQX 4.4 版本需要 OTP 24;5 版本则可以使用 OTP 25 和 26 构建。
|
||||
|
||||
```bash
|
||||
git clone https://github.com/emqx/emqx.git
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
Русский | [简体中文](./README-CN.md) | [English](./README.md)
|
||||
|
||||
# Брокер EMQX
|
||||
|
||||
[](https://github.com/emqx/emqx/releases)
|
||||
[](https://github.com/emqx/emqx/actions/workflows/_push-entrypoint.yaml)
|
||||
[](https://coveralls.io/github/emqx/emqx?branch=master)
|
||||
[](https://hub.docker.com/r/emqx/emqx)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/emqx/emqx)
|
||||
[](https://slack-invite.emqx.io/)
|
||||
[](https://discord.gg/xYGf3fQnES)
|
||||
[](https://twitter.com/EMQTech)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
English | [简体中文](./README-CN.md) | [Русский](./README-RU.md)
|
||||
|
||||
# EMQX
|
||||
|
||||
[](https://github.com/emqx/emqx/releases)
|
||||
[](https://github.com/emqx/emqx/actions/workflows/_push-entrypoint.yaml)
|
||||
[](https://coveralls.io/github/emqx/emqx?branch=master)
|
||||
[](https://hub.docker.com/r/emqx/emqx)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/emqx/emqx)
|
||||
[](https://slack-invite.emqx.io/)
|
||||
[](https://discord.gg/xYGf3fQnES)
|
||||
[](https://twitter.com/EMQTech)
|
||||
|
@ -97,7 +100,7 @@ The `master` branch tracks the latest version 5. For version 4.4 checkout the `m
|
|||
|
||||
EMQX 4.4 requires OTP 24.
|
||||
EMQX 5.0 ~ 5.3 can be built with OTP 24 or 25.
|
||||
EMQX 5.4 and newer can be built with OTP 24 or 25.
|
||||
EMQX 5.4 and newer can be built with OTP 25 or 26.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/emqx/emqx.git
|
||||
|
|
131
Windows.md
131
Windows.md
|
@ -1,131 +0,0 @@
|
|||
# Build and run EMQX on Windows
|
||||
|
||||
NOTE: The instructions and examples are based on Windows 10.
|
||||
|
||||
## Build Environment
|
||||
|
||||
### Visual studio for C/C++ compile and link
|
||||
|
||||
EMQX includes Erlang NIF (Native Implemented Function) components, implemented
|
||||
in C/C++. To compile and link C/C++ libraries, the easiest way is perhaps to
|
||||
install Visual Studio.
|
||||
|
||||
Visual Studio 2019 is used in our tests.
|
||||
If you are like me (@zmstone), do not know where to start,
|
||||
please follow this OTP guide:
|
||||
https://github.com/erlang/otp/blob/master/HOWTO/INSTALL-WIN32.md
|
||||
|
||||
NOTE: To avoid surprises, you may need to add below two paths to `Path` environment variable
|
||||
and order them before other paths.
|
||||
|
||||
```
|
||||
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64
|
||||
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build
|
||||
```
|
||||
|
||||
Depending on your visual studio version and OS, the paths may differ.
|
||||
The first path is for rebar3 port compiler to find `cl.exe` and `link.exe`
|
||||
The second path is for CMD to setup environment variables.
|
||||
|
||||
### Erlang/OTP
|
||||
|
||||
Install Erlang/OTP 24 from https://www.erlang.org/downloads
|
||||
You may need to edit the `Path` environment variable to allow running
|
||||
Erlang commands such as `erl` from powershell.
|
||||
|
||||
To validate Erlang installation in CMD or powershell:
|
||||
|
||||
* Start (or restart) CMD or powershell
|
||||
|
||||
* Execute `erl` command to enter Erlang shell
|
||||
|
||||
* Evaluate Erlang expression `halt().` to exit Erlang shell.
|
||||
|
||||
e.g.
|
||||
|
||||
```
|
||||
PS C:\Users\zmsto> erl
|
||||
Eshell V12.2.1 (abort with ^G)
|
||||
1> halt().
|
||||
```
|
||||
|
||||
### bash
|
||||
|
||||
All EMQX build/run scripts are either in `bash` or `escript`.
|
||||
`escript` is installed as a part of Erlang. To install a `bash`
|
||||
environment in Windows, there are quite a few options.
|
||||
|
||||
Cygwin is what we tested with.
|
||||
|
||||
* Add `cygwin\bin` dir to `Path` environment variable
|
||||
To do so, search for Edit environment variable in control panel and
|
||||
add `C:\tools\cygwin\bin` (depending on the location where it was installed)
|
||||
to `Path` list.
|
||||
|
||||
* Validate installation.
|
||||
Start (restart) CMD or powershell console and execute `which bash`, it should
|
||||
print out `/usr/bin/bash`
|
||||
|
||||
NOTE: Make sure cygwin's bin dir is added before `C:\Windows\system32` in `Path`,
|
||||
otherwise the build scripts may end up using binaries from wsl instead of cygwin.
|
||||
|
||||
### Other tools
|
||||
|
||||
Some of the unix world tools are required to build EMQX. Including:
|
||||
|
||||
* git
|
||||
* curl
|
||||
* make
|
||||
* cmake
|
||||
* jq
|
||||
* zip / unzip
|
||||
|
||||
We recommend using [scoop](https://scoop.sh/), or [Chocolatey](https://chocolatey.org/install) to install the tools.
|
||||
|
||||
When using scoop:
|
||||
|
||||
```
|
||||
scoop install git curl make cmake jq zip unzip
|
||||
```
|
||||
|
||||
## Build EMQX source code
|
||||
|
||||
* Clone the repo: `git clone https://github.com/emqx/emqx.git`
|
||||
|
||||
* Start CMD console
|
||||
|
||||
* Execute `vcvarsall.bat x86_amd64` to load environment variables
|
||||
|
||||
* Change to emqx directory and execute `make`
|
||||
|
||||
### Possible errors
|
||||
|
||||
* `'cl.exe' is not recognized as an internal or external command`
|
||||
This error is likely due to Visual Studio executables are not set in `Path` environment variable.
|
||||
To fix it, either add path like `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64`
|
||||
to `Paht`. Or make sure `vcvarsall.bat x86_amd64` is executed prior to the `make` command
|
||||
|
||||
* `fatal error C1083: Cannot open include file: 'assert.h': No such file or directory`
|
||||
If Visual Studio is installed correctly, this is likely `LIB` and `LIB_PATH` environment
|
||||
variables are not set. Make sure `vcvarsall.bat x86_amd64` is executed prior to the `make` command
|
||||
|
||||
* `link: extra operand 'some.obj'`
|
||||
This is likely due to the usage of GNU `lnik.exe` but not the one from Visual Studio.
|
||||
Execute `link.exe --version` to inspect which one is in use. The one installed from
|
||||
Visual Studio should print out `Microsoft (R) Incremental Linker`.
|
||||
To fix it, Visual Studio's bin paths should be ordered prior to Cygwin's (or similar installation's)
|
||||
bin paths in `Path` environment variable.
|
||||
|
||||
## Run EMQX
|
||||
|
||||
To start EMQX broker.
|
||||
|
||||
Execute `_build\emqx\rel\emqx>.\bin\emqx console` or `_build\emqx\rel\emqx>.\bin\emqx start` to start EMQX.
|
||||
|
||||
Then execute `_build\emqx\rel\emqx>.\bin\emqx_ctl status` to check status.
|
||||
If everything works fine, it should print out
|
||||
|
||||
```
|
||||
Node 'emqx@127.0.0.1' 4.3-beta.1 is started
|
||||
Application emqx 4.3.0 is running
|
||||
```
|
|
@ -1,5 +1,5 @@
|
|||
EMQX, highly scalable, highly available distributed MQTT messaging platform for IoT.
|
||||
Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
|
||||
This product contains code developed at EMQ Technologies Co., Ltd.
|
||||
Visit https://www.emqx.come to learn more.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
## EMQX provides support for two primary log handlers: `file` and `console`, with an additional `audit` handler specifically designed to always direct logs to files.
|
||||
## The system's default log handling behavior can be configured via the environment variable `EMQX_DEFAULT_LOG_HANDLER`, which accepts the following settings:
|
||||
##
|
||||
## - `file`: Directs log output exclusively to files.
|
||||
## - `console`: Channels log output solely to the console.
|
||||
##
|
||||
## It's noteworthy that `EMQX_DEFAULT_LOG_HANDLER` is set to `file` when EMQX is initiated via systemd `emqx.service` file.
|
||||
## In scenarios outside systemd initiation, `console` serves as the default log handler.
|
||||
|
||||
## Read more about configs here: {{ emqx_configuration_doc_log }}
|
||||
|
||||
log {
|
||||
# file {
|
||||
# level = warning
|
||||
# }
|
||||
# console {
|
||||
# level = warning
|
||||
# }
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -45,6 +45,10 @@
|
|||
).
|
||||
|
||||
-define(assertReceive(PATTERN, TIMEOUT),
|
||||
?assertReceive(PATTERN, TIMEOUT, #{})
|
||||
).
|
||||
|
||||
-define(assertReceive(PATTERN, TIMEOUT, EXTRA),
|
||||
(fun() ->
|
||||
receive
|
||||
X__V = PATTERN -> X__V
|
||||
|
@ -54,7 +58,8 @@
|
|||
{module, ?MODULE},
|
||||
{line, ?LINE},
|
||||
{expression, (??PATTERN)},
|
||||
{mailbox, ?drainMailbox()}
|
||||
{mailbox, ?drainMailbox()},
|
||||
{extra_info, EXTRA}
|
||||
]}
|
||||
)
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -65,9 +65,20 @@
|
|||
%% Route
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-record(share_dest, {
|
||||
session_id :: emqx_session:session_id(),
|
||||
group :: emqx_types:group()
|
||||
}).
|
||||
|
||||
-record(route, {
|
||||
topic :: binary(),
|
||||
dest :: node() | {binary(), node()} | emqx_session:session_id()
|
||||
dest ::
|
||||
node()
|
||||
| {binary(), node()}
|
||||
| emqx_session:session_id()
|
||||
%% One session can also have multiple subscriptions to the same topic through different groups
|
||||
| #share_dest{}
|
||||
| emqx_external_broker:dest()
|
||||
}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -88,14 +99,17 @@
|
|||
%%--------------------------------------------------------------------
|
||||
|
||||
-record(banned, {
|
||||
who ::
|
||||
{clientid, binary()}
|
||||
| {peerhost, inet:ip_address()}
|
||||
| {username, binary()},
|
||||
who :: emqx_types:banned_who(),
|
||||
by :: binary(),
|
||||
reason :: binary(),
|
||||
at :: integer(),
|
||||
until :: integer()
|
||||
}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Configurations
|
||||
%%--------------------------------------------------------------------
|
||||
-define(KIND_REPLICATE, replicate).
|
||||
-define(KIND_INITIATE, initiate).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%-------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -23,11 +23,20 @@
|
|||
-define(CHAN_INFO_TAB, emqx_channel_info).
|
||||
-define(CHAN_LIVE_TAB, emqx_channel_live).
|
||||
|
||||
%% Mria/Mnesia Tables for channel management.
|
||||
%% Mria table for session registration.
|
||||
-define(CHAN_REG_TAB, emqx_channel_registry).
|
||||
|
||||
-define(T_KICK, 5_000).
|
||||
-define(T_GET_INFO, 5_000).
|
||||
-define(T_TAKEOVER, 15_000).
|
||||
|
||||
-define(CM_POOL, emqx_cm_pool).
|
||||
|
||||
%% Registered sessions.
|
||||
-record(channel, {
|
||||
chid :: emqx_types:clientid() | '_',
|
||||
%% pid field is extended in 5.6.0 to support recording unregistration timestamp.
|
||||
pid :: pid() | non_neg_integer() | '$1'
|
||||
}).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022, 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed 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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc This header contains definitions of durable session metadata
|
||||
%% keys, that can be consumed by the external code.
|
||||
-ifndef(EMQX_DURABLE_SESSION_META_HRL).
|
||||
-define(EMQX_DURABLE_SESSION_META_HRL, true).
|
||||
|
||||
%% Session metadata keys:
|
||||
-define(created_at, created_at).
|
||||
-define(last_alive_at, last_alive_at).
|
||||
-define(expiry_interval, expiry_interval).
|
||||
%% Unique integer used to create unique identities:
|
||||
-define(last_id, last_id).
|
||||
%% Connection info (relevent for the dashboard):
|
||||
-define(peername, peername).
|
||||
-define(will_message, will_message).
|
||||
-define(clientinfo, clientinfo).
|
||||
-define(protocol, protocol).
|
||||
-define(offline_info, offline_info).
|
||||
|
||||
-endif.
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2021-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2021-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -25,6 +25,8 @@
|
|||
-define(HP_AUTHN, 970).
|
||||
-define(HP_AUTHZ, 960).
|
||||
-define(HP_SYS_MSGS, 950).
|
||||
-define(HP_SCHEMA_VALIDATION, 945).
|
||||
-define(HP_MESSAGE_TRANSFORMATION, 943).
|
||||
-define(HP_TOPIC_METRICS, 940).
|
||||
-define(HP_RETAINER, 930).
|
||||
-define(HP_AUTO_SUB, 920).
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed 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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-ifndef(EMQX_METRICS_HRL).
|
||||
-define(EMQX_METRICS_HRL, true).
|
||||
|
||||
%% Bytes sent and received
|
||||
-define(BYTES_METRICS, [
|
||||
{counter, 'bytes.received', <<"Number of bytes received ">>},
|
||||
{counter, 'bytes.sent', <<"Number of bytes sent on this connection">>}
|
||||
]).
|
||||
|
||||
%% Packets sent and received
|
||||
-define(PACKET_METRICS, [
|
||||
{counter, 'packets.received', <<"Number of received packet">>},
|
||||
{counter, 'packets.sent', <<"Number of sent packet">>},
|
||||
{counter, 'packets.connect.received', <<"Number of received CONNECT packet">>},
|
||||
{counter, 'packets.connack.sent', <<"Number of sent CONNACK packet">>},
|
||||
{counter, 'packets.connack.error',
|
||||
<<"Number of received CONNECT packet with unsuccessful connections">>},
|
||||
{counter, 'packets.connack.auth_error',
|
||||
<<"Number of received CONNECT packet with failed Authentication">>},
|
||||
{counter, 'packets.publish.received', <<"Number of received PUBLISH packet">>},
|
||||
%% PUBLISH packets sent
|
||||
{counter, 'packets.publish.sent', <<"Number of sent PUBLISH packet">>},
|
||||
%% PUBLISH packet_id inuse
|
||||
{counter, 'packets.publish.inuse',
|
||||
<<"Number of received PUBLISH packet with occupied identifiers">>},
|
||||
%% PUBLISH failed for error
|
||||
{counter, 'packets.publish.error',
|
||||
<<"Number of received PUBLISH packet that cannot be published">>},
|
||||
%% PUBLISH failed for auth error
|
||||
{counter, 'packets.publish.auth_error',
|
||||
<<"Number of received PUBLISH packets with failed the Authorization check">>},
|
||||
%% PUBLISH(QoS2) packets dropped
|
||||
{counter, 'packets.publish.dropped',
|
||||
<<"Number of messages discarded due to the receiving limit">>},
|
||||
%% PUBACK packets received
|
||||
{counter, 'packets.puback.received', <<"Number of received PUBACK packet">>},
|
||||
%% PUBACK packets sent
|
||||
{counter, 'packets.puback.sent', <<"Number of sent PUBACK packet">>},
|
||||
%% PUBACK packet_id inuse
|
||||
{counter, 'packets.puback.inuse',
|
||||
<<"Number of received PUBACK packet with occupied identifiers">>},
|
||||
%% PUBACK packets missed
|
||||
{counter, 'packets.puback.missed', <<"Number of received packet with identifiers.">>},
|
||||
%% PUBREC packets received
|
||||
{counter, 'packets.pubrec.received', <<"Number of received PUBREC packet">>},
|
||||
%% PUBREC packets sent
|
||||
{counter, 'packets.pubrec.sent', <<"Number of sent PUBREC packet">>},
|
||||
%% PUBREC packet_id inuse
|
||||
{counter, 'packets.pubrec.inuse',
|
||||
<<"Number of received PUBREC packet with occupied identifiers">>},
|
||||
%% PUBREC packets missed
|
||||
{counter, 'packets.pubrec.missed',
|
||||
<<"Number of received PUBREC packet with unknown identifiers">>},
|
||||
%% PUBREL packets received
|
||||
{counter, 'packets.pubrel.received', <<"Number of received PUBREL packet">>},
|
||||
%% PUBREL packets sent
|
||||
{counter, 'packets.pubrel.sent', <<"Number of sent PUBREL packet">>},
|
||||
%% PUBREL packets missed
|
||||
{counter, 'packets.pubrel.missed',
|
||||
<<"Number of received PUBREC packet with unknown identifiers">>},
|
||||
%% PUBCOMP packets received
|
||||
{counter, 'packets.pubcomp.received', <<"Number of received PUBCOMP packet">>},
|
||||
%% PUBCOMP packets sent
|
||||
{counter, 'packets.pubcomp.sent', <<"Number of sent PUBCOMP packet">>},
|
||||
%% PUBCOMP packet_id inuse
|
||||
{counter, 'packets.pubcomp.inuse',
|
||||
<<"Number of received PUBCOMP packet with occupied identifiers">>},
|
||||
%% PUBCOMP packets missed
|
||||
{counter, 'packets.pubcomp.missed', <<"Number of missed PUBCOMP packet">>},
|
||||
%% SUBSCRIBE Packets received
|
||||
{counter, 'packets.subscribe.received', <<"Number of received SUBSCRIBE packet">>},
|
||||
%% SUBSCRIBE error
|
||||
{counter, 'packets.subscribe.error',
|
||||
<<"Number of received SUBSCRIBE packet with failed subscriptions">>},
|
||||
%% SUBSCRIBE failed for not auth
|
||||
{counter, 'packets.subscribe.auth_error',
|
||||
<<"Number of received SUBACK packet with failed Authorization check">>},
|
||||
%% SUBACK packets sent
|
||||
{counter, 'packets.suback.sent', <<"Number of sent SUBACK packet">>},
|
||||
%% UNSUBSCRIBE Packets received
|
||||
{counter, 'packets.unsubscribe.received', <<"Number of received UNSUBSCRIBE packet">>},
|
||||
%% UNSUBSCRIBE error
|
||||
{counter, 'packets.unsubscribe.error',
|
||||
<<"Number of received UNSUBSCRIBE packet with failed unsubscriptions">>},
|
||||
%% UNSUBACK Packets sent
|
||||
{counter, 'packets.unsuback.sent', <<"Number of sent UNSUBACK packet">>},
|
||||
%% PINGREQ packets received
|
||||
{counter, 'packets.pingreq.received', <<"Number of received PINGREQ packet">>},
|
||||
%% PINGRESP Packets sent
|
||||
{counter, 'packets.pingresp.sent', <<"Number of sent PUBRESP packet">>},
|
||||
%% DISCONNECT Packets received
|
||||
{counter, 'packets.disconnect.received', <<"Number of received DISCONNECT packet">>},
|
||||
%% DISCONNECT Packets sent
|
||||
{counter, 'packets.disconnect.sent', <<"Number of sent DISCONNECT packet">>},
|
||||
%% Auth Packets received
|
||||
{counter, 'packets.auth.received', <<"Number of received AUTH packet">>},
|
||||
%% Auth Packets sent
|
||||
{counter, 'packets.auth.sent', <<"Number of sent AUTH packet">>}
|
||||
]).
|
||||
|
||||
%% Messages sent/received and pubsub
|
||||
-define(MESSAGE_METRICS, [
|
||||
%% All Messages received
|
||||
{counter, 'messages.received', <<
|
||||
"Number of messages received from the client, equal to the sum of "
|
||||
"messages.qos0.received, messages.qos1.received and messages.qos2.received"
|
||||
>>},
|
||||
%% All Messages sent
|
||||
{counter, 'messages.sent', <<
|
||||
"Number of messages sent to the client, equal to the sum of "
|
||||
"messages.qos0.sent, messages.qos1.sent and messages.qos2.sent"
|
||||
>>},
|
||||
%% QoS0 Messages received
|
||||
{counter, 'messages.qos0.received', <<"Number of QoS 0 messages received from clients">>},
|
||||
%% QoS0 Messages sent
|
||||
{counter, 'messages.qos0.sent', <<"Number of QoS 0 messages sent to clients">>},
|
||||
%% QoS1 Messages received
|
||||
{counter, 'messages.qos1.received', <<"Number of QoS 1 messages received from clients">>},
|
||||
%% QoS1 Messages sent
|
||||
{counter, 'messages.qos1.sent', <<"Number of QoS 1 messages sent to clients">>},
|
||||
%% QoS2 Messages received
|
||||
{counter, 'messages.qos2.received', <<"Number of QoS 2 messages received from clients">>},
|
||||
%% QoS2 Messages sent
|
||||
{counter, 'messages.qos2.sent', <<"Number of QoS 2 messages sent to clients">>},
|
||||
%% PubSub Metrics
|
||||
|
||||
%% Messages Publish
|
||||
{counter, 'messages.publish',
|
||||
<<"Number of messages published in addition to system messages">>},
|
||||
%% Messages dropped due to no subscribers
|
||||
{counter, 'messages.dropped',
|
||||
<<"Number of messages dropped before forwarding to the subscription process">>},
|
||||
%% Messages that failed validations
|
||||
{counter, 'messages.validation_failed', <<"Number of message validation failed">>},
|
||||
%% Messages that passed validations
|
||||
{counter, 'messages.validation_succeeded', <<"Number of message validation successful">>},
|
||||
%% % Messages that failed transformations
|
||||
{counter, 'messages.transformation_failed', <<"Number fo message transformation failed">>},
|
||||
%% % Messages that passed transformations
|
||||
{counter, 'messages.transformation_succeeded',
|
||||
<<"Number fo message transformation succeeded">>},
|
||||
%% QoS2 Messages expired
|
||||
{counter, 'messages.dropped.await_pubrel_timeout',
|
||||
<<"Number of messages dropped due to waiting PUBREL timeout">>},
|
||||
%% Messages dropped
|
||||
{counter, 'messages.dropped.no_subscribers',
|
||||
<<"Number of messages dropped due to no subscribers">>},
|
||||
%% Messages forward
|
||||
{counter, 'messages.forward', <<"Number of messages forwarded to other nodes">>},
|
||||
%% Messages delayed
|
||||
{counter, 'messages.delayed', <<"Number of delay-published messages">>},
|
||||
%% Messages delivered
|
||||
{counter, 'messages.delivered',
|
||||
<<"Number of messages forwarded to the subscription process internally">>},
|
||||
%% Messages acked
|
||||
{counter, 'messages.acked', <<"Number of received PUBACK and PUBREC packet">>},
|
||||
%% Messages persistently stored
|
||||
{counter, 'messages.persisted', <<"Number of message persisted">>}
|
||||
]).
|
||||
|
||||
%% Delivery metrics
|
||||
-define(DELIVERY_METRICS, [
|
||||
%% All Dropped during delivery
|
||||
{counter, 'delivery.dropped', <<"Total number of discarded messages when sending">>},
|
||||
%% Dropped due to no_local
|
||||
{counter, 'delivery.dropped.no_local', <<
|
||||
"Number of messages that were dropped due to the No Local subscription "
|
||||
"option when sending"
|
||||
>>},
|
||||
%% Dropped due to message too large
|
||||
{counter, 'delivery.dropped.too_large', <<
|
||||
"The number of messages that were dropped because the length exceeded "
|
||||
"the limit when sending"
|
||||
>>},
|
||||
%% Dropped qos0 message
|
||||
{counter, 'delivery.dropped.qos0_msg', <<
|
||||
"Number of messages with QoS 0 that were dropped because the message "
|
||||
"queue was full when sending"
|
||||
>>},
|
||||
%% Dropped due to queue full
|
||||
{counter, 'delivery.dropped.queue_full', <<
|
||||
"Number of messages with a non-zero QoS that were dropped because the "
|
||||
"message queue was full when sending"
|
||||
>>},
|
||||
%% Dropped due to expired
|
||||
{counter, 'delivery.dropped.expired',
|
||||
<<"Number of messages dropped due to message expiration on sending">>}
|
||||
]).
|
||||
|
||||
%% Client Lifecircle metrics
|
||||
-define(CLIENT_METRICS, [
|
||||
{counter, 'client.connect', <<"Number of client connections">>},
|
||||
{counter, 'client.connack', <<"Number of CONNACK packet sent">>},
|
||||
{counter, 'client.connected', <<"Number of successful client connected">>},
|
||||
{counter, 'client.authenticate', <<"Number of client Authentication">>},
|
||||
{counter, 'client.auth.anonymous', <<"Number of clients who log in anonymously">>},
|
||||
{counter, 'client.authorize', <<"Number of Authorization rule checks">>},
|
||||
{counter, 'client.subscribe', <<"Number of client subscriptions">>},
|
||||
{counter, 'client.unsubscribe', <<"Number of client unsubscriptions">>},
|
||||
{counter, 'client.disconnected', <<"Number of client disconnects">>}
|
||||
]).
|
||||
|
||||
%% Session Lifecircle metrics
|
||||
-define(SESSION_METRICS, [
|
||||
{counter, 'session.created', <<"Number of sessions created">>},
|
||||
{counter, 'session.resumed',
|
||||
<<"Number of sessions resumed because Clean Session or Clean Start is false">>},
|
||||
{counter, 'session.takenover',
|
||||
<<"Number of sessions takenover because Clean Session or Clean Start is false">>},
|
||||
{counter, 'session.discarded',
|
||||
<<"Number of sessions dropped because Clean Session or Clean Start is true">>},
|
||||
{counter, 'session.terminated', <<"Number of terminated sessions">>}
|
||||
]).
|
||||
|
||||
%% Statistic metrics for ACL checking
|
||||
-define(STASTS_ACL_METRICS, [
|
||||
{counter, 'authorization.allow', <<"Number of Authorization allow">>},
|
||||
{counter, 'authorization.deny', <<"Number of Authorization deny">>},
|
||||
{counter, 'authorization.cache_hit', <<"Number of Authorization hits the cache">>},
|
||||
{counter, 'authorization.cache_miss', <<"Number of Authorization cache missing">>}
|
||||
]).
|
||||
|
||||
%% Statistic metrics for auth checking
|
||||
-define(STASTS_AUTHN_METRICS, [
|
||||
{counter, 'authentication.success', <<"Number of successful client Authentication">>},
|
||||
{counter, 'authentication.success.anonymous',
|
||||
<<"Number of successful client Authentication due to anonymous">>},
|
||||
{counter, 'authentication.failure', <<"Number of failed client Authentication">>}
|
||||
]).
|
||||
|
||||
%% Overload protection counters
|
||||
-define(OLP_METRICS, [
|
||||
{counter, 'overload_protection.delay.ok', <<"Number of overload protection delayed">>},
|
||||
{counter, 'overload_protection.delay.timeout',
|
||||
<<"Number of overload protection delay timeout">>},
|
||||
{counter, 'overload_protection.hibernation', <<"Number of overload protection hibernation">>},
|
||||
{counter, 'overload_protection.gc', <<"Number of overload protection garbage collection">>},
|
||||
{counter, 'overload_protection.new_conn',
|
||||
<<"Number of overload protection close new incoming connection">>}
|
||||
]).
|
||||
|
||||
-endif.
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -673,7 +673,6 @@ end).
|
|||
|
||||
-define(SHARE, "$share").
|
||||
-define(QUEUE, "$queue").
|
||||
-define(SHARE(Group, Topic), emqx_topic:join([<<?SHARE>>, Group, Topic])).
|
||||
|
||||
-define(REDISPATCH_TO(GROUP, TOPIC), {GROUP, TOPIC}).
|
||||
|
||||
|
@ -684,6 +683,7 @@ end).
|
|||
|
||||
-define(FRAME_PARSE_ERROR, frame_parse_error).
|
||||
-define(FRAME_SERIALIZE_ERROR, frame_serialize_error).
|
||||
|
||||
-define(THROW_FRAME_ERROR(Reason), erlang:throw({?FRAME_PARSE_ERROR, Reason})).
|
||||
-define(THROW_SERIALIZE_ERROR(Reason), erlang:throw({?FRAME_SERIALIZE_ERROR, Reason})).
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed 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.
|
||||
%%--------------------------------------------------------------------
|
||||
-ifndef(EMQX_PERSISTENT_MESSAGE_HRL).
|
||||
-define(EMQX_PERSISTENT_MESSAGE_HRL, true).
|
||||
|
||||
-define(PERSISTENT_MESSAGE_DB, messages).
|
||||
-define(PERSISTENCE_ENABLED, emqx_message_persistence_enabled).
|
||||
|
||||
-define(WITH_DURABILITY_ENABLED(DO),
|
||||
case is_persistence_enabled() of
|
||||
true -> DO;
|
||||
false -> {skipped, disabled}
|
||||
end
|
||||
).
|
||||
|
||||
-endif.
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -28,14 +28,19 @@
|
|||
%% cert
|
||||
-define(VAR_CERT_SUBJECT, "cert_subject").
|
||||
-define(VAR_CERT_CN_NAME, "cert_common_name").
|
||||
-define(VAR_CERT_PEM, "cert_pem").
|
||||
-define(PH_CERT_SUBJECT, ?PH(?VAR_CERT_SUBJECT)).
|
||||
-define(PH_CERT_CN_NAME, ?PH(?VAR_CERT_CN_NAME)).
|
||||
-define(PH_CERT_PEM, ?PH(?VAR_CERT_PEM)).
|
||||
|
||||
%% MQTT
|
||||
%% MQTT/Gateway
|
||||
-define(VAR_PASSWORD, "password").
|
||||
-define(VAR_CLIENTID, "clientid").
|
||||
-define(VAR_USERNAME, "username").
|
||||
-define(VAR_TOPIC, "topic").
|
||||
-define(VAR_ENDPOINT_NAME, "endpoint_name").
|
||||
-define(VAR_NS_CLIENT_ATTRS, {var_namespace, "client_attrs"}).
|
||||
|
||||
-define(PH_PASSWORD, ?PH(?VAR_PASSWORD)).
|
||||
-define(PH_CLIENTID, ?PH(?VAR_CLIENTID)).
|
||||
-define(PH_FROM_CLIENTID, ?PH("from_clientid")).
|
||||
|
@ -89,7 +94,7 @@
|
|||
-define(PH_NODE, ?PH("node")).
|
||||
-define(PH_REASON, ?PH("reason")).
|
||||
|
||||
-define(PH_ENDPOINT_NAME, ?PH("endpoint_name")).
|
||||
-define(PH_ENDPOINT_NAME, ?PH(?VAR_ENDPOINT_NAME)).
|
||||
-define(VAR_RETAIN, "retain").
|
||||
-define(PH_RETAIN, ?PH(?VAR_RETAIN)).
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2021-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2021-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -32,10 +32,7 @@
|
|||
%% `apps/emqx/src/bpapi/README.md'
|
||||
|
||||
%% Opensource edition
|
||||
-define(EMQX_RELEASE_CE, "5.5.0").
|
||||
-define(EMQX_RELEASE_CE, "5.8.0-alpha.1").
|
||||
|
||||
%% Enterprise edition
|
||||
-define(EMQX_RELEASE_EE, "5.5.0-alpha.1").
|
||||
|
||||
%% The HTTP API version
|
||||
-define(EMQX_API_VERSION, "5.0").
|
||||
-define(EMQX_RELEASE_EE, "5.8.0-alpha.1").
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -21,4 +21,9 @@
|
|||
-define(TOMBSTONE_CONFIG_CHANGE_REQ, mark_it_for_deletion).
|
||||
-define(CONFIG_NOT_FOUND_MAGIC, '$0tFound').
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% EE injections
|
||||
%%--------------------------------------------------------------------
|
||||
-define(EMQX_SSL_FUN_MFA(Name), {emqx_ssl_fun_mfa, Name}).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -20,4 +20,11 @@
|
|||
-define(IS_SESSION_IMPL_MEM(S), (is_tuple(S) andalso element(1, S) =:= session)).
|
||||
-define(IS_SESSION_IMPL_DS(S), (is_map_key(id, S))).
|
||||
|
||||
%% (Erlang) messages that a connection process should forward to the
|
||||
%% session handler.
|
||||
-record(session_message, {
|
||||
message :: term()
|
||||
}).
|
||||
-define(session_message(MSG), #session_message{message = MSG}).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2018-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed 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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-ifndef(EMQX_SHARED_SUB_HRL).
|
||||
-define(EMQX_SHARED_SUB_HRL, true).
|
||||
|
||||
%% Mnesia table for shared sub message routing
|
||||
-define(SHARED_SUBSCRIPTION, emqx_shared_subscription).
|
||||
|
||||
%% ETS tables for Shared PubSub
|
||||
-define(SHARED_SUBSCRIBER, emqx_shared_subscriber).
|
||||
-define(ALIVE_SHARED_SUBSCRIBERS, emqx_alive_shared_subscribers).
|
||||
-define(SHARED_SUBS_ROUND_ROBIN_COUNTER, emqx_shared_subscriber_round_robin_counter).
|
||||
|
||||
-endif.
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -20,17 +20,33 @@
|
|||
|
||||
-record(?TRACE, {
|
||||
name :: binary() | undefined | '_',
|
||||
type :: clientid | topic | ip_address | undefined | '_',
|
||||
type :: clientid | topic | ip_address | ruleid | undefined | '_',
|
||||
filter ::
|
||||
emqx_types:topic() | emqx_types:clientid() | emqx_trace:ip_address() | undefined | '_',
|
||||
emqx_types:topic()
|
||||
| emqx_types:clientid()
|
||||
| emqx_trace:ip_address()
|
||||
| emqx_trace:ruleid()
|
||||
| undefined
|
||||
| '_',
|
||||
enable = true :: boolean() | '_',
|
||||
payload_encode = text :: hex | text | hidden | '_',
|
||||
extra = #{} :: map() | '_',
|
||||
extra = #{formatter => text} :: #{formatter => text | json} | '_',
|
||||
start_at :: integer() | undefined | '_',
|
||||
end_at :: integer() | undefined | '_'
|
||||
}).
|
||||
|
||||
-record(emqx_trace_format_func_data, {
|
||||
function :: fun((any()) -> any()),
|
||||
data :: any()
|
||||
}).
|
||||
|
||||
-define(SHARD, ?COMMON_SHARD).
|
||||
-define(MAX_SIZE, 30).
|
||||
|
||||
-define(EMQX_TRACE_STOP_ACTION(REASON),
|
||||
{unrecoverable_error, {action_stopped_after_template_rendering, REASON}}
|
||||
).
|
||||
|
||||
-define(EMQX_TRACE_STOP_ACTION_MATCH, ?EMQX_TRACE_STOP_ACTION(_)).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2017-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -17,6 +17,7 @@
|
|||
%% HTTP API Auth
|
||||
-define(BAD_USERNAME_OR_PWD, 'BAD_USERNAME_OR_PWD').
|
||||
-define(BAD_API_KEY_OR_SECRET, 'BAD_API_KEY_OR_SECRET').
|
||||
-define(API_KEY_NOT_ALLOW, 'API_KEY_NOT_ALLOW').
|
||||
-define(API_KEY_NOT_ALLOW_MSG, <<"This API Key don't have permission to access this resource">>).
|
||||
|
||||
%% Bad Request
|
||||
|
@ -85,5 +86,6 @@
|
|||
{'SOURCE_ERROR', <<"Source error">>},
|
||||
{'UPDATE_FAILED', <<"Update failed">>},
|
||||
{'REST_FAILED', <<"Reset source or config failed">>},
|
||||
{'CLIENT_NOT_RESPONSE', <<"Client not responding">>}
|
||||
{'CLIENT_NOT_RESPONSE', <<"Client not responding">>},
|
||||
{'UNSUPPORTED_MEDIA_TYPE', <<"Unsupported media type">>}
|
||||
]).
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2018-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2018-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -30,7 +30,7 @@
|
|||
logger:log(
|
||||
Level,
|
||||
(Data),
|
||||
(Meta#{
|
||||
maps:merge(Meta, #{
|
||||
mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY},
|
||||
line => ?LINE
|
||||
})
|
||||
|
@ -40,14 +40,40 @@
|
|||
end
|
||||
).
|
||||
|
||||
%% NOTE: do not forget to use atom for msg and add every used msg to
|
||||
%% the default value of `log.throttling.msgs` list.
|
||||
-define(SLOG_THROTTLE(Level, Data),
|
||||
?SLOG_THROTTLE(Level, Data, #{})
|
||||
).
|
||||
|
||||
-define(SLOG_THROTTLE(Level, Data, Meta),
|
||||
?SLOG_THROTTLE(Level, undefined, Data, Meta)
|
||||
).
|
||||
|
||||
-define(SLOG_THROTTLE(Level, UniqueKey, Data, Meta),
|
||||
case logger:allow(Level, ?MODULE) of
|
||||
true ->
|
||||
(fun(#{msg := __Msg} = __Data) ->
|
||||
case emqx_log_throttler:allow(__Msg, UniqueKey) of
|
||||
true ->
|
||||
logger:log(Level, __Data, Meta);
|
||||
false ->
|
||||
?_DO_TRACE(Level, __Msg, maps:merge(__Data, Meta))
|
||||
end
|
||||
end)(
|
||||
Data
|
||||
);
|
||||
false ->
|
||||
ok
|
||||
end
|
||||
).
|
||||
|
||||
-define(AUDIT_HANDLER, emqx_audit).
|
||||
-define(TRACE_FILTER, emqx_trace_filter).
|
||||
-define(OWN_KEYS, [level, filters, filter_default, handlers]).
|
||||
|
||||
-define(TRACE(Tag, Msg, Meta), ?TRACE(debug, Tag, Msg, Meta)).
|
||||
|
||||
%% Only evaluate when necessary
|
||||
-define(TRACE(Level, Tag, Msg, Meta), begin
|
||||
%% Internal macro
|
||||
-define(_DO_TRACE(Tag, Msg, Meta),
|
||||
case persistent_term:get(?TRACE_FILTER, []) of
|
||||
[] -> ok;
|
||||
%% We can't bind filter list to a variable because we pollute the calling scope with it.
|
||||
|
@ -55,10 +81,17 @@
|
|||
%% because this adds overhead to the happy path.
|
||||
%% So evaluate `persistent_term:get` twice.
|
||||
_ -> emqx_trace:log(persistent_term:get(?TRACE_FILTER, []), Msg, (Meta)#{trace_tag => Tag})
|
||||
end,
|
||||
end
|
||||
).
|
||||
|
||||
-define(TRACE(Tag, Msg, Meta), ?TRACE(debug, Tag, Msg, Meta)).
|
||||
|
||||
%% Only evaluate when necessary
|
||||
-define(TRACE(Level, Tag, Msg, Meta), begin
|
||||
?_DO_TRACE(Tag, Msg, Meta),
|
||||
?SLOG(
|
||||
Level,
|
||||
(emqx_trace_formatter:format_meta_map(Meta))#{msg => Msg, tag => Tag},
|
||||
(Meta)#{msg => Msg, tag => Tag},
|
||||
#{is_trace => false}
|
||||
)
|
||||
end).
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2019-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2019-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -14,7 +14,7 @@
|
|||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-type maybe(T) :: undefined | T.
|
||||
-type option(T) :: undefined | T.
|
||||
|
||||
-type startlink_ret() :: {ok, pid()} | ignore | {error, term()}.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%--------------------------------------------------------------------
|
||||
-module(emqx_persistent_session_ds_SUITE).
|
||||
|
||||
|
@ -18,15 +18,23 @@
|
|||
%% CT boilerplate
|
||||
%%------------------------------------------------------------------------------
|
||||
|
||||
suite() ->
|
||||
[{timetrap, {seconds, 60}}].
|
||||
|
||||
all() ->
|
||||
emqx_common_test_helpers:all(?MODULE).
|
||||
|
||||
init_per_suite(Config) ->
|
||||
TCApps = emqx_cth_suite:start(
|
||||
app_specs(),
|
||||
#{work_dir => emqx_cth_suite:work_dir(Config)}
|
||||
),
|
||||
[{tc_apps, TCApps} | Config].
|
||||
case emqx_ds_test_helpers:skip_if_norepl() of
|
||||
false ->
|
||||
TCApps = emqx_cth_suite:start(
|
||||
app_specs(),
|
||||
#{work_dir => emqx_cth_suite:work_dir(Config)}
|
||||
),
|
||||
[{tc_apps, TCApps} | Config];
|
||||
Yes ->
|
||||
Yes
|
||||
end.
|
||||
|
||||
end_per_suite(Config) ->
|
||||
TCApps = ?config(tc_apps, Config),
|
||||
|
@ -51,12 +59,12 @@ init_per_testcase(TestCase, Config) when
|
|||
init_per_testcase(t_session_gc = TestCase, Config) ->
|
||||
Opts = #{
|
||||
n => 3,
|
||||
roles => [core, core, replicant],
|
||||
roles => [core, core, core],
|
||||
extra_emqx_conf =>
|
||||
"\n session_persistence {"
|
||||
"\n last_alive_update_interval = 500ms "
|
||||
"\n session_gc_interval = 2s "
|
||||
"\n session_gc_batch_size = 1 "
|
||||
"\n durable_sessions {"
|
||||
"\n heartbeat_interval = 500ms "
|
||||
"\n session_gc_interval = 1s "
|
||||
"\n session_gc_batch_size = 2 "
|
||||
"\n }"
|
||||
},
|
||||
Cluster = cluster(Opts),
|
||||
|
@ -82,13 +90,15 @@ end_per_testcase(TestCase, Config) when
|
|||
Nodes = ?config(nodes, Config),
|
||||
emqx_common_test_helpers:call_janitor(60_000),
|
||||
ok = emqx_cth_cluster:stop(Nodes),
|
||||
snabbkaffe:stop(),
|
||||
ok;
|
||||
end_per_testcase(_TestCase, _Config) ->
|
||||
emqx_common_test_helpers:call_janitor(60_000),
|
||||
snabbkaffe:stop(),
|
||||
ok.
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% Helper fns
|
||||
%% Helper functions
|
||||
%%------------------------------------------------------------------------------
|
||||
|
||||
cluster(#{n := N} = Opts) ->
|
||||
|
@ -113,10 +123,10 @@ app_specs() ->
|
|||
app_specs(_Opts = #{}).
|
||||
|
||||
app_specs(Opts) ->
|
||||
DefaultEMQXConf = "durable_sessions {enable = true, renew_streams_interval = 1s}",
|
||||
ExtraEMQXConf = maps:get(extra_emqx_conf, Opts, ""),
|
||||
[
|
||||
emqx_durable_storage,
|
||||
{emqx, "session_persistence = {enable = true}" ++ ExtraEMQXConf}
|
||||
{emqx, DefaultEMQXConf ++ ExtraEMQXConf}
|
||||
].
|
||||
|
||||
get_mqtt_port(Node, Type) ->
|
||||
|
@ -130,29 +140,30 @@ wait_nodeup(Node) ->
|
|||
pong = net_adm:ping(Node)
|
||||
).
|
||||
|
||||
wait_gen_rpc_down(_NodeSpec = #{apps := Apps}) ->
|
||||
#{override_env := Env} = proplists:get_value(gen_rpc, Apps),
|
||||
Port = proplists:get_value(tcp_server_port, Env),
|
||||
?retry(
|
||||
_Sleep0 = 500,
|
||||
_Attempts0 = 50,
|
||||
false = emqx_common_test_helpers:is_tcp_server_available("127.0.0.1", Port)
|
||||
).
|
||||
|
||||
start_client(Opts0 = #{}) ->
|
||||
Defaults = #{
|
||||
port => 1883,
|
||||
proto_ver => v5,
|
||||
properties => #{'Session-Expiry-Interval' => 300}
|
||||
},
|
||||
Opts = maps:to_list(emqx_utils_maps:deep_merge(Defaults, Opts0)),
|
||||
ct:pal("starting client with opts:\n ~p", [Opts]),
|
||||
{ok, Client} = emqtt:start_link(Opts),
|
||||
Opts = emqx_utils_maps:deep_merge(Defaults, Opts0),
|
||||
?tp(notice, "starting client", Opts),
|
||||
{ok, Client} = emqtt:start_link(maps:to_list(Opts)),
|
||||
unlink(Client),
|
||||
on_exit(fun() -> catch emqtt:stop(Client) end),
|
||||
Client.
|
||||
|
||||
start_connect_client(Opts = #{}) ->
|
||||
Client = start_client(Opts),
|
||||
?assertMatch({ok, _}, emqtt:connect(Client)),
|
||||
Client.
|
||||
|
||||
mk_clientid(Prefix, ID) ->
|
||||
iolist_to_binary(io_lib:format("~p/~p", [Prefix, ID])).
|
||||
|
||||
restart_node(Node, NodeSpec) ->
|
||||
?tp(will_restart_node, #{}),
|
||||
emqx_cth_cluster:restart(Node, NodeSpec),
|
||||
emqx_cth_cluster:restart(NodeSpec),
|
||||
wait_nodeup(Node),
|
||||
?tp(restarted_node, #{}),
|
||||
ok.
|
||||
|
@ -161,58 +172,44 @@ is_persistent_connect_opts(#{properties := #{'Session-Expiry-Interval' := EI}})
|
|||
EI > 0.
|
||||
|
||||
list_all_sessions(Node) ->
|
||||
erpc:call(Node, emqx_persistent_session_ds, list_all_sessions, []).
|
||||
erpc:call(Node, emqx_persistent_session_ds_state, list_sessions, []).
|
||||
|
||||
list_all_subscriptions(Node) ->
|
||||
erpc:call(Node, emqx_persistent_session_ds, list_all_subscriptions, []).
|
||||
Sessions = list_all_sessions(Node),
|
||||
lists:flatmap(
|
||||
fun(ClientId) ->
|
||||
#{s := #{subscriptions := Subs}} = erpc:call(
|
||||
Node, emqx_persistent_session_ds, print_session, [ClientId]
|
||||
),
|
||||
maps:to_list(Subs)
|
||||
end,
|
||||
Sessions
|
||||
).
|
||||
|
||||
list_all_pubranges(Node) ->
|
||||
erpc:call(Node, emqx_persistent_session_ds, list_all_pubranges, []).
|
||||
|
||||
prop_only_cores_run_gc(CoreNodes) ->
|
||||
{"only core nodes run gc", fun(Trace) -> ?MODULE:prop_only_cores_run_gc(Trace, CoreNodes) end}.
|
||||
prop_only_cores_run_gc(Trace, CoreNodes) ->
|
||||
GCNodes = lists:usort([
|
||||
N
|
||||
|| #{
|
||||
?snk_kind := K,
|
||||
?snk_meta := #{node := N}
|
||||
} <- Trace,
|
||||
lists:member(K, [ds_session_gc, ds_session_gc_lock_taken]),
|
||||
N =/= node()
|
||||
]),
|
||||
?assertEqual(lists:usort(CoreNodes), GCNodes).
|
||||
session_open(Node, ClientId) ->
|
||||
ClientInfo = #{},
|
||||
ConnInfo = #{peername => {undefined, undefined}, proto_name => <<"MQTT">>, proto_ver => 5},
|
||||
WillMsg = undefined,
|
||||
erpc:call(
|
||||
Node,
|
||||
emqx_persistent_session_ds,
|
||||
session_open,
|
||||
[ClientId, ClientInfo, ConnInfo, WillMsg]
|
||||
).
|
||||
|
||||
force_last_alive_at(ClientId, Time) ->
|
||||
{ok, S0} = emqx_persistent_session_ds_state:open(ClientId),
|
||||
S = emqx_persistent_session_ds_state:set_last_alive_at(Time, S0),
|
||||
_ = emqx_persistent_session_ds_state:commit(S),
|
||||
ok.
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% Testcases
|
||||
%%------------------------------------------------------------------------------
|
||||
|
||||
t_non_persistent_session_subscription(_Config) ->
|
||||
ClientId = atom_to_binary(?FUNCTION_NAME),
|
||||
SubTopicFilter = <<"t/#">>,
|
||||
?check_trace(
|
||||
begin
|
||||
?tp(notice, "starting", #{}),
|
||||
Client = start_client(#{
|
||||
clientid => ClientId,
|
||||
properties => #{'Session-Expiry-Interval' => 0}
|
||||
}),
|
||||
{ok, _} = emqtt:connect(Client),
|
||||
?tp(notice, "subscribing", #{}),
|
||||
{ok, _, [?RC_GRANTED_QOS_2]} = emqtt:subscribe(Client, SubTopicFilter, qos2),
|
||||
|
||||
ok = emqtt:stop(Client),
|
||||
|
||||
ok
|
||||
end,
|
||||
fun(Trace) ->
|
||||
ct:pal("trace:\n ~p", [Trace]),
|
||||
?assertEqual([], ?of_kind(ds_session_subscription_added, Trace)),
|
||||
ok
|
||||
end
|
||||
),
|
||||
ok.
|
||||
|
||||
t_session_subscription_idempotency(Config) ->
|
||||
[Node1Spec | _] = ?config(node_specs, Config),
|
||||
[Node1] = ?config(nodes, Config),
|
||||
|
@ -220,6 +217,7 @@ t_session_subscription_idempotency(Config) ->
|
|||
SubTopicFilter = <<"t/+">>,
|
||||
ClientId = <<"myclientid">>,
|
||||
?check_trace(
|
||||
#{timetrap => 30_000},
|
||||
begin
|
||||
?force_ordering(
|
||||
#{?snk_kind := persistent_session_ds_subscription_added},
|
||||
|
@ -260,11 +258,8 @@ t_session_subscription_idempotency(Config) ->
|
|||
|
||||
ok
|
||||
end,
|
||||
fun(Trace) ->
|
||||
ct:pal("trace:\n ~p", [Trace]),
|
||||
Session = erpc:call(
|
||||
Node1, emqx_persistent_session_ds, session_open, [ClientId, _ConnInfo = #{}]
|
||||
),
|
||||
fun(_Trace) ->
|
||||
Session = session_open(Node1, ClientId),
|
||||
?assertMatch(
|
||||
#{SubTopicFilter := #{}},
|
||||
emqx_session:info(subscriptions, Session)
|
||||
|
@ -281,11 +276,11 @@ t_session_unsubscription_idempotency(Config) ->
|
|||
SubTopicFilter = <<"t/+">>,
|
||||
ClientId = <<"myclientid">>,
|
||||
?check_trace(
|
||||
#{timetrap => 30_000},
|
||||
begin
|
||||
?force_ordering(
|
||||
#{
|
||||
?snk_kind := persistent_session_ds_subscription_delete,
|
||||
?snk_span := {complete, _}
|
||||
?snk_kind := persistent_session_ds_subscription_delete
|
||||
},
|
||||
_NEvents0 = 1,
|
||||
#{?snk_kind := will_restart_node},
|
||||
|
@ -336,11 +331,8 @@ t_session_unsubscription_idempotency(Config) ->
|
|||
|
||||
ok
|
||||
end,
|
||||
fun(Trace) ->
|
||||
ct:pal("trace:\n ~p", [Trace]),
|
||||
Session = erpc:call(
|
||||
Node1, emqx_persistent_session_ds, session_open, [ClientId, _ConnInfo = #{}]
|
||||
),
|
||||
fun(_Trace) ->
|
||||
Session = session_open(Node1, ClientId),
|
||||
?assertEqual(
|
||||
#{},
|
||||
emqx_session:info(subscriptions, Session)
|
||||
|
@ -385,6 +377,7 @@ do_t_session_discard(Params) ->
|
|||
ReconnectOpts = ReconnectOpts0#{clientid => ClientId},
|
||||
SubTopicFilter = <<"t/+">>,
|
||||
?check_trace(
|
||||
#{timetrap => 30_000},
|
||||
begin
|
||||
?tp(notice, "starting", #{}),
|
||||
Client0 = start_client(#{
|
||||
|
@ -402,40 +395,38 @@ do_t_session_discard(Params) ->
|
|||
?retry(
|
||||
_Sleep0 = 100,
|
||||
_Attempts0 = 50,
|
||||
true = map_size(emqx_persistent_session_ds:list_all_streams()) > 0
|
||||
#{} = emqx_persistent_session_ds_state:print_session(ClientId)
|
||||
),
|
||||
ok = emqtt:stop(Client0),
|
||||
?tp(notice, "disconnected", #{}),
|
||||
|
||||
?tp(notice, "reconnecting", #{}),
|
||||
%% we still have streams
|
||||
?assert(map_size(emqx_persistent_session_ds:list_all_streams()) > 0),
|
||||
%% we still have the session:
|
||||
?assertMatch(#{}, emqx_persistent_session_ds_state:print_session(ClientId)),
|
||||
Client1 = start_client(ReconnectOpts),
|
||||
{ok, _} = emqtt:connect(Client1),
|
||||
?assertEqual([], emqtt:subscriptions(Client1)),
|
||||
case is_persistent_connect_opts(ReconnectOpts) of
|
||||
true ->
|
||||
?assertMatch(#{ClientId := _}, emqx_persistent_session_ds:list_all_sessions());
|
||||
?assertMatch(#{}, emqx_persistent_session_ds_state:print_session(ClientId));
|
||||
false ->
|
||||
?assertEqual(#{}, emqx_persistent_session_ds:list_all_sessions())
|
||||
?assertEqual(
|
||||
undefined, emqx_persistent_session_ds_state:print_session(ClientId)
|
||||
)
|
||||
end,
|
||||
?assertEqual(#{}, emqx_persistent_session_ds:list_all_subscriptions()),
|
||||
?assertEqual([], emqx_persistent_session_ds_router:topics()),
|
||||
?assertEqual(#{}, emqx_persistent_session_ds:list_all_streams()),
|
||||
?assertEqual(#{}, emqx_persistent_session_ds:list_all_pubranges()),
|
||||
ok = emqtt:stop(Client1),
|
||||
?tp(notice, "disconnected", #{}),
|
||||
|
||||
ok
|
||||
end,
|
||||
fun(Trace) ->
|
||||
ct:pal("trace:\n ~p", [Trace]),
|
||||
ok
|
||||
end
|
||||
[]
|
||||
),
|
||||
ok.
|
||||
|
||||
t_session_expiration1(Config) ->
|
||||
%% This testcase verifies that the properties passed in the
|
||||
%% CONNECT packet are respected by the GC process:
|
||||
ClientId = atom_to_binary(?FUNCTION_NAME),
|
||||
Opts = #{
|
||||
clientid => ClientId,
|
||||
|
@ -448,6 +439,9 @@ t_session_expiration1(Config) ->
|
|||
do_t_session_expiration(Config, Opts).
|
||||
|
||||
t_session_expiration2(Config) ->
|
||||
%% This testcase updates the expiry interval for the session in
|
||||
%% the _DISCONNECT_ packet. This setting should be respected by GC
|
||||
%% process:
|
||||
ClientId = atom_to_binary(?FUNCTION_NAME),
|
||||
Opts = #{
|
||||
clientid => ClientId,
|
||||
|
@ -462,6 +456,8 @@ t_session_expiration2(Config) ->
|
|||
do_t_session_expiration(Config, Opts).
|
||||
|
||||
do_t_session_expiration(_Config, Opts) ->
|
||||
%% Sequence is a list of pairs of properties passed through the
|
||||
%% CONNECT and for the DISCONNECT for each session:
|
||||
#{
|
||||
clientid := ClientId,
|
||||
sequence := [
|
||||
|
@ -472,13 +468,14 @@ do_t_session_expiration(_Config, Opts) ->
|
|||
} = Opts,
|
||||
CommonParams = #{proto_ver => v5, clientid => ClientId},
|
||||
?check_trace(
|
||||
#{timetrap => 30_000},
|
||||
begin
|
||||
Topic = <<"some/topic">>,
|
||||
Params0 = maps:merge(CommonParams, FirstConn),
|
||||
Client0 = start_client(Params0),
|
||||
{ok, _} = emqtt:connect(Client0),
|
||||
{ok, _, [?RC_GRANTED_QOS_2]} = emqtt:subscribe(Client0, Topic, ?QOS_2),
|
||||
Subs0 = emqx_persistent_session_ds:list_all_subscriptions(),
|
||||
#{s := #{subscriptions := Subs0}} = emqx_persistent_session_ds:print_session(ClientId),
|
||||
?assertEqual(1, map_size(Subs0), #{subs => Subs0}),
|
||||
Info0 = maps:from_list(emqtt:info(Client0)),
|
||||
?assertEqual(0, maps:get(session_present, Info0), #{info => Info0}),
|
||||
|
@ -493,7 +490,7 @@ do_t_session_expiration(_Config, Opts) ->
|
|||
?assertEqual([], Subs1),
|
||||
emqtt:disconnect(Client1, ?RC_NORMAL_DISCONNECTION, SecondDisconn),
|
||||
|
||||
ct:sleep(1_500),
|
||||
ct:sleep(2_500),
|
||||
|
||||
Params2 = maps:merge(CommonParams, ThirdConn),
|
||||
Client2 = start_client(Params2),
|
||||
|
@ -505,9 +502,9 @@ do_t_session_expiration(_Config, Opts) ->
|
|||
emqtt:publish(Client2, Topic, <<"payload">>),
|
||||
?assertNotReceive({publish, #{topic := Topic}}),
|
||||
%% ensure subscriptions are absent from table.
|
||||
?assertEqual(#{}, emqx_persistent_session_ds:list_all_subscriptions()),
|
||||
#{s := #{subscriptions := Subs3}} = emqx_persistent_session_ds:print_session(ClientId),
|
||||
?assertEqual([], maps:to_list(Subs3)),
|
||||
emqtt:disconnect(Client2, ?RC_NORMAL_DISCONNECTION, ThirdDisconn),
|
||||
|
||||
ok
|
||||
end,
|
||||
[]
|
||||
|
@ -515,14 +512,13 @@ do_t_session_expiration(_Config, Opts) ->
|
|||
ok.
|
||||
|
||||
t_session_gc(Config) ->
|
||||
GCInterval = ?config(gc_interval, Config),
|
||||
[Node1, Node2, _Node3] = Nodes = ?config(nodes, Config),
|
||||
CoreNodes = [Node1, Node2],
|
||||
[Node1, _Node2, _Node3] = Nodes = ?config(nodes, Config),
|
||||
[
|
||||
Port1,
|
||||
Port2,
|
||||
Port3
|
||||
] = lists:map(fun(N) -> get_mqtt_port(N, tcp) end, Nodes),
|
||||
ct:pal("Ports: ~p", [[Port1, Port2, Port3]]),
|
||||
CommonParams = #{
|
||||
clean_start => false,
|
||||
proto_ver => v5
|
||||
|
@ -539,15 +535,16 @@ t_session_gc(Config) ->
|
|||
end,
|
||||
|
||||
?check_trace(
|
||||
#{timetrap => 30_000},
|
||||
begin
|
||||
ClientId0 = <<"session_gc0">>,
|
||||
Client0 = StartClient(ClientId0, Port1, 30),
|
||||
|
||||
ClientId1 = <<"session_gc1">>,
|
||||
Client1 = StartClient(ClientId1, Port2, 1),
|
||||
Client1 = StartClient(ClientId1, Port1, 30),
|
||||
|
||||
ClientId2 = <<"session_gc2">>,
|
||||
Client2 = StartClient(ClientId2, Port3, 1),
|
||||
Client2 = StartClient(ClientId2, Port2, 1),
|
||||
|
||||
ClientId3 = <<"session_gc3">>,
|
||||
Client3 = StartClient(ClientId3, Port3, 1),
|
||||
|
||||
lists:foreach(
|
||||
fun(Client) ->
|
||||
|
@ -557,55 +554,51 @@ t_session_gc(Config) ->
|
|||
{ok, _} = emqtt:publish(Client, Topic, Payload, ?QOS_1),
|
||||
ok
|
||||
end,
|
||||
[Client0, Client1, Client2]
|
||||
[Client1, Client2, Client3]
|
||||
),
|
||||
|
||||
%% Clients are still alive; no session is garbage collected.
|
||||
Res0 = ?block_until(
|
||||
#{
|
||||
?snk_kind := ds_session_gc,
|
||||
?snk_span := {complete, _},
|
||||
?snk_meta := #{node := N}
|
||||
} when
|
||||
N =/= node(),
|
||||
3 * GCInterval + 1_000
|
||||
),
|
||||
?assertMatch({ok, _}, Res0),
|
||||
{ok, #{?snk_meta := #{time := T0}}} = Res0,
|
||||
Sessions0 = list_all_sessions(Node1),
|
||||
Subs0 = list_all_subscriptions(Node1),
|
||||
?assertEqual(3, map_size(Sessions0), #{sessions => Sessions0}),
|
||||
?assertEqual(3, map_size(Subs0), #{subs => Subs0}),
|
||||
|
||||
%% Now we disconnect 2 of them; only those should be GC'ed.
|
||||
?tp(notice, "waiting for gc", #{}),
|
||||
?assertMatch(
|
||||
{ok, {ok, _}},
|
||||
?wait_async_action(
|
||||
emqtt:stop(Client1),
|
||||
#{?snk_kind := terminate},
|
||||
1_000
|
||||
{ok, _},
|
||||
?block_until(
|
||||
#{
|
||||
?snk_kind := ds_session_gc,
|
||||
?snk_span := {complete, _},
|
||||
?snk_meta := #{node := N}
|
||||
} when N =/= node()
|
||||
)
|
||||
),
|
||||
ct:pal("disconnected client1"),
|
||||
?assertMatch([_, _, _], list_all_sessions(Node1), sessions),
|
||||
?assertMatch([_, _, _], list_all_subscriptions(Node1), subscriptions),
|
||||
?tp(notice, "gc ran", #{}),
|
||||
|
||||
%% Now we disconnect 2 of them; only those should be GC'ed.
|
||||
|
||||
?tp(notice, "disconnecting client1", #{}),
|
||||
?assertMatch(
|
||||
{ok, {ok, _}},
|
||||
?wait_async_action(
|
||||
emqtt:stop(Client2),
|
||||
#{?snk_kind := terminate},
|
||||
1_000
|
||||
#{?snk_kind := terminate}
|
||||
)
|
||||
),
|
||||
ct:pal("disconnected client2"),
|
||||
?tp(notice, "disconnected client1", #{}),
|
||||
?assertMatch(
|
||||
{ok, {ok, _}},
|
||||
?wait_async_action(
|
||||
emqtt:stop(Client3),
|
||||
#{?snk_kind := terminate}
|
||||
)
|
||||
),
|
||||
?tp(notice, "disconnected client2", #{}),
|
||||
?assertMatch(
|
||||
{ok, _},
|
||||
?block_until(
|
||||
#{
|
||||
?snk_kind := ds_session_gc_cleaned,
|
||||
?snk_meta := #{node := N, time := T},
|
||||
session_ids := [ClientId1]
|
||||
} when
|
||||
N =/= node() andalso T > T0,
|
||||
4 * GCInterval + 1_000
|
||||
session_id := ClientId2
|
||||
}
|
||||
)
|
||||
),
|
||||
?assertMatch(
|
||||
|
@ -613,22 +606,116 @@ t_session_gc(Config) ->
|
|||
?block_until(
|
||||
#{
|
||||
?snk_kind := ds_session_gc_cleaned,
|
||||
?snk_meta := #{node := N, time := T},
|
||||
session_ids := [ClientId2]
|
||||
} when
|
||||
N =/= node() andalso T > T0,
|
||||
4 * GCInterval + 1_000
|
||||
session_id := ClientId3
|
||||
}
|
||||
)
|
||||
),
|
||||
Sessions1 = list_all_sessions(Node1),
|
||||
Subs1 = list_all_subscriptions(Node1),
|
||||
?assertEqual(1, map_size(Sessions1), #{sessions => Sessions1}),
|
||||
?assertEqual(1, map_size(Subs1), #{subs => Subs1}),
|
||||
?retry(50, 3, [ClientId1] = list_all_sessions(Node1)),
|
||||
?assertMatch([_], list_all_subscriptions(Node1), subscriptions),
|
||||
ok
|
||||
end,
|
||||
[]
|
||||
),
|
||||
ok.
|
||||
|
||||
t_session_replay_retry(_Config) ->
|
||||
%% Verify that the session recovers smoothly from transient errors during
|
||||
%% replay.
|
||||
|
||||
ok = emqx_ds_test_helpers:mock_rpc(),
|
||||
|
||||
NClients = 10,
|
||||
ClientSubOpts = #{
|
||||
clientid => mk_clientid(?FUNCTION_NAME, sub),
|
||||
auto_ack => never
|
||||
},
|
||||
ClientSub = start_connect_client(ClientSubOpts),
|
||||
?assertMatch(
|
||||
{ok, _, [?RC_GRANTED_QOS_1]},
|
||||
emqtt:subscribe(ClientSub, <<"t/#">>, ?QOS_1)
|
||||
),
|
||||
|
||||
ClientsPub = [
|
||||
start_connect_client(#{
|
||||
clientid => mk_clientid(?FUNCTION_NAME, I),
|
||||
properties => #{'Session-Expiry-Interval' => 0}
|
||||
})
|
||||
|| I <- lists:seq(1, NClients)
|
||||
],
|
||||
lists:foreach(
|
||||
fun(Client) ->
|
||||
Index = integer_to_binary(rand:uniform(NClients)),
|
||||
Topic = <<"t/", Index/binary>>,
|
||||
?assertMatch({ok, #{}}, emqtt:publish(Client, Topic, Index, 1))
|
||||
end,
|
||||
ClientsPub
|
||||
),
|
||||
|
||||
Pubs0 = emqx_common_test_helpers:wait_publishes(NClients, 5_000),
|
||||
NPubs = length(Pubs0),
|
||||
?assertEqual(NClients, NPubs, ?drainMailbox(1_500)),
|
||||
|
||||
ok = emqtt:stop(ClientSub),
|
||||
|
||||
%% Make `emqx_ds` believe that roughly half of the shards are unavailable.
|
||||
ok = emqx_ds_test_helpers:mock_rpc_result(
|
||||
fun(_Node, emqx_ds_replication_layer, _Function, [_DB, Shard | _]) ->
|
||||
case erlang:phash2(Shard) rem 2 of
|
||||
0 -> unavailable;
|
||||
1 -> passthrough
|
||||
end
|
||||
end
|
||||
),
|
||||
|
||||
_ClientSub = start_connect_client(ClientSubOpts#{clean_start => false}),
|
||||
|
||||
Pubs1 = emqx_common_test_helpers:wait_publishes(NPubs, 5_000),
|
||||
?assert(length(Pubs1) < length(Pubs0), Pubs1),
|
||||
|
||||
%% "Recover" the shards.
|
||||
emqx_ds_test_helpers:unmock_rpc(),
|
||||
|
||||
Pubs2 = emqx_common_test_helpers:wait_publishes(NPubs - length(Pubs1), 5_000),
|
||||
?assertEqual(
|
||||
[maps:with([topic, payload, qos], P) || P <- Pubs0],
|
||||
[maps:with([topic, payload, qos], P) || P <- Pubs1 ++ Pubs2]
|
||||
).
|
||||
|
||||
%% Check that we send will messages when performing GC without relying on timers set by
|
||||
%% the channel process.
|
||||
t_session_gc_will_message(_Config) ->
|
||||
?check_trace(
|
||||
#{timetrap => 10_000},
|
||||
begin
|
||||
WillTopic = <<"will/t">>,
|
||||
ok = emqx:subscribe(WillTopic, #{qos => 2}),
|
||||
ClientId = <<"will_msg_client">>,
|
||||
Client = start_client(#{
|
||||
clientid => ClientId,
|
||||
will_topic => WillTopic,
|
||||
will_payload => <<"will payload">>,
|
||||
will_qos => 0,
|
||||
will_props => #{'Will-Delay-Interval' => 300}
|
||||
}),
|
||||
{ok, _} = emqtt:connect(Client),
|
||||
%% Use reason code =/= `?RC_SUCCESS' to allow will message
|
||||
{ok, {ok, _}} =
|
||||
?wait_async_action(
|
||||
emqtt:disconnect(Client, ?RC_UNSPECIFIED_ERROR),
|
||||
#{?snk_kind := emqx_cm_clean_down}
|
||||
),
|
||||
?assertNotReceive({deliver, WillTopic, _}),
|
||||
%% Set fake `last_alive_at' to trigger immediate will message.
|
||||
force_last_alive_at(ClientId, _Time = 0),
|
||||
{ok, {ok, _}} =
|
||||
?wait_async_action(
|
||||
emqx_persistent_session_ds_gc_worker:check_session(ClientId),
|
||||
#{?snk_kind := session_gc_published_will_msg}
|
||||
),
|
||||
?assertReceive({deliver, WillTopic, _}),
|
||||
|
||||
ok
|
||||
end,
|
||||
[
|
||||
prop_only_cores_run_gc(CoreNodes)
|
||||
]
|
||||
[]
|
||||
),
|
||||
ok.
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
defmodule EMQX.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
alias EMQXUmbrella.MixProject, as: UMP
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :emqx,
|
||||
version: "0.1.0",
|
||||
build_path: "../../_build",
|
||||
erlc_paths: erlc_paths(),
|
||||
erlc_options: [
|
||||
{:i, "src"}
|
||||
| UMP.erlc_options()
|
||||
],
|
||||
compilers: Mix.compilers() ++ [:copy_srcs],
|
||||
# used by our `Mix.Tasks.Compile.CopySrcs` compiler
|
||||
extra_dirs: extra_dirs(),
|
||||
deps_path: "../../deps",
|
||||
lockfile: "../../mix.lock",
|
||||
elixir: "~> 1.14",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications
|
||||
def application do
|
||||
[
|
||||
## FIXME!!! go though emqx.app.src and add missing stuff...
|
||||
extra_applications: [:public_key, :ssl, :os_mon, :logger, :mnesia, :sasl] ++ UMP.extra_applications(),
|
||||
mod: {:emqx_app, []}
|
||||
]
|
||||
end
|
||||
|
||||
def deps() do
|
||||
## FIXME!!! go though emqx.app.src and add missing stuff...
|
||||
[
|
||||
{:emqx_mix_utils, in_umbrella: true, runtime: false},
|
||||
{:emqx_utils, in_umbrella: true},
|
||||
{:emqx_ds_backends, in_umbrella: true},
|
||||
|
||||
UMP.common_dep(:gproc),
|
||||
UMP.common_dep(:gen_rpc),
|
||||
UMP.common_dep(:ekka),
|
||||
UMP.common_dep(:esockd),
|
||||
UMP.common_dep(:cowboy),
|
||||
UMP.common_dep(:lc),
|
||||
UMP.common_dep(:hocon),
|
||||
UMP.common_dep(:ranch),
|
||||
UMP.common_dep(:bcrypt),
|
||||
UMP.common_dep(:pbkdf2),
|
||||
UMP.common_dep(:emqx_http_lib),
|
||||
] ++ UMP.quicer_dep()
|
||||
end
|
||||
|
||||
defp erlc_paths() do
|
||||
paths = UMP.erlc_paths()
|
||||
if UMP.test_env?() do
|
||||
["integration_test" | paths]
|
||||
else
|
||||
paths
|
||||
end
|
||||
end
|
||||
|
||||
defp extra_dirs() do
|
||||
dirs = ["src", "etc"]
|
||||
if UMP.test_env?() do
|
||||
["test", "integration_test" | dirs]
|
||||
else
|
||||
dirs
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,12 +8,16 @@
|
|||
{emqx_bridge,3}.
|
||||
{emqx_bridge,4}.
|
||||
{emqx_bridge,5}.
|
||||
{emqx_bridge,6}.
|
||||
{emqx_broker,1}.
|
||||
{emqx_cluster_link,1}.
|
||||
{emqx_cm,1}.
|
||||
{emqx_cm,2}.
|
||||
{emqx_cm,3}.
|
||||
{emqx_conf,1}.
|
||||
{emqx_conf,2}.
|
||||
{emqx_conf,3}.
|
||||
{emqx_conf,4}.
|
||||
{emqx_connector,1}.
|
||||
{emqx_dashboard,1}.
|
||||
{emqx_delayed,1}.
|
||||
|
@ -21,8 +25,12 @@
|
|||
{emqx_delayed,3}.
|
||||
{emqx_ds,1}.
|
||||
{emqx_ds,2}.
|
||||
{emqx_ds,3}.
|
||||
{emqx_ds,4}.
|
||||
{emqx_ds_shared_sub,1}.
|
||||
{emqx_eviction_agent,1}.
|
||||
{emqx_eviction_agent,2}.
|
||||
{emqx_eviction_agent,3}.
|
||||
{emqx_exhook,1}.
|
||||
{emqx_ft_storage_exporter_fs,1}.
|
||||
{emqx_ft_storage_fs,1}.
|
||||
|
@ -36,11 +44,16 @@
|
|||
{emqx_management,2}.
|
||||
{emqx_management,3}.
|
||||
{emqx_management,4}.
|
||||
{emqx_management,5}.
|
||||
{emqx_metrics,1}.
|
||||
{emqx_metrics,2}.
|
||||
{emqx_mgmt_api_plugins,1}.
|
||||
{emqx_mgmt_api_plugins,2}.
|
||||
{emqx_mgmt_api_plugins,3}.
|
||||
{emqx_mgmt_api_relup,1}.
|
||||
{emqx_mgmt_cluster,1}.
|
||||
{emqx_mgmt_cluster,2}.
|
||||
{emqx_mgmt_cluster,3}.
|
||||
{emqx_mgmt_data_backup,1}.
|
||||
{emqx_mgmt_trace,1}.
|
||||
{emqx_mgmt_trace,2}.
|
||||
|
@ -50,15 +63,18 @@
|
|||
{emqx_node_rebalance_api,1}.
|
||||
{emqx_node_rebalance_api,2}.
|
||||
{emqx_node_rebalance_evacuation,1}.
|
||||
{emqx_node_rebalance_purge,1}.
|
||||
{emqx_node_rebalance_status,1}.
|
||||
{emqx_node_rebalance_status,2}.
|
||||
{emqx_persistent_session_ds,1}.
|
||||
{emqx_plugins,1}.
|
||||
{emqx_plugins,2}.
|
||||
{emqx_prometheus,1}.
|
||||
{emqx_prometheus,2}.
|
||||
{emqx_resource,1}.
|
||||
{emqx_resource,2}.
|
||||
{emqx_retainer,1}.
|
||||
{emqx_retainer,2}.
|
||||
{emqx_router,1}.
|
||||
{emqx_rule_engine,1}.
|
||||
{emqx_shared_sub,1}.
|
||||
{emqx_slow_subs,1}.
|
||||
|
|
|
@ -24,17 +24,18 @@
|
|||
{deps, [
|
||||
{emqx_utils, {path, "../emqx_utils"}},
|
||||
{emqx_durable_storage, {path, "../emqx_durable_storage"}},
|
||||
{emqx_ds_backends, {path, "../emqx_ds_backends"}},
|
||||
{lc, {git, "https://github.com/emqx/lc.git", {tag, "0.3.2"}}},
|
||||
{gproc, {git, "https://github.com/emqx/gproc", {tag, "0.9.0.1"}}},
|
||||
{cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.9.2"}}},
|
||||
{esockd, {git, "https://github.com/emqx/esockd", {tag, "5.11.1"}}},
|
||||
{ekka, {git, "https://github.com/emqx/ekka", {tag, "0.18.1"}}},
|
||||
{esockd, {git, "https://github.com/emqx/esockd", {tag, "5.12.0"}}},
|
||||
{ekka, {git, "https://github.com/emqx/ekka", {tag, "0.19.5"}}},
|
||||
{gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.3.1"}}},
|
||||
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.40.4"}}},
|
||||
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.43.2"}}},
|
||||
{emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.5.3"}}},
|
||||
{pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}},
|
||||
{recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}},
|
||||
{snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.8"}}}
|
||||
{snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.10"}}}
|
||||
]}.
|
||||
|
||||
{plugins, [{rebar3_proper, "0.12.1"}, rebar3_path_deps]}.
|
||||
|
@ -71,7 +72,7 @@
|
|||
{statistics, true}
|
||||
]}.
|
||||
|
||||
{project_plugins, [erlfmt]}.
|
||||
{project_plugins, [{erlfmt, "1.3.0"}]}.
|
||||
|
||||
{erlfmt, [
|
||||
{files, [
|
||||
|
|
|
@ -24,7 +24,8 @@ IsQuicSupp = fun() ->
|
|||
end,
|
||||
|
||||
Bcrypt = {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {tag, "0.6.0"}}},
|
||||
Quicer = {quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.311"}}}.
|
||||
Quicer =
|
||||
{quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.500"}}}.
|
||||
|
||||
Dialyzer = fun(Config) ->
|
||||
{dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -16,9 +16,14 @@
|
|||
|
||||
-module(emqx_config_backup).
|
||||
|
||||
-type ok_result() :: #{
|
||||
root_key => emqx_utils_maps:config_key(),
|
||||
changed => [emqx_utils_maps:config_key_path()]
|
||||
}.
|
||||
|
||||
-type error_result() :: #{root_key => emqx_utils_maps:config_key(), reason => term()}.
|
||||
|
||||
-callback import_config(RawConf :: map()) ->
|
||||
{ok, #{
|
||||
root_key => emqx_utils_maps:config_key(),
|
||||
changed => [emqx_utils_maps:config_key_path()]
|
||||
}}
|
||||
| {error, #{root_key => emqx_utils_maps:config_key(), reason => term()}}.
|
||||
{ok, ok_result()}
|
||||
| {error, error_result()}
|
||||
| {results, {[ok_result()], [error_result()]}}.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,8 @@
|
|||
|
||||
-type traverse_break_reason() :: over | migrate.
|
||||
|
||||
-type opts() :: #{print_fun => fun((io:format(), [term()]) -> ok)}.
|
||||
|
||||
-callback backup_tables() -> [mria:table()].
|
||||
|
||||
%% validate the backup
|
||||
|
@ -31,6 +33,9 @@
|
|||
|
||||
-callback migrate_mnesia_backup(tuple()) -> {ok, tuple()} | {error, term()}.
|
||||
|
||||
-optional_callbacks([validate_mnesia_backup/1, migrate_mnesia_backup/1]).
|
||||
%% NOTE: currently, this is called only when the table has been restored successfully.
|
||||
-callback on_backup_table_imported(mria:table(), opts()) -> ok | {error, term()}.
|
||||
|
||||
-optional_callbacks([validate_mnesia_backup/1, migrate_mnesia_backup/1, on_backup_table_imported/2]).
|
||||
|
||||
-export_type([traverse_break_reason/0]).
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -18,14 +18,15 @@
|
|||
%% API:
|
||||
-export([
|
||||
start/0,
|
||||
announce/1,
|
||||
announce/2,
|
||||
supported_version/1, supported_version/2,
|
||||
versions_file/1
|
||||
]).
|
||||
|
||||
%% Internal exports (RPC)
|
||||
-export([
|
||||
announce_fun/1
|
||||
announce_fun/1,
|
||||
announce_fun/2
|
||||
]).
|
||||
|
||||
-export_type([api/0, api_version/0, var_name/0, call/0, rpc/0, bpapi_meta/0]).
|
||||
|
@ -66,7 +67,7 @@ start() ->
|
|||
{rlog_shard, ?COMMON_SHARD}
|
||||
]),
|
||||
ok = mria:wait_for_tables([?TAB]),
|
||||
announce(emqx).
|
||||
announce(node(), emqx).
|
||||
|
||||
%% @doc Get maximum version of the backplane API supported by the node
|
||||
-spec supported_version(node(), api()) -> api_version() | undefined.
|
||||
|
@ -82,11 +83,38 @@ supported_version(Node, API) ->
|
|||
supported_version(API) ->
|
||||
ets:lookup_element(?TAB, {?multicall, API}, #?TAB.version).
|
||||
|
||||
-spec announce(atom()) -> ok.
|
||||
announce(App) ->
|
||||
-spec announce(node(), atom()) -> ok.
|
||||
announce(Node, App) ->
|
||||
{ok, Data} = file:consult(?MODULE:versions_file(App)),
|
||||
{atomic, ok} = mria:transaction(?COMMON_SHARD, fun ?MODULE:announce_fun/1, [Data]),
|
||||
ok.
|
||||
%% replicant(5.6.0) will call old core(<5.6.0) announce_fun/2 is undef on old core
|
||||
%% so we just use anonymous function to update.
|
||||
case mria:transaction(?COMMON_SHARD, fun ?MODULE:announce_fun/2, [Node, Data]) of
|
||||
{atomic, ok} ->
|
||||
ok;
|
||||
{aborted, {undef, [{?MODULE, announce_fun, _, _} | _]}} ->
|
||||
{atomic, ok} = mria:transaction(
|
||||
?COMMON_SHARD,
|
||||
fun() ->
|
||||
MS = ets:fun2ms(fun(#?TAB{key = {N, API}}) when N =:= Node ->
|
||||
{N, API}
|
||||
end),
|
||||
OldKeys = mnesia:select(?TAB, MS, write),
|
||||
_ = [
|
||||
mnesia:delete({?TAB, Key})
|
||||
|| Key <- OldKeys
|
||||
],
|
||||
%% Insert new records:
|
||||
_ = [
|
||||
mnesia:write(#?TAB{key = {Node, API}, version = Version})
|
||||
|| {API, Version} <- Data
|
||||
],
|
||||
%% Update maximum supported version:
|
||||
_ = [update_minimum(API) || {API, _} <- Data],
|
||||
ok
|
||||
end
|
||||
),
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec versions_file(atom()) -> file:filename_all().
|
||||
versions_file(App) ->
|
||||
|
@ -96,11 +124,18 @@ versions_file(App) ->
|
|||
%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Attention:
|
||||
%% This function is just to prevent errors when being called during a rolling upgrade
|
||||
%% if the version is less than 5.5.0. Its 'node' parameter is wrong!
|
||||
-spec announce_fun([{api(), api_version()}]) -> ok.
|
||||
announce_fun(Data) ->
|
||||
announce_fun(node(), Data).
|
||||
|
||||
-spec announce_fun(node(), [{api(), api_version()}]) -> ok.
|
||||
announce_fun(Node, Data) ->
|
||||
%% Delete old records, if present:
|
||||
MS = ets:fun2ms(fun(#?TAB{key = {node(), API}}) ->
|
||||
{node(), API}
|
||||
MS = ets:fun2ms(fun(#?TAB{key = {N, API}}) when N =:= Node ->
|
||||
{N, API}
|
||||
end),
|
||||
OldKeys = mnesia:select(?TAB, MS, write),
|
||||
_ = [
|
||||
|
@ -109,7 +144,7 @@ announce_fun(Data) ->
|
|||
],
|
||||
%% Insert new records:
|
||||
_ = [
|
||||
mnesia:write(#?TAB{key = {node(), API}, version = Version})
|
||||
mnesia:write(#?TAB{key = {Node, API}, version = Version})
|
||||
|| {API, Version} <- Data
|
||||
],
|
||||
%% Update maximum supported version:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2022-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2020-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2020-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -237,25 +237,38 @@ log_formatter(HandlerName, Conf) ->
|
|||
_ ->
|
||||
conf_get("formatter", Conf)
|
||||
end,
|
||||
TsFormat = timestamp_format(Conf),
|
||||
WithMfa = conf_get("with_mfa", Conf),
|
||||
PayloadEncode = conf_get("payload_encode", Conf, text),
|
||||
do_formatter(
|
||||
Format, CharsLimit, SingleLine, TimeOffSet, Depth
|
||||
Format, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat, WithMfa, PayloadEncode
|
||||
).
|
||||
|
||||
%% auto | epoch | rfc3339
|
||||
timestamp_format(Conf) ->
|
||||
conf_get("timestamp_format", Conf).
|
||||
|
||||
%% helpers
|
||||
do_formatter(json, CharsLimit, SingleLine, TimeOffSet, Depth) ->
|
||||
do_formatter(json, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat, WithMfa, PayloadEncode) ->
|
||||
{emqx_logger_jsonfmt, #{
|
||||
chars_limit => CharsLimit,
|
||||
single_line => SingleLine,
|
||||
time_offset => TimeOffSet,
|
||||
depth => Depth
|
||||
depth => Depth,
|
||||
timestamp_format => TsFormat,
|
||||
with_mfa => WithMfa,
|
||||
payload_encode => PayloadEncode
|
||||
}};
|
||||
do_formatter(text, CharsLimit, SingleLine, TimeOffSet, Depth) ->
|
||||
do_formatter(text, CharsLimit, SingleLine, TimeOffSet, Depth, TsFormat, WithMfa, PayloadEncode) ->
|
||||
{emqx_logger_textfmt, #{
|
||||
template => [time, " [", level, "] ", msg, "\n"],
|
||||
template => ["[", level, "] ", msg, "\n"],
|
||||
chars_limit => CharsLimit,
|
||||
single_line => SingleLine,
|
||||
time_offset => TimeOffSet,
|
||||
depth => Depth
|
||||
depth => Depth,
|
||||
timestamp_format => TsFormat,
|
||||
with_mfa => WithMfa,
|
||||
payload_encode => PayloadEncode
|
||||
}}.
|
||||
|
||||
%% Don't record all logger message
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2020-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%% Copyright (c) 2020-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
|
@ -20,6 +20,7 @@
|
|||
%% API
|
||||
-export([add_handler/0, remove_handler/0, pre_config_update/3]).
|
||||
-export([is_olp_enabled/0]).
|
||||
-export([assert_zone_exists/1]).
|
||||
|
||||
-define(ZONES, [zones]).
|
||||
|
||||
|
@ -44,3 +45,26 @@ is_olp_enabled() ->
|
|||
false,
|
||||
emqx_config:get([zones], #{})
|
||||
).
|
||||
|
||||
-spec assert_zone_exists(binary() | atom()) -> ok.
|
||||
assert_zone_exists(Name0) when is_binary(Name0) ->
|
||||
%% an existing zone must have already an atom-name
|
||||
Name =
|
||||
try
|
||||
binary_to_existing_atom(Name0)
|
||||
catch
|
||||
_:_ ->
|
||||
throw({unknown_zone, Name0})
|
||||
end,
|
||||
assert_zone_exists(Name);
|
||||
assert_zone_exists(default) ->
|
||||
%% there is always a 'default' zone
|
||||
ok;
|
||||
assert_zone_exists(Name) when is_atom(Name) ->
|
||||
try
|
||||
_ = emqx_config:get([zones, Name]),
|
||||
ok
|
||||
catch
|
||||
error:{config_not_found, _} ->
|
||||
throw({unknown_zone, Name})
|
||||
end.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{application, emqx, [
|
||||
{id, "emqx"},
|
||||
{description, "EMQX Core"},
|
||||
{vsn, "5.1.19"},
|
||||
{vsn, "5.3.4"},
|
||||
{modules, []},
|
||||
{registered, []},
|
||||
{applications, [
|
||||
|
@ -18,7 +18,7 @@
|
|||
sasl,
|
||||
lc,
|
||||
hocon,
|
||||
emqx_durable_storage,
|
||||
emqx_ds_backends,
|
||||
bcrypt,
|
||||
pbkdf2,
|
||||
emqx_http_lib,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue