Compare commits
6604 Commits
Author | SHA1 | Date | |
---|---|---|---|
ca7ee794bf | |||
f9f2ba6faf | |||
aea1d211d4 | |||
57a518a36d | |||
29b83189b0 | |||
1d3df7885d | |||
fd06ffa2af | |||
36a1622dd1 | |||
7a91b23cb5 | |||
4b90b6a226 | |||
b13daa4cdf | |||
0c6f026828 | |||
a2520bd267 | |||
b928a209a4 | |||
89e16ed6a5 | |||
1a1f99af37 | |||
df2cd37ed2 | |||
12a71bc6bc | |||
7d270c235a | |||
b0b7248504 | |||
78460c1848 | |||
75b119eafc | |||
64b0ae93f7 | |||
7c0b25f5a6 | |||
07b5df3a19 | |||
e7023726f4 | |||
a9ccd9254c | |||
335f3271d2 | |||
7f93f7ef47 | |||
cf46a87fcd | |||
ad6680f602 | |||
5e287f67af | |||
ecfe6e0609 | |||
df9790dd11 | |||
67cfc4c9bc | |||
a68e623c80 | |||
9e3915ba48 | |||
ba2de61748 | |||
a9a4edebe2 | |||
64f2ffa166 | |||
13020b9cc2 | |||
96b96fba0f | |||
2cbe53a9ba | |||
48755114e5 | |||
a5d5f67be7 | |||
dfb58c44a2 | |||
69948ce919 | |||
3190ccf3b2 | |||
a8ea8173aa | |||
e13a49d1f0 | |||
2f0b8f675a | |||
c2aed033ba | |||
0f8a780b0d | |||
c5bc2e77c8 | |||
079310dc7c | |||
0d2cdf6165 | |||
436dde271f | |||
96891a076f | |||
9ce0067bdf | |||
345940bbc1 | |||
c49507b289 | |||
c730142508 | |||
27aa00b15f | |||
36a00a255b | |||
0e3249c89b | |||
920019ab70 | |||
82c8b44db7 | |||
bb3a307d5a | |||
dcb0ddaf5e | |||
4c1edd52c5 | |||
d512e27979 | |||
0619d82e0b | |||
a4038d5b94 | |||
e3d5e1fab7 | |||
035036308a | |||
0d29259d9b | |||
26b0f3dc96 | |||
5c9306b0fe | |||
3befb0e4b9 | |||
97bb88f10b | |||
6c7467a58b | |||
c579a85c12 | |||
400fdd08fd | |||
c1fe6c9c81 | |||
c58a0bea91 | |||
88a934b93c | |||
cde5cced69 | |||
472bedd3ea | |||
d8a06d03bd | |||
32020f9fb3 | |||
d574b14934 | |||
00c5d89e7d | |||
d2c8aefe64 | |||
ba796bbdd3 | |||
a0bb2ba7b7 | |||
f9fa3b5b6c | |||
f89d438116 | |||
1abe791d46 | |||
1502ae78b6 | |||
bad6e719de | |||
8c7129f3d2 | |||
dbff6f71e1 | |||
fcd934ccf6 | |||
45a8f340d9 | |||
5856513405 | |||
01fa3ee5c3 | |||
b8d69ffdf3 | |||
7ef60ec2a9 | |||
83f905c0e1 | |||
72ba3a3918 | |||
df10597da4 | |||
5db2e794a9 | |||
486aa06747 | |||
01ce1b32df | |||
c78b0b2c51 | |||
9ade1c3ea3 | |||
315a4cfcd4 | |||
11c04027ab | |||
eabe3b4c39 | |||
d471454675 | |||
bf57776b59 | |||
a32579ae5b | |||
780601d27a | |||
c909e731d7 | |||
9b8eb42354 | |||
0757174e8e | |||
3a43cdefe8 | |||
38c48beddd | |||
ad5749fb04 | |||
f6a838e9ee | |||
a6d1f4aaf1 | |||
eca8d11ee2 | |||
a195b7dbe4 | |||
083d7ec902 | |||
9d2d0cae6d | |||
c2f4a9bf71 | |||
231095fe8a | |||
28a532483a | |||
83853a215d | |||
8248307a99 | |||
67bd88b19a | |||
9f698b4de0 | |||
742f3d6787 | |||
323651bd38 | |||
9d397eb5a1 | |||
6114cd2bd4 | |||
d494f7bd5e | |||
ec6a7ab721 | |||
ad6d2b4619 | |||
c093390010 | |||
acd69f2be2 | |||
5d2f341653 | |||
420d1c35f5 | |||
08647267bb | |||
215d50d2f6 | |||
bf2cb6fa48 | |||
e97a2d4123 | |||
585e3f6adc | |||
7f77ce1a48 | |||
a1616ce181 | |||
1c22dff714 | |||
8d1d6e8f70 | |||
e7f4aba5a3 | |||
fdbe9f5d9f | |||
8bead6bfdd | |||
52dda73dbb | |||
31b3888a2f | |||
6f938470c2 | |||
776c4afc03 | |||
536dd647c6 | |||
51d581ab27 | |||
75294e7dad | |||
04bada7a9d | |||
2349143477 | |||
e9bff5fe9f | |||
411cb0cb92 | |||
53e1fb3554 | |||
2cb3b66640 | |||
5af3144330 | |||
e4043cbb3a | |||
fff424a35f | |||
b5d1c8b05a | |||
d713e33cc4 | |||
3d327d25f0 | |||
077283bf0f | |||
9ec25ea036 | |||
878cfe669c | |||
5f0be3cb2e | |||
9e28e14c08 | |||
954d002884 | |||
0a48591e53 | |||
d37c723951 | |||
9078ca557e | |||
2be1ef6ba0 | |||
47c02efccb | |||
d7ecfb432a | |||
59abf4a33f | |||
d6e715e726 | |||
fcfcd1037c | |||
f3ccd29e7b | |||
5c0bdae809 | |||
838902556b | |||
c6872c02d8 | |||
819982ea20 | |||
f9daa136c3 | |||
6a0d2ed6c8 | |||
2c1f35e794 | |||
5345e8da45 | |||
e35269dd87 | |||
60a03b7ef7 | |||
305b5a3887 | |||
bc549361d3 | |||
084b627f2e | |||
6755d00601 | |||
cba1da3e44 | |||
7be8bb1489 | |||
c7c0c1f626 | |||
3aa4629f92 | |||
2d86dbb090 | |||
91767ff0f9 | |||
078b004ecc | |||
930d204d83 | |||
8d82cdfc77 | |||
cb6996b5c3 | |||
a4f7740332 | |||
ba0faa2f77 | |||
3e68029522 | |||
b4e26b5828 | |||
15cf7fcac2 | |||
24ff0eb13b | |||
cf86f72eb7 | |||
61486f14f1 | |||
d16a7f3ecc | |||
82761ec50e | |||
235bfa77a9 | |||
299ae1bb1c | |||
80f7522dab | |||
028921e369 | |||
a4e11bb524 | |||
a4131752d2 | |||
060dcfbba1 | |||
4be7008f80 | |||
4a0d05515e | |||
83ab99c746 | |||
270da1f69f | |||
6b0e46e36c | |||
3642707145 | |||
0ea76edfd8 | |||
d493a83b2b | |||
f1721d5cef | |||
5b3fd6aa82 | |||
6f829180f7 | |||
27b95ba64a | |||
ef405b1e90 | |||
441073bad5 | |||
cfb37b8994 | |||
a1001f2ea0 | |||
6ca3fb19fd | |||
267f844811 | |||
59e7203a40 | |||
7db177d181 | |||
3f4232a23d | |||
2a634648c2 | |||
97e13991c5 | |||
d42a912343 | |||
03fef736d6 | |||
78b8d0e1ef | |||
aedac71491 | |||
89b44d1900 | |||
2fc5ae561b | |||
cb719ee16e | |||
ed46d9ebd7 | |||
1380c5642b | |||
e3d447229d | |||
327980bf49 | |||
4c30aa8343 | |||
e7c878027a | |||
886f90516d | |||
1faf9bbeb0 | |||
325ad7eb53 | |||
362fba4bde | |||
211d33ad59 | |||
383f04b96d | |||
4e96cdc23f | |||
772c5b8f64 | |||
8f1d0c317e | |||
deac994517 | |||
b754ab298a | |||
3a4e1b8f86 | |||
a73d2a7688 | |||
009f394237 | |||
5ac5ac1dec | |||
cc1e0bbdc0 | |||
ef9f8df9ed | |||
87f951c5c1 | |||
afd58b3739 | |||
c2c14c2a1f | |||
e19930e70d | |||
e7c017cfe3 | |||
8a3493af47 | |||
318e9372c9 | |||
22d80a6780 | |||
593e07bd21 | |||
3dfc7703c2 | |||
2ca2c8fe0f | |||
8004eb0eec | |||
89995075e6 | |||
c2fa65640c | |||
2d065a32ec | |||
fcb68cc139 | |||
01d1c1a9ab | |||
1754beb59c | |||
844208f463 | |||
1689f9378b | |||
011fdfa94f | |||
6466fb20c2 | |||
3f9b3d7666 | |||
8524688a87 | |||
7f58c579f3 | |||
3d7c85b2aa | |||
55c2433171 | |||
03afa36334 | |||
05f1df3224 | |||
901db0e730 | |||
564ca9e8ec | |||
20d377c11b | |||
2c5e873da0 | |||
42a9e5ad7d | |||
cda2530df5 | |||
aaa89bb715 | |||
ea971f7098 | |||
ddaa124162 | |||
7a30153aa1 | |||
7acd33007d | |||
8a56c99f87 | |||
77c0ef38be | |||
5f64e52ed4 | |||
b2a3325258 | |||
95f429c7e2 | |||
f16ca1ce46 | |||
508c555ce2 | |||
f97d8a9cbd | |||
24ec5235a0 | |||
bbd556ee9f | |||
466df41c8f | |||
4e1b5e43fa | |||
b0e362f75b | |||
91092f668e | |||
d268d2ad85 | |||
2486db7c2b | |||
0672a0e547 | |||
9846b19986 | |||
8b79075497 | |||
2956f21d82 | |||
c8ee390d23 | |||
d7440c452a | |||
a2b8dc1cfb | |||
7ebf35c5f8 | |||
dbcaf22805 | |||
0066a1ae70 | |||
491da99abe | |||
13ba84731f | |||
b58bd2bb91 | |||
a32cbed89c | |||
c42f35eb2f | |||
2418c6aca1 | |||
90205079d7 | |||
57a868627f | |||
2cacab92e6 | |||
0520ecb7d0 | |||
047642556c | |||
9edea0bb75 | |||
ce39755937 | |||
7d3f5043e1 | |||
14c0ec97d8 | |||
45f4a47286 | |||
141fcb95a4 | |||
dbf1f6b233 | |||
5d12c19ce9 | |||
352b9c78e0 | |||
019835c721 | |||
255c2b2ff0 | |||
0731fc47e4 | |||
7ffdbc05d2 | |||
4f3ac1d983 | |||
d7c70caa4c | |||
2cddeabce0 | |||
7addc9f1a9 | |||
cb6ddfc215 | |||
681741cd13 | |||
8fe532e593 | |||
198fc6f108 | |||
8d8e419664 | |||
1e208e8c87 | |||
286fbf42c6 | |||
40025f55ad | |||
7eb1a58b26 | |||
28f3c1c96a | |||
0c8adbc4ec | |||
ed1b4a8f19 | |||
bd30c37040 | |||
eb34aa551a | |||
1142c378fd | |||
82a3bd5e8b | |||
5f3fba43fa | |||
eca2246fbc | |||
df71c7c617 | |||
c184de175d | |||
8b65946eb8 | |||
de0c71c467 | |||
39e066add1 | |||
178e750f16 | |||
14be55c9fa | |||
fdd61152c5 | |||
7cc332efe6 | |||
1eba1aaf15 | |||
4e628a887a | |||
b6bc0aeb61 | |||
77d8afb7da | |||
42d1091d6a | |||
d0280a0335 | |||
97d6d909e7 | |||
f7815cf96d | |||
9e43e4900e | |||
8ce38cac0d | |||
a10c126692 | |||
b682bd1916 | |||
26eacd4fcb | |||
fc4741f638 | |||
3f3e9b7555 | |||
53a8459d5f | |||
0ec0ff3bce | |||
f930e75a80 | |||
854bd7d0c8 | |||
e17fe90aaa | |||
0577bf0e3e | |||
4c92cf43cf | |||
c6ecdc9a81 | |||
20cc3ab37e | |||
420b9be1c1 | |||
3c6c00d1d4 | |||
6fa36e387f | |||
9bde1be5a4 | |||
040253c426 | |||
c98a4d6ddd | |||
d5293d2aa3 | |||
d578ab8f3c | |||
9dbb30f884 | |||
fafa50d97f | |||
e010f2ca54 | |||
c9e0db55f7 | |||
ecffc3557f | |||
b861e9c0ac | |||
4213e8d5f0 | |||
bab90a7709 | |||
da79e0433f | |||
1b8752e595 | |||
b3cf5b246f | |||
0a695e181e | |||
a5d1d1161b | |||
a25c3c5c3b | |||
d1a8afbbd0 | |||
f4fcb0c54c | |||
e92b81351b | |||
53805f07ba | |||
e73daa3736 | |||
eef01160f4 | |||
333abf16e4 | |||
388dc93cee | |||
fbd281c26e | |||
420c179b39 | |||
35d61c11fd | |||
e30e1325f3 | |||
fc6c3ae97d | |||
63a28d6805 | |||
b95a336f12 | |||
b4df19c029 | |||
dbd0f8e699 | |||
b7fb92a048 | |||
2ff4b357d7 | |||
1c26f40cd4 | |||
2de34770c4 | |||
0fc6ed3c4a | |||
63455b839a | |||
70b25a3d4f | |||
2200c8a87b | |||
306f46ce92 | |||
1b2d6ea11b | |||
03198de73a | |||
bb0e57eccb | |||
a468f11c7c | |||
9d2241b901 | |||
88a235de3a | |||
7bd9e09c78 | |||
42c58d9fe8 | |||
b3713a112f | |||
e037840b88 | |||
ec6b9cc17d | |||
db4c59dad9 | |||
58ea040570 | |||
6046e86506 | |||
297dab845d | |||
2cb5f59acc | |||
0f3831b105 | |||
9d9d46f52b | |||
d9c4840a9c | |||
12fcc7cafe | |||
95a407d9dd | |||
e9300c979e | |||
df274b478e | |||
f8941a5b6b | |||
38f805cd06 | |||
98931bf9b5 | |||
9b85b533ff | |||
d805526659 | |||
ee435761fd | |||
35c6ed2675 | |||
72f534f7f8 | |||
3cb9b43851 | |||
bf0c520f2e | |||
ee35e223a7 | |||
dc9f4b994e | |||
49be32c931 | |||
1786586747 | |||
45c09416ed | |||
4779c4b94a | |||
793cb328de | |||
966598cda7 | |||
772ccf0d9f | |||
ff6e93163f | |||
dff5129661 | |||
e367593a26 | |||
16039d837e | |||
4665c35453 | |||
4c63241b34 | |||
9aa778e843 | |||
62ba0acfb5 | |||
52d2e46700 | |||
c89421bfa8 | |||
cebd4fada7 | |||
3d82aa781d | |||
89c589085d | |||
a6a7e1bb99 | |||
70dd27ffd8 | |||
7bc5bcde34 | |||
aa0dd0d5ff | |||
e0aa39929b | |||
4172707346 | |||
7c8c41353b | |||
1d9375d115 | |||
f27deea003 | |||
00e6cb1d62 | |||
cae2a893f2 | |||
b34fb04cbf | |||
2365bb89d7 | |||
7b5a0ba8c3 | |||
ad8c4cdd75 | |||
f5ff2068a4 | |||
90a2796a7e | |||
76190c71fc | |||
dd049caf0a | |||
bcd31cb857 | |||
e6161ca307 | |||
d6f6cd0cb1 | |||
b7f2a033df | |||
e37f2663c2 | |||
5e579c4dc9 | |||
f0ec4ae941 | |||
b80b43ddae | |||
f0c570bd41 | |||
e5d2853070 | |||
152293d3cf | |||
ceb61d10c1 | |||
dd806b0d99 | |||
113c75dd27 | |||
b7acf07a70 | |||
519f2baff0 | |||
3962908d36 | |||
afd2cbc3c4 | |||
4275b3412f | |||
1b3ee17888 | |||
8306da5ce1 | |||
75dff8a93a | |||
fc1b557d98 | |||
47f98673c7 | |||
781f5611d1 | |||
deea6da0e0 | |||
43622d32e4 | |||
5db8d93fe5 | |||
535c249f3a | |||
942b986ef3 | |||
acf6075ca9 | |||
28995dba19 | |||
f186c32245 | |||
d7c77cb175 | |||
51b09244ff | |||
458dc10ddc | |||
4341743b4a | |||
b5e92b9a5d | |||
28ff02b116 | |||
f4ef8a92f8 | |||
d7e9d8746a | |||
351759906b | |||
0c2ed4c3e5 | |||
37bfb14956 | |||
81d23b33ef | |||
bb150c2704 | |||
46ff673192 | |||
7842f73e8b | |||
e5f9e3d018 | |||
aebd5f9af6 | |||
4fb034aeec | |||
4da901f8c0 | |||
39b043646b | |||
4480ba3e29 | |||
5e79799b89 | |||
1fa1dd5aaa | |||
8be0972836 | |||
78840e59a7 | |||
c332d4d916 | |||
bb944eecd6 | |||
443f5eee85 | |||
7e5e60b757 | |||
33df4b74da | |||
3c14e9612f | |||
cabf997933 | |||
2ed7146393 | |||
bfda7ca5bd | |||
305b059809 | |||
297b7da166 | |||
6aac91743b | |||
f06d5f02b3 | |||
4a9f0bebc3 | |||
88b0985bad | |||
1e3b8a1354 | |||
5a09753e07 | |||
02bfa9e0e0 | |||
306ff3cd54 | |||
ec5c108b60 | |||
4d9da9b0a1 | |||
3ce7c87cbd | |||
061107c5f6 | |||
9f039d40c1 | |||
b1f1d3ffd2 | |||
03ff380e13 | |||
c6e5fc4fbe | |||
074266b896 | |||
c4dc642f99 | |||
e041ac6f0d | |||
66effde9f3 | |||
663b768780 | |||
0147de9044 | |||
b010849102 | |||
698b0288be | |||
5e80e7e216 | |||
d50cb30443 | |||
29122c518b | |||
58e175318c | |||
f88e63519a | |||
0cc53fb398 | |||
713bce19f4 | |||
d972821889 | |||
2d16b4711e | |||
9181b73e5a | |||
5737e65700 | |||
ca677481a2 | |||
6ab43d7335 | |||
fee316161d | |||
2e4244d521 | |||
3bedfdac9d | |||
ec0ce6005a | |||
a185efbd60 | |||
4aa4e6fd03 | |||
078b0be4dc | |||
13ae2d7271 | |||
99b93e55cb | |||
80e6c07d89 | |||
34aa5570ed | |||
e526f74dfd | |||
9e78f55c32 | |||
f1731d807e | |||
92c4f3d508 | |||
e92fce1c27 | |||
83a9159063 | |||
0a69a2832b | |||
717df13207 | |||
b40b5576df | |||
03f2f1ae47 | |||
a8978ebf8e | |||
7d7b59efa5 | |||
4cf89d4bd7 | |||
d47b318fee | |||
e485236502 | |||
41667de778 | |||
ef4736d052 | |||
db4a448439 | |||
7549c65502 | |||
1beccc1a6c | |||
0075017b43 | |||
4374931b0e | |||
64022f51d4 | |||
f9f6e2e1b3 | |||
aecf9de738 | |||
81195a238b | |||
96a3de6364 | |||
00027130ea | |||
4a18428de6 | |||
7f28845f58 | |||
1dd0b6cc18 | |||
e0415dbf16 | |||
95fc3d4c5c | |||
e145fa13b1 | |||
5fa7b8ba56 | |||
2c7d366c82 | |||
2dd6f25647 | |||
d2623f13d9 | |||
7d0af179e3 | |||
416c786774 | |||
93302b7fb8 | |||
eb8c6c7eff | |||
8660806ddc | |||
4c5e085c93 | |||
d707124fd9 | |||
aece3669e5 | |||
09c84169d5 | |||
d43c30688a | |||
ee70a18a75 | |||
76a8cd57ae | |||
4c7f89ff6d | |||
f9fb8338f5 | |||
6b3aa60446 | |||
2463548fa7 | |||
1140bbc25c | |||
1b4df6484e | |||
f40d51733a | |||
e893c5a330 | |||
8be8466a00 | |||
c8bef1259c | |||
568e9df1d6 | |||
a555fdba32 | |||
36535e9abd | |||
6402a9ae2a | |||
ca25c957bf | |||
93f07aee6c | |||
0af6e9fcbb | |||
008e12edda | |||
1927d0c7db | |||
9a0a90feb3 | |||
76d86d5a07 | |||
de7a9a3b93 | |||
04f61c0c3e | |||
c810ac7153 | |||
c24ad560fa | |||
3d2db5c5f0 | |||
32eafef6a7 | |||
2366480250 | |||
8e55a11283 | |||
e9de28111d | |||
75afd80ae8 | |||
a5eb0e56b6 | |||
4d458db1b5 | |||
24a92472bf | |||
43006bcc45 | |||
326240eb91 | |||
b59bc0e38c | |||
5516802142 | |||
cc4b813e75 | |||
64631063ae | |||
719224bffd | |||
fe2b6923ba | |||
38ad1d97ab | |||
372b9101e2 | |||
7e62aa0c6e | |||
36e927a8c6 | |||
9d8bb634f9 | |||
c5c57f6737 | |||
51a89c32c4 | |||
e1ac2efe4a | |||
702e17cfe2 | |||
4d1d0fa03b | |||
ec8bae1b27 | |||
08348fc2e8 | |||
63fbc71439 | |||
b44f7b5e16 | |||
c5df9ce474 | |||
2510e7dad6 | |||
80c68583d1 | |||
5b6ced5599 | |||
a383116b43 | |||
c6dd900f60 | |||
5ac308060d | |||
bc089abd32 | |||
c94a33c525 | |||
5cee709266 | |||
2d0847c307 | |||
995cd15a69 | |||
16497438d6 | |||
b54db86f43 | |||
44acf6734b | |||
b07b6edc2a | |||
83e4a76afa | |||
bfa7b1a494 | |||
8e0dec538e | |||
1c385a1c22 | |||
f9bc84cd99 | |||
2d7c95fb70 | |||
29e8a64cf0 | |||
00efacf561 | |||
d96995b4e3 | |||
fc3e5cb6d3 | |||
d37dad82f1 | |||
22710fc353 | |||
4f66250618 | |||
d783519835 | |||
b8e9a30d3b | |||
32ce8b1326 | |||
ff4eb0cb63 | |||
9ba46d9f88 | |||
b14ac96750 | |||
55dac05cf2 | |||
ae28d7c0b2 | |||
380de1e7b4 | |||
4f9717331d | |||
36fc28642a | |||
a323b9b1a3 | |||
58f4254fba | |||
4419907b08 | |||
9d415f9c3f | |||
fced8ee40e | |||
1cb7b88505 | |||
0e76b32aa5 | |||
e81ad3a1bc | |||
c3a85ceabc | |||
85e0e366df | |||
0ce8ad3493 | |||
528e25a81a | |||
d25012e864 | |||
c21c46a8e8 | |||
9cc8bd5f7d | |||
ae3eaf8b16 | |||
d714b95fb9 | |||
912692137a | |||
6fc85073d2 | |||
989dea7083 | |||
8968b206b4 | |||
df890d7629 | |||
47bfec4e46 | |||
b4972fa165 | |||
fb92f5de1a | |||
e342ffd855 | |||
c0143cb2ab | |||
c9f554cda7 | |||
ff665b9e6a | |||
1790b63a5d | |||
39d4016fe9 | |||
712f2642d5 | |||
d50881a86e | |||
c1a0f0617c | |||
13f7631c25 | |||
d2c60cc216 | |||
1aa5783a45 | |||
67b9adfd1a | |||
5007b97db6 | |||
5e45061a94 | |||
2132ee38e4 | |||
f6adc0c3f9 | |||
9afd360eba | |||
dbbc8ef8a6 | |||
9d22e2a445 | |||
c9fd8e39f3 | |||
e108646d43 | |||
2cb862447c | |||
fc325c49ec | |||
a8e936791b | |||
5fccb46f6f | |||
5a7ac8c3b9 | |||
21b8d6956a | |||
cc238e6377 | |||
df7504ade1 | |||
fbed0a1471 | |||
4cde83188a | |||
3e08347d8a | |||
9e70bcb34f | |||
1bc3893c65 | |||
a1e00f82f4 | |||
a1cae28283 | |||
02281281a8 | |||
22be967104 | |||
f5a5c36d3c | |||
b7138c1ec5 | |||
7aab399c84 | |||
9ea53803f7 | |||
34a17f3699 | |||
f862536ec4 | |||
afc9839f43 | |||
e3ecdc6a63 | |||
4af2a068c5 | |||
52d66ea5a9 | |||
61c37954c6 | |||
acc483e2eb | |||
168a393589 | |||
e552591768 | |||
46fe8fb8b4 | |||
31bec8ce61 | |||
e179c5827f | |||
79659ee5aa | |||
3fa895298d | |||
54634628ac | |||
8456c5ec60 | |||
0f8e710c7c | |||
05d0586223 | |||
6b4c5289b3 | |||
db74f2074b | |||
772bb5e742 | |||
47025e07ce | |||
e8900824dd | |||
a40be00e17 | |||
348ff0c8ea | |||
c852ec9283 | |||
8c2d8428d5 | |||
4a9514ec4e | |||
63815b54f3 | |||
372a56a0c9 | |||
2e493edf80 | |||
43635a6c54 | |||
37a48391f2 | |||
0d806c84e2 | |||
2b6028b643 | |||
99ea5d7044 | |||
8ea61a19cd | |||
ec9f4d5bc6 | |||
560542c2a8 | |||
a0ce8bc236 | |||
74e47c503a | |||
5af0e7523c | |||
18b1bd4415 | |||
06779cfe24 | |||
32f099aa36 | |||
96e3449ed7 | |||
20f01163af | |||
d8f9ec5291 | |||
7bd5368d8b | |||
cffbaba914 | |||
146ef48a6e | |||
9a1240360b | |||
b99b80c18b | |||
77da6887f7 | |||
5f7d06668e | |||
5e3a898f10 | |||
49478f5e19 | |||
10f1e94f18 | |||
1f89c6130e | |||
aad02e8337 | |||
4fba8a6aea | |||
42375c4b3a | |||
13495c64f7 | |||
f5c7e883a9 | |||
15f8afa4bf | |||
19cfaf7f4c | |||
6f95bc915d | |||
e74738db8c | |||
3aa5ae98ab | |||
5cb082ed53 | |||
95c729f5d1 | |||
c98c6e80c8 | |||
e4b1e6c622 | |||
65a6848ed7 | |||
0bf6e58db2 | |||
191e4d15b5 | |||
9368053be5 | |||
983f48136a | |||
edf881dbf1 | |||
287bfefade | |||
64d6f13b87 | |||
fc71032dc4 | |||
81cb54fc15 | |||
3d46a45fa8 | |||
406419bc0f | |||
a73e125c04 | |||
71309d223d | |||
15482e7367 | |||
9ff9a072e6 | |||
fc4c3c3eb5 | |||
1882451ec0 | |||
2b8edbbb1d | |||
446b51e164 | |||
11f7e275e6 | |||
0e2a577b42 | |||
08071e5634 | |||
350ac11554 | |||
cd32085a75 | |||
d88b237f1e | |||
99ce015f42 | |||
55b3f97be0 | |||
958165888c | |||
68bebd67f7 | |||
82a6fc5ef9 | |||
86a45ff561 | |||
84c2458ea7 | |||
c06f9a1ce3 | |||
d912d4f34c | |||
59607dc495 | |||
bef14cf424 | |||
59078c444c | |||
4e1d780554 | |||
44f9fa6ce5 | |||
a1b90619ba | |||
b42e2e0dff | |||
c55f900081 | |||
4acd658635 | |||
94fa140888 | |||
bdaab4184d | |||
98a9daf4f4 | |||
716d50aa21 | |||
876aa5a78a | |||
e0a35e13d5 | |||
8ef29b65ff | |||
a1d0396c55 | |||
de67978a7d | |||
b57be3bb41 | |||
dcf28bf320 | |||
1b8a66893e | |||
25ab4647c5 | |||
3ce5be7715 | |||
603ab40e85 | |||
c1b5daf5a8 | |||
c296bfcaf9 | |||
7d832ae100 | |||
4c7d833233 | |||
3f88de9407 | |||
2e728f7fff | |||
d543b13e5c | |||
00f3c58bb9 | |||
ed44073a58 | |||
2c41bb8490 | |||
1f8a243b67 | |||
17cf04ebea | |||
c7d0567d37 | |||
5615928df9 | |||
5349e46b46 | |||
93fc392549 | |||
89b5b97368 | |||
3b0b90527e | |||
f13ee3e692 | |||
0653db14e7 | |||
bf42807aa6 | |||
c195d22f68 | |||
9cf85d2177 | |||
ba3612774f | |||
dc6a7918e3 | |||
4052dd8188 | |||
47a1811e0b | |||
8eb4a9d395 | |||
ef2721b903 | |||
4ba4d9076d | |||
5652fb1018 | |||
44e47da4cf | |||
a153b61098 | |||
a4e956a7cf | |||
40da51f641 | |||
35c9f0dc2f | |||
d7efc45c04 | |||
dc40a93317 | |||
0a5a841994 | |||
746e313a76 | |||
5c2a90814b | |||
d4fa9744e4 | |||
5bc39f8c8d | |||
ef75875ca3 | |||
40035380e7 | |||
8f38eb7acb | |||
40039d8068 | |||
208ef7bd62 | |||
de4e17b76e | |||
73ee57a6e3 | |||
5e38056459 | |||
a55f7aeff0 | |||
3e3a1ef30d | |||
03d88c7965 | |||
b7519e5cfa | |||
7b13977c3a | |||
8fed1fe792 | |||
bc7b589611 | |||
5d8f7da3aa | |||
73cf7d5cb4 | |||
72c4fda613 | |||
01ab168774 | |||
aec463c606 | |||
30f29ee8e7 | |||
20b0c80b0b | |||
0b97d07ad6 | |||
7ca2a2a863 | |||
d3c0d92d28 | |||
916dabe5f4 | |||
91934ebb5c | |||
0bc35a71e2 | |||
ec789b0198 | |||
59c0689ade | |||
8f5b7f367c | |||
184a8493c8 | |||
1f3dd000ad | |||
f9f44bf743 | |||
500e49f0ac | |||
e3a5e24ef3 | |||
173a1ac8e4 | |||
2d89b5d13d | |||
3af103aa61 | |||
975a11b37f | |||
9c01ca42d3 | |||
4acb676f2e | |||
df816c9c80 | |||
2a8dd4758c | |||
d41988437e | |||
a7ed74f573 | |||
8fbb966ca7 | |||
6f68eae9dd | |||
bde4cd7982 | |||
835618c678 | |||
1e20b2ca36 | |||
294e56d529 | |||
8e354dae00 | |||
0a1a989fa9 | |||
c414f45ddf | |||
96cdf035d8 | |||
24f32e373d | |||
f9d483e76e | |||
af76651ccc | |||
f1ffa7a367 | |||
3887be464b | |||
f89d9f384e | |||
3400af6888 | |||
c839c05620 | |||
737ec52e9d | |||
3893799183 | |||
71b5970450 | |||
53f059ee8f | |||
a7d5c55926 | |||
ea991f7edf | |||
74c4fe10e9 | |||
40ae89e3bf | |||
983e487a8f | |||
5e55587633 | |||
561d402c65 | |||
6375454fe6 | |||
92b82605b9 | |||
899aafbb16 | |||
dde68ff954 | |||
e084835fb1 | |||
e17bde99f8 | |||
4253662231 | |||
a61fe4177f | |||
049f118c1b | |||
54fd33fb80 | |||
bd6a39c364 | |||
14744f27c5 | |||
b6e8847967 | |||
d7d359e3ee | |||
8cb1f65e7d | |||
22786c8e88 | |||
9228d7f15d | |||
39ef57971c | |||
17b862cf82 | |||
2562a3b1b0 | |||
66c06eb1ad | |||
d2a112fa72 | |||
3cc812711b | |||
fde89156fa | |||
2baf90209b | |||
646655d09a | |||
df75451a0c | |||
c91304f191 | |||
2aa940f55c | |||
34b84f61e0 | |||
dc4ae4b4cf | |||
1b72fc10eb | |||
4c693ea817 | |||
1997b86a00 | |||
a756161dc2 | |||
8e12707f88 | |||
675b5aca0e | |||
90692f0f2e | |||
d0d36a5ebf | |||
eef07539a6 | |||
7e8ce24116 | |||
f95b8ce07e | |||
3f4e02b8c7 | |||
5fbfe6996a | |||
183a8629a4 | |||
2f18e8565e | |||
a788d585f8 | |||
c013dd4ca6 | |||
7b56daffe6 | |||
19396769e2 | |||
bdfe71ae93 | |||
ab8199f7c9 | |||
d7c4f40171 | |||
99fdba0165 | |||
939e2f76f6 | |||
d05629be3b | |||
8c75f2155d | |||
be5e75c804 | |||
2ca7984d55 | |||
5576031b44 | |||
b9b512f729 | |||
27cd01f606 | |||
2780dcc487 | |||
d66a8c8189 | |||
9ca1faf865 | |||
b2222e7e02 | |||
e09abc5b5a | |||
a7ee2bcaba | |||
417ed3aa85 | |||
e34c7da830 | |||
e2b8b7c0be | |||
5a219e2588 | |||
f015d99117 | |||
dc63ceb5a3 | |||
d6bc63fa38 | |||
e8ea3be843 | |||
a6aa35e598 | |||
6091039223 | |||
f222bc1e30 | |||
1530c28e05 | |||
a787b9d2dd | |||
3bf3e5d760 | |||
4aeb6c4e78 | |||
eef047bc5f | |||
b9b38f0ad2 | |||
afdd405995 | |||
414dd95a0b | |||
acfd0edd38 | |||
7c9735a995 | |||
332937ef24 | |||
81241af7ac | |||
a92d97cda7 | |||
e1160f19be | |||
5f57376899 | |||
dcb8d6740e | |||
9a55020286 | |||
76b77ec3c2 | |||
2d5bb26b02 | |||
13be065ed9 | |||
045a989a03 | |||
ae0253f34a | |||
d5d9971c28 | |||
60471c092f | |||
5efe9be051 | |||
5ca7c2d40f | |||
26b17aee14 | |||
5de5b52beb | |||
daac33cdc8 | |||
f7e1c21596 | |||
def64efdfc | |||
843b3a2197 | |||
54c3a5da3f | |||
1c85c24ed3 | |||
b5fa4b58ca | |||
0cbdd54fd0 | |||
79742a397f | |||
5b80e944be | |||
53193c9779 | |||
16eb691e7f | |||
d3650ce3d8 | |||
bee6d73755 | |||
363e1ab775 | |||
dc5ac88a19 | |||
dcff6c9940 | |||
129010e4c2 | |||
6fb538ed1d | |||
c4ad12c1c3 | |||
10ad984334 | |||
27d16a7881 | |||
3c69442dbd | |||
14aa6d090e | |||
49dd7b6a0a | |||
532ccb647c | |||
ba0cdd3010 | |||
86db592b5c | |||
053dabb7ed | |||
22acdc2728 | |||
548b0e5fc2 | |||
722251da40 | |||
c286fbb9dc | |||
7526ef77b7 | |||
4e9d62ff81 | |||
a08f6d9795 | |||
4fc2678438 | |||
c73d7181ae | |||
9f99c9955f | |||
c35671c0a4 | |||
1f6da8c7d5 | |||
491654d882 | |||
12b49167b8 | |||
960e5e25e5 | |||
aed5c7caad | |||
d528dedd50 | |||
770980de69 | |||
7fb66eca25 | |||
991e665fba | |||
e210715958 | |||
6ddf5508db | |||
5cada5cce1 | |||
f7d4cc9cab | |||
8499bbdd17 | |||
51f47535e8 | |||
c2c4aea97d | |||
e6cb60ee22 | |||
7369dd6f24 | |||
0e3eeb4e71 | |||
128d4ac8a9 | |||
523c785e8f | |||
3c30474417 | |||
9601b5d18a | |||
ab931cf872 | |||
a8609ba0ad | |||
c8584e5d36 | |||
01308e4c7c | |||
65dbd50594 | |||
3d4067a464 | |||
a3c7ab99b7 | |||
4d36b2f6e9 | |||
f0b8f0cc7c | |||
2bfddcf29f | |||
2e52fcf1eb | |||
16e15f50d2 | |||
3cf55c195b | |||
cc43bfa725 | |||
171a79d04f | |||
6d11a81994 | |||
58b29f1503 | |||
60018d265f | |||
da604310c6 | |||
513c69169e | |||
c77cf717aa | |||
115b7e42c6 | |||
a622a281d3 | |||
e672b1f2ac | |||
7431206247 | |||
fcfce99e9e | |||
6b710f7ae1 | |||
c070037357 | |||
a4cacb55eb | |||
69b52903f0 | |||
68f51e0adc | |||
374a8ec263 | |||
a25cb2d1e0 | |||
9f5b490800 | |||
cd9ae66b35 | |||
471375adbe | |||
d72cfc9d57 | |||
37f39d6db5 | |||
c1cf46c5c3 | |||
ee8b8f52aa | |||
cf07d428a1 | |||
17650523a8 | |||
95383ee6a9 | |||
7ca74375cb | |||
a3de110b52 | |||
d5205a01cb | |||
a892054448 | |||
b8ffcf973c | |||
519e9e1ae8 | |||
4a5467bac6 | |||
b608fa55f0 | |||
b64ead5cb8 | |||
3822455928 | |||
8fd2a97c44 | |||
d43187f7ef | |||
fb852f7252 | |||
53c4c8de8f | |||
9c55fc0f13 | |||
4d88b4bc26 | |||
669df70da5 | |||
c8eb164f01 | |||
0f02e66170 | |||
9e351b8fe1 | |||
bd61cd0267 | |||
98a6fb9192 | |||
dff4e1e19c | |||
a5a598104f | |||
1cee9b32c3 | |||
d15d6b7a63 | |||
296dc0622f | |||
7f44fa65a7 | |||
e7c74cbd69 | |||
24864ee71e | |||
90b303faa3 | |||
304584c291 | |||
7069a83727 | |||
6e5cfd2cd2 | |||
36ff0dba1c | |||
c485c8a8c0 | |||
549ab2ecc3 | |||
09869af90f | |||
e7dff9eb0c | |||
0a1af2ff36 | |||
53b7bbf3ff | |||
b3bd6ca925 | |||
8fbb48cc2e | |||
724ce8c22b | |||
2f36f17fc0 | |||
c349cb2d16 | |||
3d4b1431ec | |||
4c3a543f7f | |||
7360e1ea2c | |||
241f0acfb4 | |||
a58034b316 | |||
be8d06c6ea | |||
3414ef276e | |||
8926f764a5 | |||
9bd9590767 | |||
4c7087ccdb | |||
5aabe93abe | |||
b4a711ea9f | |||
69de7680f5 | |||
4005815114 | |||
b7ff38b1ef | |||
54af220107 | |||
da7e362bce | |||
2227d471a4 | |||
2961bf06c6 | |||
94504ff5c8 | |||
76698d38f7 | |||
ef95da6d3b | |||
ed24100976 | |||
24b2f1da2b | |||
31e9dda2c8 | |||
0223aa6121 | |||
b50ed5c22c | |||
7659f2e24b | |||
ba82532812 | |||
5b42084912 | |||
ba2bf82540 | |||
fa8d324929 | |||
5aa0507f6a | |||
5b2fa3cfd3 | |||
fa4ea34401 | |||
3049878aa9 | |||
055533b6a7 | |||
4ba478267e | |||
eb4b7d2d8b | |||
970b22f98e | |||
fd3cfbb678 | |||
0c8d085666 | |||
cb11380515 | |||
5b9c96b9b8 | |||
af015982f5 | |||
cfe5dccdd2 | |||
22c957a93d | |||
6b468f9b2e | |||
93ffc67bfb | |||
43db4ffcd6 | |||
68025ce09a | |||
1ea04ffc05 | |||
48f8ca5483 | |||
32b72f39f0 | |||
d15cf60c49 | |||
03465b621b | |||
a107e9edc6 | |||
3a6cb6a5d2 | |||
ecbc25044c | |||
92c411f86d | |||
1be5b69174 | |||
f49b45832c | |||
77c53559d0 | |||
00f13cc074 | |||
e1fc44f5d6 | |||
13ce3756c2 | |||
32489c7426 | |||
61ad50d40a | |||
e7cf37d99f | |||
2954a14c3d | |||
cc956744d7 | |||
ef665889a1 | |||
f723a27a71 | |||
84d24c08e1 | |||
0d8309509b | |||
b5e9264579 | |||
11a4370e15 | |||
a3b2d6735a | |||
5b77e67dff | |||
39ec188003 | |||
def4127bf1 | |||
7342d4b6f0 | |||
20419d3d49 | |||
697f6a55a5 | |||
15ae924035 | |||
6c8e322fa1 | |||
17e98e1678 | |||
47f233a4a7 | |||
b04c3cce09 | |||
2f7857f0fb | |||
fae5c521d8 | |||
4dbc871169 | |||
2694a3b734 | |||
e0ad9ecda0 | |||
0b1e34de40 | |||
abd4628587 | |||
27b9eb5e38 | |||
f2df1c79d2 | |||
d56cf6a92d | |||
63c9c2d2be | |||
f2a545479d | |||
7dc74decb7 | |||
39ab72ebdc | |||
3102dc8344 | |||
436e7388c3 | |||
6174dffc2a | |||
6bb6588ce0 | |||
e0601df59d | |||
0b377bd445 | |||
a28c02bf89 | |||
1e3f41be8f | |||
81f6da173b | |||
e0827f2ad5 | |||
cc0f3c1422 | |||
aee67f08d9 | |||
a4bbc35005 | |||
99d73906a8 | |||
96a61d21db | |||
45ae62787a | |||
dcff76e8b9 | |||
ba662fa7a9 | |||
93c2df23bf | |||
3d5bcd5883 | |||
85b5c365fc | |||
da51d884a1 | |||
b7385a77ad | |||
bf8ba89394 | |||
9c211f9625 | |||
c9f24e6a58 | |||
649d01e52a | |||
5d203c318f | |||
dd03dca321 | |||
31abafe0a1 | |||
c7c38ac16e | |||
dcdaa921d8 | |||
f5a4de7428 | |||
2019b2c911 | |||
62cb1b56dc | |||
1f79e624d1 | |||
d7ea389c84 | |||
cb142b6df9 | |||
c3c72f689a | |||
9ceee07d83 | |||
d863526ca9 | |||
84c659e246 | |||
23cbfa791c | |||
ec147bd839 | |||
fa63c2160c | |||
b188b8c3ba | |||
3fada8d100 | |||
475d07c72b | |||
6cdfa73dd0 | |||
c2766f4e82 | |||
4f6924c622 | |||
55047eaa10 | |||
280aae6fc5 | |||
277681096d | |||
1a453872c8 | |||
6f916c1240 | |||
c8c6fd7153 | |||
7005645592 | |||
5260021447 | |||
7325053dfa | |||
15b4173a76 | |||
7d401853b5 | |||
58f10026c4 | |||
39b479dae0 | |||
2f31ceca47 | |||
ed2f5e0efa | |||
ca1bc7e80b | |||
cfbb1a1e77 | |||
eb6e1af46d | |||
8de3c20e50 | |||
ebcd59ae4f | |||
55037d1107 | |||
5f1f42ba54 | |||
3dee2244da | |||
afc88074cd | |||
0b9c4245f9 | |||
4b534358bb | |||
a44479d0a0 | |||
bfe9bc912a | |||
6d534f10e6 | |||
6d28a209e4 | |||
f6dee72a88 | |||
e88d652f2a | |||
aa0244765a | |||
538d0446b5 | |||
7e9ac7650b | |||
7eddbe5d7f | |||
ae007513f5 | |||
6e5774b9a0 | |||
56ef500716 | |||
e2fe62d4cf | |||
5e60215470 | |||
01d1da67ee | |||
eabe961197 | |||
b788c36909 | |||
66fbc2a1b8 | |||
24679d8676 | |||
88c7dfefe6 | |||
2f810b2c1f | |||
6d385e8cb6 | |||
475ffd67f5 | |||
efdf347f9c | |||
9e0583045c | |||
7a63e4f7d5 | |||
753b5bc305 | |||
79a0d007b4 | |||
67044ef55d | |||
c3e8439954 | |||
4754e495dc | |||
3fda893f00 | |||
da4782e67f | |||
0e52d9297f | |||
d0400a1188 | |||
8042433cb0 | |||
1ba6fd3f42 | |||
7203169c3d | |||
053b23d902 | |||
9bb349e1c8 | |||
96643e7ce2 | |||
cb6ffa1211 | |||
4d95c3d39a | |||
c3271ac22a | |||
b1eb84c57e | |||
794dcb58d3 | |||
b3441eea4c | |||
25eaff447a | |||
9c5510b28e | |||
6315acae94 | |||
c3f14bb7a5 | |||
181d766941 | |||
97c3e9d59f | |||
443e423b58 | |||
f87b84593b | |||
f981dd9175 | |||
e48e36bde3 | |||
99cc7cdc15 | |||
0083443050 | |||
8815ace418 | |||
9f65b787d0 | |||
660546d0ec | |||
58cdc22791 | |||
570574df5b | |||
efbb147f65 | |||
02baaa4813 | |||
8942b7106d | |||
bcf55b0b4c | |||
d909fb0b1f | |||
6fda7f3da4 | |||
07ea6cf582 | |||
c38195f59e | |||
6606ce69f6 | |||
17d5e2bc99 | |||
d5fd742763 | |||
6654f82522 | |||
02e4921ac9 | |||
39bf104a03 | |||
b3398eee61 | |||
18d89c9c89 | |||
a00f82797b | |||
4d7a9db44c | |||
852746e032 | |||
1b6ad15bc5 | |||
c288975898 | |||
8f389361ec | |||
7cdc118c8e | |||
d66cf31ffc | |||
c2d03e5e21 | |||
ccb7bd0630 | |||
ff72751f13 | |||
10e29355db | |||
4f42de9704 | |||
69950e3888 | |||
e2b184515b | |||
3053e022d3 | |||
b9b8920227 | |||
b4c5bdb093 | |||
0254cba4b3 | |||
effb92dfae | |||
5b864ede13 | |||
ee46b9b44f | |||
c079f38cbb | |||
ba2fd31e62 | |||
eab7f9f101 | |||
e14e43bda2 | |||
e116816131 | |||
2e82357611 | |||
1de49ba369 | |||
f27187c063 | |||
19944c2424 | |||
8410278b6d | |||
9b9116c79d | |||
2dffe65cfd | |||
260a061f9f | |||
cf37c003ff | |||
dcc8ff4ce7 | |||
6057c7a373 | |||
498a2ffba3 | |||
047488c5d8 | |||
3959511b80 | |||
024e3b30ac | |||
8c6468a025 | |||
23595272fe | |||
9264f43511 | |||
918d8c9909 | |||
31be29a9f3 | |||
f22a6eb00e | |||
e9fb5fdb89 | |||
47666f548c | |||
0b837e2f0d | |||
dfecca29da | |||
1eae7c81e9 | |||
a04f7c0d5f | |||
9d1175e2b2 | |||
3e201181bb | |||
7938ff34b1 | |||
b637b9322e | |||
6bfe214346 | |||
9ba8059e88 | |||
763f8d470a | |||
9cabd6638e | |||
cd8a837956 | |||
5cecd97493 | |||
5df8a3ba95 | |||
28b4f4abce | |||
5eaab85fc0 | |||
357a0733c7 | |||
835ed0f35f | |||
1144ce97f9 | |||
23cf11a788 | |||
d0a04bf309 | |||
ddc229b69b | |||
12444a8afc | |||
a186dbc1d4 | |||
04ab03664d | |||
6d3a25d897 | |||
3bbd12d560 | |||
c049cf2206 | |||
3ceb2b85da | |||
fac997c53b | |||
f79110c637 | |||
c2a904da09 | |||
ded78e5688 | |||
1efa0ca4d0 | |||
758f7a7d8e | |||
8eb0596463 | |||
c45a70c3b8 | |||
0100a39e21 | |||
17f7f06ca5 | |||
ea57587b7c | |||
a781800276 | |||
b405942b0c | |||
0fba79cda2 | |||
a9e3cbd534 | |||
af95dddd7e | |||
ff0a91422a | |||
014a7137f4 | |||
4945274080 | |||
8c2cbdd385 | |||
2f5ddd9c96 | |||
6e5f076330 | |||
3255d2b197 | |||
6e7ca05efc | |||
6ba5fdc208 | |||
74edde0a94 | |||
50cdc0ac1b | |||
252e3e9487 | |||
c13a4b8c03 | |||
05c1398b4d | |||
1583293694 | |||
ad987021ce | |||
9a800e8fa2 | |||
0bf9263297 | |||
ef179e6a00 | |||
caaeb21e59 | |||
c77656e2dd | |||
5f2897be0b | |||
6ce940315b | |||
656607b640 | |||
b0534177e0 | |||
7df2b4aeff | |||
bfeaa7d564 | |||
dd3b27e971 | |||
db4f508737 | |||
08ea38f197 | |||
8572911e94 | |||
f503832abe | |||
b72c7a89a9 | |||
a8fced8846 | |||
0984fbc748 | |||
22ad701134 | |||
c9df9afddd | |||
c8b5b81516 | |||
c8447d21bd | |||
4ef6f1ab2e | |||
bb52fb798c | |||
2ecf9f3f2a | |||
8683c0335b | |||
419b153b17 | |||
f95e2c7e7e | |||
659356a97b | |||
ead169a402 | |||
95429d55ff | |||
0f0fd25038 | |||
9fa2c398e7 | |||
13c2fad240 | |||
7823c23932 | |||
2f3d41f081 | |||
d3069dbec6 | |||
f98aeca146 | |||
a1d0f1e5d2 | |||
a12b5f930a | |||
b342a69bbc | |||
718d7fe5fe | |||
f72de51a6f | |||
89ef77f750 | |||
e7cf1e0580 | |||
7a6e326ec6 | |||
613dc1122a | |||
3805172f9c | |||
f05e1719cc | |||
a91ca99b1f | |||
7a86a32040 | |||
148a060daa | |||
2ebaa51514 | |||
0d95c08cda | |||
d6f278867f | |||
0341f3239a | |||
421dba0184 | |||
de62d8ebdb | |||
02134172dd | |||
023c9bebe5 | |||
ecb29de82f | |||
1084d4ab49 | |||
37bb90140c | |||
542f236dc4 | |||
a188312929 | |||
61e8ed6623 | |||
c0869ecfb3 | |||
28ef1af376 | |||
e71d151571 | |||
f9e959e098 | |||
634887c0e7 | |||
5e94f9a100 | |||
c4ce24647b | |||
bc7cde0f01 | |||
cca2616637 | |||
9b6a1b85b1 | |||
c50faa97ca | |||
60b13d9948 | |||
e315215983 | |||
a295255e58 | |||
fcbc38cb22 | |||
5a52990b91 | |||
2cf25facd9 | |||
bd820fdf84 | |||
627814cc4a | |||
8f102fe674 | |||
15d3e741e9 | |||
3c2438425b | |||
86d5472d91 | |||
671deadde1 | |||
f84f362de3 | |||
e6909bda89 | |||
539d8f09e0 | |||
6b1a47183d | |||
41485599f3 | |||
f6a6f26e0f | |||
f16f6a290b | |||
cebe49d3c9 | |||
e524322c43 | |||
8e96b450e2 | |||
599a55e691 | |||
0971d305e1 | |||
80d326bd49 | |||
e12933a3aa | |||
67eac733d2 | |||
56f4e56094 | |||
dd944ef73f | |||
c60d7563a8 | |||
d4b83681f1 | |||
0cd8431698 | |||
755d2d572f | |||
02958c07f6 | |||
a6b6d74c00 | |||
e6dbcd0f46 | |||
d529b55651 | |||
180a41af68 | |||
1421eff382 | |||
d8792b3c36 | |||
b8eb2f2f23 | |||
5a7f33496b | |||
e7cc1d606a | |||
5b04abd5c0 | |||
040673464c | |||
7eccbcd30d | |||
99320e1ffc | |||
39722df41e | |||
c16a79df5c | |||
72d366fe21 | |||
1425e63029 | |||
72abde603d | |||
bbce2ad7d4 | |||
2cc954d5a5 | |||
3408468121 | |||
b15f86e1ce | |||
d251f22ebd | |||
df6d6e0b1d | |||
ea37e82e69 | |||
168abc6d6f | |||
6108962291 | |||
85b551a388 | |||
c5006e025f | |||
5a227d8d7c | |||
de7713d6ea | |||
2fb9b7ff1b | |||
658087be7e | |||
8c33f91529 | |||
0366743fc3 | |||
55b7fe9998 | |||
ee7857300b | |||
d5aedbe892 | |||
92c547830a | |||
c291c8e2cb | |||
005c4a1cc5 | |||
c4335e2817 | |||
3f68377c3d | |||
4413660d47 | |||
4ece0eb27c | |||
7f0d7f4d12 | |||
49804fe017 | |||
6d7d2e439c | |||
807c89441a | |||
4022376b3f | |||
5e3f6d203d | |||
f9def8cd30 | |||
3414760bdd | |||
48a1acab52 | |||
78c65c330f | |||
5ff98fe701 | |||
af2d22c43d | |||
35a57cb213 | |||
fadb2d9004 | |||
f0f426b2d0 | |||
5de7960f01 | |||
d655093123 | |||
953365d090 | |||
7cd16b9e2c | |||
d25de63ac8 | |||
1a0ee18d62 | |||
1ab2ebc719 | |||
ed55355363 | |||
9ba5344f3e | |||
25dcc7631f | |||
ec495c807f | |||
9b5299131b | |||
9bc8864d03 | |||
56f33bc266 | |||
31e2bdffa8 | |||
d80eeb6959 | |||
8969f35bb5 | |||
478f8821a0 | |||
04b12fc0d6 | |||
f2800b90b2 | |||
44225e4010 | |||
51a56bc4c6 | |||
1217c6b7cc | |||
8c76e78ec4 | |||
5129bccebf | |||
fe91700dc6 | |||
e24453b9f8 | |||
4cf197998a | |||
a4c3ceeddb | |||
17857a311f | |||
588823b437 | |||
de043a4bcb | |||
955423c79b | |||
804933284b | |||
d752e26eb2 | |||
ff1be4cd28 | |||
485ce640fd | |||
dca6ad87fe | |||
356e6a88f4 | |||
621b659aa9 | |||
82be6215af | |||
3c335c3590 | |||
a37bf9a516 | |||
9f211ba0f5 | |||
bb79018f92 | |||
310ce6dcc2 | |||
5024e217d7 | |||
2dd572b15c | |||
828e5c1f79 | |||
c8ea99f9da | |||
7d579b913c | |||
3d69693692 | |||
fd5f101bab | |||
2303dc4f28 | |||
9d7b939554 | |||
e128d87030 | |||
acd8734937 | |||
4d03ec0e85 | |||
bf1bcd1e08 | |||
346e1c14d9 | |||
df71aa425f | |||
715d02aa14 | |||
e53375b7b6 | |||
891708cfc9 | |||
fc2f6b8456 | |||
11a35e5d14 | |||
4ae754a222 | |||
b07b6f1d40 | |||
70311ebca1 | |||
fd83d9479a | |||
87994d2c03 | |||
55748dbc55 | |||
6a5475f65b | |||
5af3bd4728 | |||
e13aa65f49 | |||
7b4853bae4 | |||
51cee50ee3 | |||
27562e92db | |||
d78d29ff8c | |||
08a4f10ee7 | |||
b54ed980ed | |||
eb6975acaf | |||
97fbdab3b8 | |||
4be8929844 | |||
cf9aa4fd14 | |||
9e45203679 | |||
b7fd86ec50 | |||
a959fae66e | |||
bb290cefae | |||
850aee2448 | |||
51720745dd | |||
6bf2531b19 | |||
e698d355c1 | |||
da0c372fdf | |||
5aec1798eb | |||
8a052dc858 | |||
f69c6e204a | |||
8555d51bc7 | |||
ad4300f52b | |||
3557849371 | |||
be58159550 | |||
5c23ea71c4 | |||
288009d6fb | |||
29b8666b10 | |||
c68200cf42 | |||
90c3d98dd9 | |||
c44415494a | |||
96499c898f | |||
ffa3936b4c | |||
a6247aafa1 | |||
62f7d0fe5c | |||
74e6d379d8 | |||
49c9f782ab | |||
a681c8553a | |||
f4caf263d4 | |||
15fefdbb8d | |||
71b8e271b3 | |||
341d5847d6 | |||
2e7a3e9ae6 | |||
5fb7d3d3b0 | |||
6bc28b925c | |||
91a2506c82 | |||
cec60b792c | |||
7215889b3c | |||
32a4a549fd | |||
985cadb73d | |||
023c4ffdde | |||
06bca0cc66 | |||
526537fefe | |||
5beae0633b | |||
e666d283dd | |||
19a6c158d2 | |||
e2cba6ed7d | |||
a48573efe8 | |||
6fadb7a3a4 | |||
53fc2ed8bf | |||
d27f0b5c22 | |||
e7dd7525cb | |||
a67cb92e6b | |||
592fd37b3e | |||
7eb3e3bce6 | |||
c89eed56b6 | |||
b90aac0d43 | |||
9d21065e25 | |||
7f2885ec7d | |||
e6045ee0b7 | |||
f2828a08bd | |||
cbb1d9f2bb | |||
1d3aae6f92 | |||
ab0bcee144 | |||
c5a75fd807 | |||
c365eded5b | |||
7c64b1889f | |||
8f034896a3 | |||
7bf3e70553 | |||
695bb6ca87 | |||
ffe57a004c | |||
336c2d5461 | |||
e51ec671a5 | |||
96c9ccc81a | |||
eca85d5880 | |||
fc78c64e8d | |||
e25b256aa4 | |||
9935aa43ad | |||
784fd26473 | |||
f4cdd35b3c | |||
fe4447d568 | |||
72b9276ec9 | |||
b30bb8dd91 | |||
033aba9351 | |||
704775168d | |||
c79d50f38f | |||
624425a288 | |||
fcdada53f1 | |||
9a68f23dd2 | |||
78912093f8 | |||
ac08a499a3 | |||
7df7e340ce | |||
0fecea1427 | |||
f1b32840d0 | |||
18a8abb2bf | |||
1d563a7acd | |||
1e1e242570 | |||
d21471e24e | |||
9c6ee5fcd0 | |||
7f24975a60 | |||
95715fc71e | |||
6888cb3d7a | |||
2be0a1d35b | |||
cf10b336e7 | |||
9485e16e3b | |||
84a0105625 | |||
f922903b62 | |||
9a840e5021 | |||
1389d173fb | |||
7a29b24720 | |||
15f8638b1c | |||
31c5e67ba6 | |||
6899ee5ddd | |||
b62b11bd6b | |||
641c671bac | |||
2f0b8bc541 | |||
db2c606d41 | |||
e31f62045d | |||
ccee818034 | |||
2ce9cdab9d | |||
74b7d1ace1 | |||
f1b0547f0a | |||
e1ee90c218 | |||
a972e4cd4d | |||
fcde671ae2 | |||
8b91ea5532 | |||
942e2ebe44 | |||
472641cea0 | |||
e511bfcab5 | |||
c303371b26 | |||
f7475870a6 | |||
d8be830fce | |||
b3c3000004 | |||
52d1500155 | |||
c6ebcd1eb9 | |||
eece138fa7 | |||
ca1ff3ea11 | |||
a8f9ff52f3 | |||
a1e9956290 | |||
1527ac6c47 | |||
6cb9988d63 | |||
b197e90206 | |||
976bdf1087 | |||
5c6e36eb95 | |||
0260b8c795 | |||
39712bcdb2 | |||
9d99c7244f | |||
05d7c575e4 | |||
056236cafd | |||
1d429b2165 | |||
a40103d849 | |||
b97577bd94 | |||
4385cbaa65 | |||
98766b1d07 | |||
afbaaf93c5 | |||
1db86500de | |||
570936e39f | |||
43ffe7257a | |||
c4fbd0bef7 | |||
f63e5d9319 | |||
c57759f191 | |||
a33162bb66 | |||
c77faf566e | |||
e51acd5bcc | |||
71b400eb7b | |||
0ca2a390d5 | |||
e8d43d8fde | |||
81828ae7f4 | |||
1aa3053b12 | |||
7c5c2139ab | |||
8912b11f56 | |||
8d72a37f3e | |||
becc820159 | |||
68a1edd4cc | |||
42d394973d | |||
bca437617f | |||
1ebe172c2e | |||
c25503b142 | |||
10583f951d | |||
39550746f8 | |||
e3895b8a95 | |||
c0f69f3245 | |||
55b1b7745b | |||
a20979d5f6 | |||
2ed04ffcdc | |||
cf598f71fd | |||
1c22e464b2 | |||
fe12d0dc78 | |||
7b87392f47 | |||
e2d7b25e0d | |||
d749dd3ea1 | |||
2a4061a3fd | |||
41560b47c4 | |||
e89c2dd8d0 | |||
3297a76195 | |||
5453c4cd96 | |||
8e6bed988e | |||
8c6fb17d29 | |||
3de72e4124 | |||
d751ca7596 | |||
974005b064 | |||
1bd8fdb766 | |||
29007e406d | |||
c0ad47a3fb | |||
4b62ba9017 | |||
0addaab270 | |||
bf10e98891 | |||
44623a1161 | |||
c5894e08bc | |||
7e8eec57f0 | |||
5b21b71c9a | |||
cd6ab209b6 | |||
a3c44124ab | |||
502dd89290 | |||
85298e345d | |||
93a23b9ae0 | |||
90f33dd11d | |||
8d0de89ece | |||
d9a38928f5 | |||
25aaff2ee1 | |||
5bc1b6f9ac | |||
4abf15c50c | |||
9c13d6e8e6 | |||
91147ade2e | |||
e3189f97ff | |||
4ff43e1324 | |||
66725b7b37 | |||
5437e2da29 | |||
c83f5013bf | |||
ac9d044cad | |||
9e83814e61 | |||
f185fabc11 | |||
4857c53a49 | |||
4e7ffbfbac | |||
02308c4f71 | |||
a8f4f14bdc | |||
f02213a661 | |||
09536423e8 | |||
fc8eecad3f | |||
feb5f27d09 | |||
31116f0ced | |||
9ebac71521 | |||
ce30888a26 | |||
4d4b527474 | |||
602eeee7d6 | |||
38758d856a | |||
9db59d010d | |||
72eba7745f | |||
083d48e072 | |||
df1bef31a4 | |||
4452d6d848 | |||
41caafcaf2 | |||
2c208f98a9 | |||
3ff712a0f5 | |||
1d141a8ab1 | |||
d5ae854b5b | |||
d863839ecc | |||
66ab701606 | |||
64ac106248 | |||
4099822ba2 | |||
7355906a95 | |||
2b1ba1835e | |||
12703d5601 | |||
e4ebffab8d | |||
c4695bb387 | |||
7caed51c24 | |||
2eed7e33ef | |||
a38508122a | |||
c35587ba56 | |||
31dccab2da | |||
300d7ca6da | |||
563a507315 | |||
a5167bd53c | |||
87743f1aa1 | |||
502fb7e307 | |||
f197191a5f | |||
7e135f6d3a | |||
fba72f0d4d | |||
5666d11633 | |||
540d104b17 | |||
7193e151d7 | |||
1de757993d | |||
5ed6abe3df | |||
649093c0ec | |||
bf913cc39b | |||
ba0c178dbb | |||
c3e93564d0 | |||
d1246a1d10 | |||
f4160b5d5d | |||
936700ad9f | |||
a3034ef92e | |||
bd40c89688 | |||
da4eb91283 | |||
afa50838a7 | |||
4e38cabc49 | |||
27745c5d8c | |||
2f6c97e93c | |||
8b5ca670ad | |||
89704cc5f3 | |||
2c623fde16 | |||
c2f13a1e3a | |||
e483acaa17 | |||
e16f75db56 | |||
c61f413477 | |||
eb0d8c09e3 | |||
d8d8b8915c | |||
4ee354da99 | |||
41979d6a27 | |||
62b2840822 | |||
e23bc4991d | |||
7a280b1a21 | |||
26f44c0d6b | |||
5607ad8c62 | |||
335854f6bc | |||
4d23b60d09 | |||
eeecbf28e4 | |||
4b81bb5c97 | |||
14c4b1b205 | |||
3505692f75 | |||
8d15bfa6ee | |||
e4e8dbdee0 | |||
f085fd5666 | |||
49bfc7421a | |||
01455d70e3 | |||
aa36b55bd9 | |||
348615be62 | |||
e2310732d7 | |||
a78b70178e | |||
6323a35468 | |||
b381497126 | |||
818c514968 | |||
6b267482d7 | |||
2e5e1dd5f5 | |||
3858b26211 | |||
31b9492951 | |||
0de2dbfec1 | |||
dcdb433b7d | |||
ee4fc12e42 | |||
3f195fefa9 | |||
a17cc9beee | |||
0d9be22023 | |||
113411c9b0 | |||
d8ce2129d5 | |||
4aa51b751b | |||
09a2bb839f | |||
9ea3430a5b | |||
4821330a17 | |||
d883007cc6 | |||
4c4217c5b7 | |||
93a0b1ba13 | |||
73530a9e25 | |||
b00189bb9a | |||
a42057d0f8 | |||
9a5e08f2a7 | |||
63f0ded5cf | |||
25ed82db23 | |||
f76b370d70 | |||
fb84ea74fe | |||
f17072c7af | |||
fde8363e0d | |||
ed4244e932 | |||
efbbae5a48 | |||
22e483858e | |||
122f755b21 | |||
3d11355fec | |||
2805af900f | |||
2f3812a1ef | |||
f1269d98dc | |||
a1d7b6bb86 | |||
d40ee6a259 | |||
c79d6ec502 | |||
0e9140c738 | |||
2f541a979e | |||
e2211ed211 | |||
77240e1b60 | |||
ba29e4d953 | |||
355e54a410 | |||
1b607529a6 | |||
2ecc4c7886 | |||
3f257e96c6 | |||
8bc5fb2ab6 | |||
b04de1363d | |||
bd89626e2e | |||
66519de2dd | |||
f013515307 | |||
43ac02e566 | |||
ed4d96f858 | |||
383457f898 | |||
49eec5d872 | |||
c0b90c2010 | |||
398ff1e7e7 | |||
b3d6d500be | |||
1b8b04cf26 | |||
5632424d04 | |||
f1ffd57105 | |||
7f7dc7c294 | |||
5d86e4a9b1 | |||
aaa08f7be3 | |||
58b3a51e64 | |||
03103d2d59 | |||
447e251736 | |||
72d7eb7a93 | |||
df92abc60a | |||
65a0d2b53d | |||
e030375d9a | |||
c4733c15c0 | |||
a86a179f45 | |||
ec482dadb1 | |||
427a1ccd9a | |||
403bb6bee3 | |||
418e9cf3c4 | |||
fa0ab38546 | |||
3b643b8f3c | |||
37a87418b6 | |||
2ea52b0cb9 | |||
931739ac73 | |||
717bace7ba | |||
9de4b1c441 | |||
ff36a8daf6 | |||
8e2e1f8340 | |||
3ae72dccfb | |||
3f273f8d63 | |||
fbf6ec8813 | |||
56731f624a | |||
e5081bcf25 | |||
c0ebecf54d | |||
160547dad6 | |||
6471a2668e | |||
609d2557bc | |||
abd2a58c67 | |||
d7dc6cbc04 | |||
8017229292 | |||
755a80c7ec | |||
1b4eaea6d4 | |||
d4db746898 | |||
29bc3a775f | |||
8d44b5edac | |||
f289411fa9 | |||
32b042014d | |||
940fbbb014 | |||
1799f621b7 | |||
cb4f803238 | |||
0e08ad628a | |||
e0059c7d51 | |||
e122d27176 | |||
bab740d793 | |||
60e4490808 | |||
251a512222 | |||
692535a935 | |||
7c64b8d3fd | |||
c44a1a78a9 | |||
f6667f8281 | |||
6958d11d95 | |||
bfd07b3c94 | |||
01d3599f32 | |||
a0d16dcfea | |||
f0366843ea | |||
86e1e6c082 | |||
117ca7cf39 | |||
7fb55f29b6 | |||
eaa1984d41 | |||
d2222541e8 | |||
9e7668f16b | |||
5dfbcd5631 | |||
de445709d4 | |||
50710838bf | |||
4da2dda647 | |||
afcff73be3 | |||
2196114501 | |||
fd4fed14d8 | |||
422eb14dc0 | |||
7b64680670 | |||
d5b59009d4 | |||
f45c43188f | |||
9d54679e66 | |||
7e64bbe5a8 | |||
1a8bd22fa3 | |||
78214e72ea | |||
bb53b6549c | |||
43487f6761 | |||
6f203c9575 | |||
08cb2fa80f | |||
6c3c030f0d | |||
b60541c92a | |||
d1323b5c8f | |||
06093559a2 | |||
4800fa1c08 | |||
cc7c2a81df | |||
ab09895810 | |||
a9fd36f2f8 | |||
16fe90d6ac | |||
0e260d2c3b | |||
3dc6490e72 | |||
082aed6e46 | |||
d192a7b47a | |||
9e9491272f | |||
e4504a40bd | |||
a914859067 | |||
724707c6e4 | |||
e9ee6859e3 | |||
a67df6520a | |||
e71a93afb3 | |||
25bc56ed64 | |||
31b5db6fa8 | |||
11bf7679a1 | |||
43241a560a | |||
becd62d4a1 | |||
86104b82b8 | |||
cda9248b33 | |||
3e14c2d02c | |||
aef7dca234 | |||
21c1e14385 | |||
4c63e6ba04 | |||
4659cc26ea | |||
67c914819a | |||
51b9ce44ea | |||
d3f3d9b4cb | |||
4198ea7ca6 | |||
8c57a23b90 | |||
ad72c90447 | |||
11e04b1892 | |||
ec6a9f2a02 | |||
30d25f67af | |||
ca94d2b7f0 | |||
0bdb71c122 | |||
1cda80eb3a | |||
a86893c10f | |||
ce7f934c66 | |||
6bc016f3fa | |||
b6dfc8b08c | |||
8b0cb2f0c5 | |||
ac745c8356 | |||
a9228aabac | |||
8321bd8a74 | |||
72494c4411 | |||
10dcbcf45d | |||
5265b74138 | |||
64aae3a9df | |||
4c0726db9c | |||
fc93dafab1 | |||
d62eff7316 | |||
f433d6604b | |||
e409ed0eab | |||
0de2a5e408 | |||
c3aaa5211e | |||
dcbc3b197d | |||
0004896ff9 | |||
5e694e519b | |||
cd7b199219 | |||
f05999730a | |||
ece0b2d7ce | |||
50bf17aca0 | |||
39587ad127 | |||
5557dec120 | |||
52483bf680 | |||
1353afc2b1 | |||
b04488d692 | |||
68f06c8dd6 | |||
e2d5bc2514 | |||
868b3f9463 | |||
83425fa119 | |||
1845faa66b | |||
d617373a76 | |||
127cec0214 | |||
4b30108734 | |||
25af147a8c | |||
1a34fbce25 | |||
4acf0a09ac | |||
84ba1f012e | |||
1a67d70bf8 | |||
d8249d1230 | |||
c88305d2eb | |||
64fd0d6db9 | |||
d4d07233dc | |||
dcca80bb1e | |||
b800b88224 | |||
0b1daa9ebd | |||
15e3b5f531 | |||
0c69ec20c2 | |||
0dcff40ec2 | |||
b934898e45 | |||
9c153cfb3e | |||
c8fd94ea44 | |||
2ddc851090 | |||
f54adf10b5 | |||
b0834fe962 | |||
6ab5f3648a | |||
1ae77da609 | |||
100ba0bd06 | |||
df78d7c0d9 | |||
90007e97ca | |||
916762440c | |||
35a95a8a7e | |||
728cd8446f | |||
f640a4a494 | |||
5ede5b7807 | |||
af1f27e756 | |||
b2decf0266 | |||
8d111da7f6 | |||
22d4efbed1 | |||
3001716a2f | |||
ebd557c1e1 | |||
d349cd91b1 | |||
a2d2a5d572 | |||
b2666a2857 | |||
9abc1f9156 | |||
4283e1f784 | |||
4541b9b565 | |||
dcd28b591d | |||
4e1f37fc17 | |||
be54c580bf | |||
676a95a21c | |||
a3ef3e11c4 | |||
57d099ceea | |||
6028159dfb | |||
748edb81ec | |||
305f3686c3 | |||
009cab8dce | |||
90855f331f | |||
2cdb3a079d | |||
d5b87d32b0 | |||
b2b917d2d8 | |||
9f0c549bc8 | |||
affae99b22 | |||
ed711418f1 | |||
c653a16b57 | |||
64823f561c | |||
e1d07b2fd2 | |||
cdfbda3d3b | |||
78ada980a6 | |||
3830f6fc14 | |||
f783244ad1 | |||
2265cb5938 | |||
c507dda21a | |||
40d87dd801 | |||
0ce8621196 | |||
2089727db9 | |||
c1bb88603e | |||
fee28e20bb | |||
3efb060127 | |||
c61e4d7841 | |||
393398e6f5 | |||
e007918e35 | |||
3c2770bfc7 | |||
90fb5d9f7a | |||
d18289fa9c | |||
bad3434337 | |||
0119f46daf | |||
f8eca840ee | |||
7f6429d802 | |||
94b9b7e154 | |||
3a53e2c960 | |||
01677b21b6 | |||
60047037a3 | |||
e6881b5b42 | |||
8593d0d52e | |||
53d13c3fc6 | |||
442f323a32 | |||
480b775ba7 | |||
32b16de8ea | |||
ea9245446f | |||
ad753d3fa7 | |||
7c9219f029 | |||
eb72cecc42 | |||
bc886a64a7 | |||
75fd407bbd | |||
adb562bca6 | |||
900d0055e0 | |||
7806596fba | |||
deaac32bbd | |||
65297cde19 | |||
fca3e79415 | |||
bcbf3e4123 | |||
fc28b266cd | |||
447fa2fccd | |||
0f21ae9a74 | |||
9364a14d36 | |||
efbce7501b | |||
5332b04f35 | |||
6f5f481fda | |||
90dda5873a | |||
7503e3540d | |||
32e315755b | |||
9188751adc | |||
d24ade91b8 | |||
9b15588188 | |||
97d5700456 | |||
601f87c2ec | |||
052cae6427 | |||
e7729b6863 | |||
0d186dda35 | |||
3de59d48b5 | |||
3c7ac5f835 | |||
41ed694d01 | |||
954b8e53a2 | |||
a3b6b109d8 | |||
4e35e348af | |||
2729747225 | |||
be83ae752e | |||
70429bf350 | |||
add5c3992c | |||
04bfe87764 | |||
879ad69602 | |||
39e8ceb2cd | |||
448749cafa | |||
25219baeb4 | |||
948b01ce55 | |||
0f3a48e4d4 | |||
653eb0fef9 | |||
fc3260d87e | |||
296954041e | |||
1115961892 | |||
6db5c4a6f6 | |||
5d5c94d83a | |||
090732fc2d | |||
206fb82330 | |||
63256b511a | |||
01e4d44e8c | |||
66658c447f | |||
668f57abaa | |||
72f3747d7b | |||
088435c5eb | |||
32b6548be9 | |||
98feee7e0e | |||
28358b6395 | |||
9e7aa60ae7 | |||
ffc34b3676 | |||
b3549e6680 | |||
475e36abb5 | |||
53b32f17b3 | |||
45c893d0e1 | |||
c32b2ae0a8 | |||
747f0cff9e | |||
002a97d852 | |||
f438ae8a3a | |||
d5071651df | |||
8985233804 | |||
877f9ad7b9 | |||
a23ee2b0a1 | |||
e41cbfb585 | |||
84feda1db7 | |||
ecd7554051 | |||
5ae48d52e6 | |||
966c2a326a | |||
278d634723 | |||
f6914159e4 | |||
2e730287fb | |||
a7d090d22e | |||
85990c3213 | |||
fbad4ff65c | |||
c07b6fece5 | |||
e9867e8ae1 | |||
0ea4875b10 | |||
c1346462db | |||
c8be987b40 | |||
a54adcaff0 | |||
fe54af9ba6 | |||
8da26d9de9 | |||
4dddee7424 | |||
39bc6f7bea | |||
948714c17c | |||
e668d7971d | |||
3a96631387 | |||
c093390c22 | |||
32b6c2285e | |||
86fd5719b5 | |||
32f4544f34 | |||
f8f7c1540a | |||
52552b0520 | |||
5651fa3a95 | |||
353368cccd | |||
7a00c676ec | |||
04ddcfecd8 | |||
f3859ff2b9 | |||
0450f39625 | |||
5d12cb9fdf | |||
ec0aa88f4e | |||
f88f717094 | |||
0618bed83e | |||
708ae4c8ef | |||
5c2e890d76 | |||
5ace90f04d | |||
9d8dc793da | |||
2846505dbd | |||
ab29874f09 | |||
9b0861c649 | |||
df1c456347 | |||
05e1b3b312 | |||
3ace25f4a1 | |||
4726ac2481 | |||
252966bcca | |||
f1b1de9a3d | |||
4c168ed9ba | |||
cd4021ba41 | |||
a0d04c628c | |||
b741a1c3e7 | |||
357aa4a097 | |||
870d189433 | |||
c7abb7d196 | |||
fd62ed66e3 | |||
e5a3de575f | |||
894c4b5390 | |||
d9054803e3 | |||
4ff9c942c0 | |||
67d08b15e0 | |||
d2bf8fac5b | |||
a2e890e4f7 | |||
4f41473048 | |||
e6ed4a21e4 | |||
4c061271db | |||
52a6da043d | |||
1748aeb9c8 | |||
f6d66671b6 | |||
3a90a7cb43 | |||
8415460b12 | |||
217db9b216 | |||
be13e8b1e4 | |||
bfb3995869 | |||
5328bb223a | |||
0477bfc8ed | |||
e1065eec5b | |||
082b0d3ef8 | |||
c442c0334f | |||
c7ea3260bc | |||
bbb2798d41 | |||
2bf5606bbe | |||
e82f56b96f | |||
3c7da767d8 | |||
c4e039a43a | |||
5a830c49cf | |||
bd679581e2 | |||
ad178c55fd | |||
adeee0fa7f | |||
88c28ce208 | |||
e013aee636 | |||
373e1337de | |||
2279cb8dc0 | |||
222af38462 | |||
73cb581728 | |||
527ce3b142 | |||
f06505aafd | |||
51292e27c9 | |||
6674746e86 | |||
024765b86a | |||
eab959aa18 | |||
1771d6ff25 | |||
7a569a7c52 | |||
5cf597249c | |||
0a0489d3d0 | |||
fcdd06896e | |||
ea378a993a | |||
5f095a501e | |||
a85eccd6ff | |||
5356826a38 | |||
97dae900fb | |||
f0a969579d | |||
b6f439d91b | |||
d30cd3309b | |||
a32df388f8 | |||
8a911773b8 | |||
f5982fd746 | |||
4f033235b1 | |||
53dbff66d7 | |||
bb9e61202c | |||
c1ac21d5f7 | |||
15aeab1620 | |||
55b55e7c97 | |||
ff228b14d1 | |||
43bbc409a2 | |||
c84c27f7f4 | |||
a813ae07e2 | |||
6ccb4e0bab | |||
65f5c0476f | |||
d0dd69f177 | |||
79b673a17f | |||
3b37469735 | |||
8a7129e21a | |||
7059f7af11 | |||
f937f8f604 | |||
9448828b0d | |||
21245887e6 | |||
72807101ed | |||
25d90dabbe | |||
544eb89198 | |||
e38351fce7 | |||
f00bb85b58 | |||
5b2408f0a6 | |||
bbd4a33f6c | |||
6052b12fb3 | |||
ded57245e1 | |||
8a6e54a06d | |||
a1beba4b6e | |||
664e0015d4 | |||
2230dfaea7 | |||
ea6a2e9f25 | |||
9166baf709 | |||
a64eded521 | |||
a391aebbcf | |||
c3a1ef219e | |||
2895edc9c6 | |||
66df745721 | |||
18798a1cb2 | |||
8296f6b681 | |||
c714330856 | |||
e36e6c85ef | |||
f4e4bb2085 | |||
2844dd2972 | |||
0cf94e3ed5 | |||
9270d3f279 | |||
3127ba3c35 | |||
5c213e5474 | |||
3d9dd6df0e | |||
38359b166e | |||
bd1de32b33 | |||
bf15d3eea8 | |||
a65d3fa1de | |||
b5eda603a2 | |||
df5924abd0 | |||
33038f6ebe | |||
1716b91334 | |||
8ae7f14252 | |||
bc061b78be | |||
4c3674f660 | |||
497d6b1323 | |||
62d92f8091 | |||
098feec4a0 | |||
a9ff48e67f | |||
da42a7648a | |||
5ab7cb4188 | |||
fed6b25be0 | |||
7bbc3523ba | |||
f00d03356f | |||
36d613dd67 | |||
e505fa61f3 | |||
cc06153e85 | |||
d4003452c7 | |||
007282d2bb | |||
094538c0ce | |||
bda2b4ebb6 | |||
20dc5e83ee | |||
24b8b3427c | |||
a731119f9f | |||
0187b3288b | |||
4b037abda4 | |||
c849a30db4 | |||
5d8eb74634 | |||
7cc4225eb9 | |||
f6e88cd659 | |||
bdbf0c94b1 | |||
01e0f58dd6 | |||
f0bdf2a1ae | |||
641c5c1c1e | |||
a383a5a165 | |||
cfa09b84dd | |||
e213080c0b | |||
04d4fea3e8 | |||
89434e09c2 | |||
1a7c79746d | |||
c207ad80fd | |||
970b58b13f | |||
1ed3531049 | |||
a20fcbbe06 | |||
d0b3688a23 | |||
e8f9ba4b6c | |||
f5bec3ff50 | |||
9a55eaf10d | |||
8cdfcc5489 | |||
fe5caca884 | |||
a7f61e63fa | |||
c024d89448 | |||
fa79f51645 | |||
b21397bde9 | |||
b34bdf5c42 | |||
260217a800 | |||
c8b065524e | |||
60f963986f | |||
c507e4907d | |||
afc6ab5442 | |||
c56c2416a9 | |||
d498314850 | |||
8dc3f3647c | |||
67d80f9ae8 | |||
43619fc847 | |||
ad13520b24 | |||
350ea47def | |||
8c388e3730 | |||
9bbe67f286 | |||
ab30b2ad01 | |||
ba5e07efc7 | |||
df8e6750a1 | |||
1537791f06 | |||
77c382ccba | |||
8a47b48912 | |||
f7471eea3c | |||
4161d19374 | |||
375897801b | |||
03cbce8c66 | |||
288e5d894d | |||
b48dd52494 | |||
7fb3cc07de | |||
3af99a7b4a | |||
b4d3468088 | |||
266c267b62 | |||
d5101dff3b | |||
63dff9c888 | |||
7742a99cee | |||
5635505f2e | |||
cc288aec3d | |||
2d96576a10 | |||
a9864471a4 | |||
47a4edb817 | |||
3aba7ebe6a | |||
2b28b91fd9 | |||
18ce58c2bc | |||
852afb312a | |||
d4703d9316 | |||
1bb9ce5d8c | |||
97fc45f32a | |||
4b1251106e | |||
a1e91b00d2 | |||
fac066ea9f | |||
85864ed9f7 | |||
581b837e88 | |||
60a056d5dc | |||
543631f2b3 | |||
d0f3539e6e | |||
e5636a322c | |||
b094936d72 | |||
f3e4cb491e | |||
cb5701f8d9 | |||
c0680602f9 | |||
30dabdf8fc | |||
ede5786d1e | |||
46caf88b2c | |||
98420c27de | |||
a8131365c5 | |||
3e52e32dce | |||
0a09fb1432 | |||
2f6062f632 | |||
066b281979 | |||
125ef0a0ec | |||
65aaffcfe4 | |||
ac11a0be15 | |||
e3f42818e9 | |||
ef2047555a | |||
d953c1cee3 | |||
7c7fcd7ab8 | |||
c885178d5f | |||
14feb56139 | |||
f209aacbfa | |||
55eaa5fb6d | |||
70cf8ed05d | |||
c7c7f9fbe8 | |||
1cb62346e4 | |||
f57c17de2c | |||
0874bf42b6 | |||
3a4839c97e | |||
82abbecddf | |||
e63a7b0532 | |||
e3422e0aed | |||
860b5d0efa | |||
9bc9685911 | |||
cf4b944865 | |||
28c8b03797 | |||
24127a2492 | |||
bceeeba405 | |||
7bcd42e7be | |||
4908a5cffc | |||
c3f9893d81 | |||
25f31f2a14 | |||
e563d77128 | |||
e79ba194b4 | |||
ae9960be53 | |||
c7f4d500db | |||
e188c9703c | |||
b9fbd9bb03 | |||
a58a5fd7bb | |||
9bb5f05cb9 | |||
3693d7ad23 | |||
c624b14e8e | |||
3dd614db61 | |||
d443a28743 | |||
21bb74d16f | |||
1d1ab37546 | |||
a00824c986 | |||
d5aca7ef51 | |||
47cc92f004 | |||
e21e01ca22 | |||
6d11154652 | |||
6b245a39ee | |||
4f7c971ee7 | |||
0677cf0cbe | |||
904a2018e0 | |||
b6fa9299e5 | |||
21edc6a82e | |||
a367b90a82 | |||
a84b5ef81b | |||
5c94833b8f | |||
b85ac03136 | |||
7fed0faa44 | |||
02a567e46f | |||
0b009f06a9 | |||
e8c09e3b57 | |||
53bfa7c6d6 | |||
53f33c1cec | |||
10629600c5 | |||
4d549f69f8 | |||
de8ebbdfd0 | |||
0287b234ea | |||
bfc26bcd8c | |||
daac386f4d | |||
0db1b5d8f1 | |||
8e1a725462 | |||
424ab48672 | |||
62f4140634 | |||
64770571b2 | |||
c957dfc167 | |||
10ea3a9f4d | |||
ec4381dd40 | |||
2b64031ddc | |||
388578fec9 | |||
dd6070a49b | |||
3dbc4ab572 | |||
cfed0c0cf1 | |||
bb3c684b98 | |||
f8b995dbf9 | |||
639b732024 | |||
5da5ca5c23 | |||
0b1bf14cd8 | |||
d1cc7a0b26 | |||
431ddb9a45 | |||
7c2cd97e60 | |||
c2868de25a | |||
994264c0ba | |||
4bbf16e654 | |||
ae142a6827 | |||
e85ec23037 | |||
172bb76964 | |||
adb4f7c7cb | |||
5f76de1d71 | |||
71ada483bf | |||
abb44f7db0 | |||
43163523f6 | |||
ee486233e9 | |||
4c3b791ff3 | |||
964d72610f | |||
02bab8cf90 | |||
69ce1c2d41 | |||
6a0b1d58ba | |||
373d9660d0 | |||
1c6516199e | |||
3cf2005a93 | |||
2e4d17f3a9 | |||
40b28742a9 | |||
253a1125bf | |||
f41c41fd50 | |||
33fab26930 | |||
be665d8de1 | |||
c422c7210f | |||
f6a1de6b31 | |||
5a562d8a0a | |||
d6bbc4d76d | |||
4055150910 | |||
4d436800de | |||
0660903784 | |||
984d23f687 | |||
8af85d812d | |||
843881120a | |||
9e6c677135 | |||
9808d91c62 | |||
7a75f7805c | |||
cda205deb4 | |||
466f5c67d6 | |||
b9dfe66028 | |||
4d96cf5197 | |||
024c31da25 | |||
5064dc75ac | |||
bef27f2a28 | |||
628b0c1154 | |||
e4d5102b17 | |||
b25f925311 | |||
7d4c9e4b67 | |||
a5f39aeda6 | |||
a91ab15525 | |||
a95f860a96 | |||
6215636bc6 | |||
3cd8a2b907 | |||
ebcf79d7f3 | |||
a91a55a6d2 | |||
48487cb70e | |||
c68371ed14 | |||
9406104c0a | |||
c0194e0115 | |||
914900a561 | |||
4ea3e7e000 | |||
6eb9c2fab0 | |||
7b9414565e | |||
37de490e23 | |||
753080133b | |||
9a37e827e2 | |||
3df54be9e4 | |||
c0d5684078 | |||
2b289250d8 | |||
ddd02044ea | |||
c198a27a3c | |||
4f37487b1c | |||
0ddf0c4895 | |||
fd6ed1713d | |||
eb5412d76f | |||
7533338362 | |||
9896d438c0 | |||
684579b338 | |||
695f322dc1 | |||
f90c7a9df0 | |||
f2466cf4ee | |||
bed680cff8 | |||
a647298412 | |||
2abbe98e33 | |||
7613f13e54 | |||
4b8cdd4b57 | |||
17e289c39f | |||
2913340af7 | |||
f8c27d42ed | |||
17bb633031 | |||
9106271f2c | |||
48a3741d5a | |||
9d1f43f3ba | |||
6f98107d5e | |||
a8e2ee1343 | |||
e906a4f0d8 | |||
b5b33d12d6 | |||
22d3cabc10 | |||
a06043b703 | |||
4689ea2727 | |||
939529ce5d | |||
46304a4f83 | |||
f7eebd0227 | |||
8af2cc1efe | |||
e5a89e047c | |||
29d3b68554 | |||
93d27eefd5 | |||
ed70f73794 | |||
ef12e10e59 | |||
2954d1b5ca | |||
3077c9a1f8 | |||
9537b2ff84 | |||
961d663fbe | |||
57e15fc08b | |||
b70746a113 | |||
0709ed4c2b | |||
fa699f65d7 | |||
18bc4eda9f | |||
f542649b2b | |||
a574e462c9 | |||
65cafa0eec | |||
18aa173d39 | |||
bc8eb8508b | |||
7db269ba6a | |||
8e5567d964 | |||
541ce98432 | |||
e7e3f5d952 | |||
382d3ed1d2 | |||
a07de82f79 | |||
2e84f4e0cd | |||
a5b12db7d6 | |||
8b94d6a402 | |||
96cbcd6da4 | |||
2a6e6c02ed | |||
fa4e17082c | |||
ebb27727e4 | |||
046532b661 | |||
7b9891d7cd | |||
a2183ddb7a | |||
3122f3415a | |||
aaf29c8099 | |||
32e2f4daef | |||
a7c71d1a57 | |||
f2d47c96c4 | |||
184d270725 | |||
a610d12266 | |||
d0d875a3fe | |||
e8b8f6d09b | |||
9e9179e915 | |||
c1ae6124c8 | |||
b3b5c66414 | |||
82b97280f3 | |||
ecffbda664 | |||
adc39752f3 | |||
584b42343f | |||
8e7a0d4ff9 | |||
4db959260b | |||
76503e65c8 | |||
eac993dfce | |||
975917bafd | |||
185b3dd08e | |||
78659ec0b0 | |||
a9ec3db91a | |||
561ec6a5be | |||
c0317d40c9 | |||
a4bc0db474 | |||
430124a051 | |||
e08391b333 | |||
a77d0e22bf | |||
4f42eb4e77 | |||
f216724c2c | |||
5c9a8961da | |||
3479fddf68 | |||
5bebac42f9 | |||
cbcbe23fd1 | |||
fc6f48185c | |||
80f290e301 | |||
5e5be43acd | |||
0386c964b5 | |||
f5c605b608 | |||
14dba72aee | |||
5f0d5e9ccf | |||
5296c04f61 | |||
40a0666651 | |||
4da805243a | |||
14ae50b4c3 | |||
397d0ba9a3 | |||
859ebdd836 | |||
30673090ec | |||
6033446d2d | |||
174770e6f3 | |||
6ece7db37a | |||
3a2b195a58 | |||
489cef6ea2 | |||
985513351b | |||
8f3dd85600 | |||
6b67cd5620 | |||
0cd4c019cf | |||
7e46a6d99d | |||
85d051f8d5 | |||
c7542a1d09 | |||
2172368eae | |||
2c402d5c99 | |||
35a025fbca | |||
a86850e3f2 | |||
1bcd58cee8 | |||
dd0be7feb7 | |||
3d7303efc0 | |||
716af1059c | |||
a182714703 | |||
17b32b5fd4 | |||
29e1c53a31 | |||
87ce4e997b | |||
2bb9a65351 | |||
6b51ed29ef | |||
b696413a79 | |||
b6aeaceb8e | |||
5ae9b76a9b | |||
82055b2fb8 | |||
44039a4b16 | |||
a445826dad | |||
7f7033bbd7 | |||
27997a16c0 | |||
59c3700c8c | |||
4d93d2406f | |||
d39a2beae1 | |||
c038992fae | |||
8a470b9af9 | |||
399935c32b | |||
97ab52c618 | |||
f69e4e6f77 | |||
9f2ae5d6ff | |||
9eefe25e2f | |||
221782a8a1 | |||
24ca582bc5 | |||
b31a292955 | |||
1d7aa0a92c | |||
0aff4a6919 | |||
f50dede8f7 | |||
0e68c7edf9 | |||
54ef63b0f4 | |||
215ef3c5f4 | |||
5a8eb924ba | |||
c845a7b887 | |||
8b26447c4f | |||
ce196105ce | |||
b9a94c6d02 | |||
ebc71f7caa | |||
f65db20c6d | |||
8f084d7214 | |||
cb848b9410 | |||
d52ae7cbab | |||
9c954ebc62 | |||
f14693b9a4 | |||
f10d6c66c9 | |||
4495a46b99 | |||
ef75fb8ecd | |||
7b6ee5e0d9 | |||
e822394075 | |||
1b6e8411bd | |||
7151eae36d | |||
376ad9c3cd | |||
4aecf9253b | |||
60f58bf051 | |||
10a1e1974b | |||
647d7bdd88 | |||
69a612d402 | |||
221cbd0b47 | |||
ce9d0de840 | |||
18f0c2f1d4 | |||
5bd12c5aa1 | |||
0139b11227 | |||
e061e638cb | |||
dda781ecce | |||
a27c5dd740 | |||
012b535147 | |||
2200884e55 | |||
78e7fdd98d | |||
1e9eeafa9e | |||
9ef9bfe76b | |||
a5f9a86520 | |||
dd664f694c | |||
b66d82e308 | |||
518bca0841 | |||
d7ca263cc4 | |||
e8ae3c5f2e | |||
85a7fe8702 | |||
32c07ceca0 | |||
d3744457ab | |||
fc61284dbe | |||
12fd06916b | |||
9e83822679 | |||
54794f9b31 | |||
897bd18fbc | |||
1ac07757dd | |||
0110de2662 | |||
f166b6d8f6 | |||
09576e9683 | |||
40d785f0a0 | |||
46c03bd866 | |||
d5d8657d30 | |||
8853f13f82 | |||
3166cffd28 | |||
40705f3366 | |||
19bc11139d | |||
31ea254a07 | |||
caf8c0a437 | |||
d6c80871f5 | |||
edc51f76c4 | |||
c529be9f24 | |||
b65e11e3c3 | |||
3a09d01c63 | |||
604d9063c5 | |||
c4c340a7c4 | |||
32aa18be78 | |||
80fa84c177 | |||
e44ba0ffa9 | |||
19a28e599b | |||
14ad7562c6 | |||
0c61a35ea3 | |||
fac20bd8d1 | |||
63e458dd3a | |||
d545bbeee4 | |||
4bb283cbb2 | |||
a08b4b3519 | |||
0e86551a63 | |||
5c738417db | |||
3d9ba19ff8 | |||
8b7a4d7550 | |||
76b755e292 | |||
565a58e261 | |||
7014b67e51 | |||
6f50aad5c4 | |||
ef44f51d58 | |||
9204de96a1 | |||
7c62a8f9ca | |||
a55c6df07b | |||
d33204956f | |||
66d6b53fb1 | |||
e85fa5d4ff | |||
0c00c94f34 | |||
9b29ca95a2 | |||
479d926b4b | |||
b9195289a5 | |||
75b6b0e1ba | |||
2d4f507b61 | |||
3246a8553c | |||
db557221bc | |||
7ea6073534 | |||
1cba5d42d1 | |||
103a5b42ec | |||
fe1793844d | |||
68940f05d8 | |||
53212db3ed | |||
dee16a4355 | |||
6da1446afc | |||
76e3b57a12 | |||
524180c271 | |||
c69e552a83 | |||
2844f2779f | |||
2b44be984e | |||
989ebcbb62 | |||
23e0d65471 | |||
e92fb68f3c | |||
7724f7446a | |||
207f9b6017 | |||
a581773887 | |||
7f2330a968 | |||
aaaeb924ac | |||
98a68ad3e7 | |||
36d3062a42 | |||
83b19bf1a2 | |||
e6f1b04cd5 | |||
6aaca21c27 | |||
50c4ec6687 | |||
9a2d1fab84 | |||
8052de07e2 | |||
40aaa42f44 | |||
35f8bfce8b | |||
4b05ebc804 | |||
e30f494a39 | |||
1d3e22766a | |||
c0955975f4 | |||
9515f171b4 | |||
1efaac5cb0 | |||
d27181fcdd | |||
9e34670b25 | |||
5039faff8d | |||
44c6534f3c | |||
09970d52e8 | |||
95a9d67599 | |||
fde016bc38 | |||
11a208f55c | |||
1db3ac457c | |||
02491a6ce8 | |||
dca713c087 | |||
eb6281f5b4 | |||
a4a423a083 | |||
ba5b3af077 | |||
64e7af4e43 | |||
d2d84c4460 | |||
29f5582af5 | |||
63bdfca580 | |||
361109d80f | |||
b7a099d27e | |||
f83dfd6f5a | |||
dd36f3ac99 | |||
0d6fd134d4 | |||
bbb27b5517 | |||
7ca611cd12 | |||
c12b6fa028 | |||
a29dc961a2 | |||
0de5d79bf6 | |||
f57e77eeb4 | |||
2b5d52fbdc | |||
81332150aa | |||
c6b29f4c6d | |||
261dc04d8e | |||
15e397816f | |||
f96a81a818 | |||
4f38419e33 | |||
119004c7d4 | |||
d171006083 | |||
19e8570ac0 | |||
93abc35213 | |||
d7be38f84b | |||
2d38623974 | |||
5306330d85 | |||
c150354464 | |||
7217525da4 | |||
b6e8d19313 | |||
6c0cca093a | |||
f2360aab9d | |||
d7b4172678 | |||
641a4ea763 | |||
da4f7fbe1b | |||
9c87d223ee | |||
2be061a96e | |||
3851544674 | |||
6b7b4ee891 | |||
279e74603e | |||
8503901746 | |||
e01d697eed | |||
59d2edfebe | |||
a8f3b317f1 | |||
3788ebb714 | |||
32c760f5e7 | |||
f690a4e0af | |||
42036f4b79 | |||
74f637f98d | |||
e943859843 | |||
a94bdc6793 | |||
2dfd97d8f0 | |||
869e3e8edc | |||
7c4c676413 | |||
4004d15ba5 | |||
abbbc69e64 | |||
4fe0e75365 | |||
103064a3d0 | |||
29a9909232 | |||
7186f9c016 | |||
1e7e065423 | |||
ae1ac45981 | |||
280e8563f0 | |||
660800ca4e | |||
2c07820636 | |||
44b1ce6c72 | |||
5eb4691dec | |||
35acd44a07 | |||
8afc998ec4 | |||
26a85a82ff | |||
98685e6f85 | |||
61f2353467 | |||
ef9cb6a034 | |||
3846192bde | |||
a1d436e6a4 | |||
02d98ed823 | |||
e8d0265c1e | |||
00ecfc7f9a | |||
6ff3970ec7 | |||
1d5c44551d | |||
2aba485118 | |||
b11a2057c6 | |||
6ba42f1da4 | |||
708d0a2db2 | |||
ab27337612 | |||
72e4ff7591 | |||
5bec683692 | |||
cd617b15e8 | |||
a38433f36b | |||
28d3bfc416 | |||
f7e9659c4d | |||
16717fa12c | |||
74f4f5dfab | |||
3fb73ac62b | |||
a5dd4edab9 | |||
e83667ad76 | |||
805fc8698c | |||
23c017121e | |||
fcb03abc72 | |||
6f5d910ddd | |||
d72f8c949f | |||
29df3b0ee2 | |||
a4fc98cace | |||
131e2440f2 | |||
65974154e2 | |||
7035f225ad | |||
9c06af2dfc | |||
83f0304cfc | |||
a9502886b1 | |||
4bd6fca4ef | |||
bd3b0564e6 | |||
b1664425a9 | |||
ecd7f6ecdc | |||
6a381d9246 | |||
1f1cf1a169 | |||
48def92cad | |||
dc613b336d | |||
7ff628f8d5 | |||
3fb78aaacc | |||
5e53956c2b | |||
fad03c3c14 | |||
34eaafdf40 | |||
bf7d046269 | |||
5eb7426216 | |||
7b3bcc23af | |||
b356fb01d5 | |||
f2219081e3 | |||
70ad91ed8b | |||
75ac724842 | |||
4c45aa39e4 | |||
c5d1e1a3da | |||
b1fe1aa8fa | |||
9177ffaf58 | |||
f4fe1f65be | |||
029f1be204 | |||
91008bd979 | |||
f0395836b6 | |||
4b16d98955 | |||
ab86a58f27 | |||
4ec50811d4 | |||
c34abf2cbc | |||
c6b180380a | |||
7814ef55c5 | |||
f72772b038 | |||
0bf810022a | |||
bc04d18420 | |||
7a53b9090e | |||
db08fd2607 | |||
3998335188 | |||
f4cd2b75b4 | |||
5909c442b7 | |||
f5fa9dc6b8 | |||
87665fe324 | |||
16ac611a84 | |||
beaab27a49 | |||
87168acf39 | |||
65544ac742 | |||
57c4788bc7 | |||
7e49beb8cd | |||
036294d566 | |||
98515e1ecf | |||
c52ade2878 | |||
4adf95ed6f | |||
a1fc4deff3 | |||
e0969b2480 | |||
c596795e64 | |||
a6cb20cbe7 | |||
6fbfb5a159 | |||
16aa6ceff8 | |||
b5aa0473fc | |||
e76690be29 | |||
6c4d91297e | |||
f41242f18e | |||
e2fd628618 | |||
2c2135d331 | |||
7e3a60ad31 | |||
85d38ae564 | |||
4ad323a4d6 | |||
a4601eca68 | |||
e84b51d2b6 | |||
8f5c396a7c | |||
0c3bb6a731 | |||
cc0bd11a5e | |||
5d24a75ac9 | |||
799d1fd333 | |||
6bc9c78d76 | |||
bb4e230eae | |||
48d11d5fa0 | |||
1a5c7112e0 | |||
352f9672c0 | |||
76584804c8 | |||
2c78da00ae | |||
bb8a18e72d | |||
82e0b4a4fb | |||
574990e0fd | |||
aa9eb55e3c | |||
052ef654d2 | |||
58be2ff884 | |||
7912db3829 | |||
0ee09cdd7e | |||
b2937b16c3 | |||
a4b4f35533 | |||
b0866769b0 | |||
699283c4ee | |||
bb635c09fd | |||
c15e6750d5 | |||
87bf1791a9 | |||
8c4bd61b2f | |||
230e9766f6 | |||
2b4d5c7548 | |||
271d2b51a9 | |||
7b0bee73de | |||
c9ce485ce0 | |||
ba4ca5f9a5 | |||
4155ed439a | |||
2b9a4cc6a6 | |||
016b3f16a3 | |||
87b1a2af4d | |||
a2cd401a2e | |||
93af1f8456 | |||
5193acb0a3 | |||
532c1cb485 | |||
ef0b2cc74d | |||
a794143820 | |||
ba83d33dd0 | |||
17d87d4e10 | |||
9d9c9e43e5 | |||
c0386757b1 | |||
5c18f23788 | |||
7afd2603c9 | |||
81c2a94310 | |||
297222f892 | |||
64488b12ac | |||
8b6fbf8655 | |||
383ab8515d | |||
11a4454ab3 | |||
04587a33c5 | |||
b4b7af86c2 | |||
f440bd1793 | |||
3859bcc70c | |||
30efb6b8ea | |||
05a43ca869 | |||
b51d8dd438 | |||
ea2d453118 | |||
17bfedd224 | |||
540b01402f | |||
8852b793df | |||
d1df0a94d4 | |||
00cc905b98 | |||
337b6fe003 | |||
ef4a15bc0b | |||
0d4f8c7dd9 | |||
b74df20c2a | |||
4ecff42e7f | |||
55a14e4866 | |||
c7850fff3b | |||
456f2e70af | |||
4da5e9a156 | |||
812c231b0c | |||
3ed7463ad7 | |||
8154433130 | |||
07cd65b5ec | |||
cd6fc8bf06 | |||
fcdd784667 | |||
a981dd2aab | |||
b4e68025f8 | |||
680d38513b | |||
21328f2373 | |||
dd8cf19352 | |||
8bedf50073 | |||
32886cf9ac | |||
fcef39048a | |||
1315d23aa4 | |||
8ce288a852 | |||
f936590573 | |||
876cd603f1 | |||
aca339e864 | |||
f4cd3740b2 | |||
6d861f240b | |||
1f79c827a0 | |||
e0c36620c1 | |||
80394ce08b | |||
99c9bcab03 | |||
fa354888b1 | |||
d82adbe8c4 | |||
09c57ecf95 | |||
282abdb02d | |||
19bbf4bc8e | |||
53c6b78c51 | |||
91699259b2 | |||
41f372fe79 | |||
8e8c1ad47d | |||
b61784948a | |||
b4644d7bb0 | |||
7a0f8ac36c | |||
5e0f982961 | |||
f5b0c8a323 | |||
d2b0ac7de8 | |||
a2d26c6f2a | |||
62332b80da | |||
e3f3b106ac | |||
fd23663a29 | |||
71be1da0ad | |||
6a5cc8f95c | |||
2c406fb1a9 | |||
0b23adca80 | |||
671f64324b | |||
f1f8d70a41 | |||
8301028319 | |||
ba5309c1f8 | |||
fa5d8ca041 | |||
24ca8ba7ce | |||
af4925f374 | |||
77578266fd | |||
7bf7244ba3 | |||
1a98d51f98 | |||
82682bb93f | |||
d72479b628 | |||
dd0815095f | |||
48093823cb | |||
51cb5925c5 | |||
a36cacae79 | |||
1b5096d5a9 | |||
875eedbfb0 | |||
75cdda5f0a | |||
6363db89d0 | |||
573f57ac90 | |||
41cf066906 | |||
661c6e6f10 | |||
84dd2679a9 | |||
dc6406e5e8 | |||
deb77bd3df | |||
d5f96a887d | |||
68cd0cab8c | |||
9b3af1468d | |||
be0bc799f3 | |||
0d23cedab8 | |||
6bf5ec241d | |||
cdb5ea4200 | |||
bfedfa79ed | |||
911a8160ec | |||
8479cb4233 | |||
250887244e | |||
9b035e4038 | |||
ccc76f7498 | |||
f310a5960e | |||
b5c893916d | |||
132c61dfd4 | |||
5640cedc82 | |||
faac51fd2e | |||
214ae0ea4c | |||
dcdecfa9a8 | |||
4299ecf9be | |||
21e8ac1e02 | |||
01cf04c85f | |||
5c5cee9f39 | |||
2f336f15be | |||
e122b44269 | |||
9ce9561737 | |||
2545445ffb | |||
300f1b289a | |||
975845596d | |||
2cdbe9b2ef | |||
988afad2af | |||
1537aec1f9 | |||
7555a46e23 | |||
38d7acee4d | |||
10f48278c2 | |||
d4e6263453 | |||
86c46908d4 | |||
fa6cbb3ffe | |||
e20b92ba37 | |||
c7a9987067 | |||
1bdec3ed6a | |||
620cd5c148 | |||
76391f8999 | |||
02523debe5 | |||
70fd4300f4 | |||
3125376ec1 | |||
2cd5294394 | |||
3c548189b1 | |||
ae91f45b27 | |||
f74e0fd825 | |||
f1ea78ba09 | |||
87a2366eeb | |||
0f5da82cfd | |||
66f269c077 | |||
b613f90146 | |||
2fe6f350cb | |||
514ebf402a | |||
7c0667d215 | |||
f6bf8928f2 | |||
6debe9dfb9 | |||
0d52a27f41 | |||
697046c2b2 | |||
53a0b26348 | |||
8c00fced1c | |||
a50c1bb7bc | |||
f3c69e7f6b | |||
c9f5f3d802 | |||
a96976e88f | |||
ebfbc04000 | |||
e1af6e3c70 | |||
9e946c9715 | |||
0d97143965 | |||
df1d3fbd7b | |||
e946594bf8 | |||
abe4433202 | |||
c79bffaacb | |||
e58e5ec6a6 | |||
e688e02ee4 | |||
d7eaae6f22 | |||
1c3ee41902 | |||
f78bda9ff0 | |||
6454f76cf6 | |||
28ae22ecb9 | |||
c1135ee18f | |||
1114053daa | |||
95830ee584 | |||
661a57d9e2 | |||
660a091f41 | |||
7d31f7b540 | |||
ab4a23d0e0 | |||
a39f4e2301 | |||
8e2e9dcee6 | |||
9d5abfb3d9 | |||
fd7dd4d9fc | |||
01919fbaae | |||
80d4fc5e26 | |||
eda09e69ea | |||
0937062a64 | |||
6f073885b0 | |||
f03475cac8 | |||
848e53efd0 | |||
6bf8b1007c | |||
98ded949dd | |||
a5a1f4f52f | |||
8c1a041411 | |||
b1ba2d6f4e | |||
1714451a6d | |||
1f6fcb6cd3 | |||
60235b5aef | |||
d18c58816f | |||
222dde129d | |||
257e9646d0 | |||
a5e06ba629 | |||
9a6d298ca7 | |||
6ec621b72d | |||
07ebe9624f | |||
b4014e9a39 | |||
73e3f565e0 | |||
757d4c33df | |||
edd775eabc | |||
c613596658 | |||
f4655ea98a | |||
f6aa60c03c | |||
7fec1771fc | |||
c9b588b349 | |||
37f69eddc7 | |||
0fa72a8bc8 | |||
48b77459ef | |||
989bfd2e97 | |||
aeec66b657 | |||
e68490c5e4 | |||
95c5b1a7f6 | |||
8e201f713a | |||
ac34a1429b | |||
739e5a4f53 | |||
bf94932c7a | |||
6cb3b50a03 | |||
0e92332491 | |||
f5127f601d | |||
1b613c3ebf | |||
3f7e823b80 | |||
e9ead2bc09 | |||
b6b1aec22b | |||
1aff524b63 | |||
077809398c | |||
f9404d9e7c | |||
b766987b98 | |||
c62c5e2999 | |||
f2ae452f01 | |||
79903b1842 | |||
0051ddf0f3 | |||
3a8f74e392 | |||
8555016eec | |||
45e11915dc | |||
1a0e500eea | |||
35c1750fcc | |||
53f356427f | |||
d20b0f4b93 | |||
79d4b16f8a | |||
0fd9d086e4 | |||
4f9b16783b | |||
018a5168a5 | |||
cf86ed7b29 | |||
dbb150a9bd | |||
9e5377a2e3 | |||
0cdf5980e2 | |||
6ceb9034dc | |||
f9fb921f91 | |||
1b059e595f | |||
ff29cccb77 | |||
c7f9a95a3f | |||
06efc340b6 | |||
3fecab64b1 | |||
34e0d621fd | |||
cc2f175617 | |||
96baff3a85 | |||
090eac068a | |||
d09d8e0adf | |||
a57f3e7bbf | |||
197584d1af | |||
18c0ba5272 | |||
1bd4891c9a | |||
3a7bfc721e | |||
f74373f2dd | |||
2f35dbfd3b | |||
31df5139c5 | |||
7569a2e0d9 | |||
7dad3284e3 | |||
0cf09fc981 | |||
877b2285f9 | |||
0d4a0b6519 | |||
4feb9b1c72 | |||
cb6dea473f | |||
5ab809ddf9 | |||
fbff03b476 | |||
411524d341 | |||
0a0b4c1d8f | |||
5887ddfa3c | |||
d80ae6ba0d | |||
44cf981407 | |||
5fd39283ec | |||
1f2b39ad7d | |||
24e172d779 | |||
b68850215a | |||
9abf114fbb | |||
8d3365e4fc | |||
8cec8f5584 | |||
741a5dc5f7 | |||
de996c6d56 | |||
d750b1e10d | |||
d2c83ea81b | |||
bf031fc56b | |||
b1d45ee6d2 | |||
f26f036286 | |||
0ffdb48f62 | |||
cb6ad971c3 | |||
d70b1ff177 | |||
3aff79c251 | |||
d8665e639b | |||
c016e2c4ec | |||
452f121486 | |||
728db88280 | |||
9a807bd26a | |||
eccc41c5cf | |||
509352fc36 | |||
349935a434 | |||
6357d4a0d3 | |||
29786e856d | |||
bf6bedd714 | |||
f094bb54a7 | |||
4c12d742dc | |||
04a9f28c3d | |||
d9b9ed56b6 | |||
7c8a62d64d | |||
de651122a5 | |||
4a96ddfb54 | |||
8ced321bb6 | |||
2a0f497e94 | |||
392473ec79 | |||
345a3cd9aa | |||
bd37622050 | |||
48de6e87f0 | |||
3b551e0fcd | |||
be8fbac942 | |||
98a38ec98b | |||
4f055d4257 | |||
c59717571e | |||
f5b2ae616f | |||
1660b34e2d | |||
b40f6f3eae | |||
3327bd8eab | |||
ea9a381c8c | |||
b2437c4500 | |||
d6538eb2fd | |||
0926119977 | |||
39f2c9f46b | |||
60a8888b4f | |||
4537816c1d | |||
bf73fb7420 | |||
1ec092ba32 | |||
30d1f292c9 | |||
b70d20b510 | |||
066ec33342 | |||
5b80ab372d | |||
638ba4a2cf | |||
7ec8806dc5 | |||
7d6f4885b2 | |||
b1506a3271 | |||
b15a403c71 | |||
37c598db04 | |||
ad94e02981 | |||
00ffc03523 | |||
e53cf81689 | |||
089fcbf369 | |||
68ff2cc323 | |||
164d160b22 | |||
1353bf0277 | |||
6dc884f2ab | |||
05eabb19d6 | |||
f4916730b5 | |||
67012509a8 | |||
28a1caa0ed | |||
f015dbe1ba | |||
029a93963a | |||
20898f9f4f | |||
ef861958a9 | |||
16d7dde2ad | |||
1fd2cc6340 | |||
5ced8fbbd5 | |||
23152c37c8 | |||
4a2405929c | |||
eef4ca5dd3 | |||
321da5cc83 | |||
c2cf500da9 | |||
4c03208537 | |||
78b5bd5174 | |||
1195dabb84 | |||
2945f47977 | |||
a44b510087 | |||
572b54967c | |||
6f433887e0 | |||
537502d685 | |||
e5c3695dbd | |||
3cf318b498 | |||
54d4105264 | |||
dd59b1d371 | |||
124e49752f | |||
fc2dd5482e | |||
e4b81a6957 | |||
3efdd39a18 | |||
582ef2e7b4 | |||
214fef2ee4 | |||
531fcaa99a | |||
8a60239ae7 | |||
10705684c8 | |||
bdc6818716 | |||
5f95796b61 | |||
f2709ac3f9 | |||
cce9b9912f | |||
2ae26ce20b | |||
d47de60944 | |||
acfcf90528 | |||
c99d379cc8 | |||
0151ad432b | |||
1b0be8d656 | |||
47244ba2b8 | |||
0d66844ad6 | |||
b945bc3a9e | |||
4ae0ee86cb | |||
6c86ae710a | |||
f3ce8eeb83 | |||
876ceb3688 | |||
ee12c45473 | |||
1f4c380f58 | |||
b9f0720c95 | |||
71b8b355a6 | |||
f45684ff95 | |||
5b134caf2d | |||
fcacb2a4a2 | |||
933772ed69 | |||
a03a9236f2 | |||
6de4cbdd41 | |||
61365a94ed | |||
3a9d2473ca | |||
6200732e23 | |||
304a12f027 | |||
acaf1aa530 | |||
282167a37f | |||
eb85c8a742 | |||
2002db28ff | |||
6c1ae294dc | |||
b8298f1b2d | |||
3def652e18 | |||
909557d5f8 | |||
957f594d7c | |||
8f120aff33 | |||
4cfba58072 | |||
aa53d6cc6d | |||
be28a6ad8e | |||
39c0152b76 | |||
d7887ab4ab | |||
2236ea4359 | |||
0ddf2e7a5b | |||
2dc4e8801c | |||
9914998e76 | |||
00866186a7 | |||
9e85d7ff0b | |||
28e6aa723a | |||
bb47ad295a | |||
169d51beb8 | |||
8b0ebe17b3 | |||
a400429faa | |||
e720675f8b | |||
d316a18dc6 | |||
79141f4424 | |||
28fd5ab12b | |||
c61df39323 | |||
abcb2cf9a0 | |||
a9379e0ed2 | |||
6da19599de | |||
46f547499d | |||
2864108510 | |||
e95f460f39 | |||
75a23ab623 | |||
071ee64d91 | |||
efdbbe1aa6 | |||
c0c8d2349c | |||
4277600d5e | |||
f185ff3792 | |||
ec455e1cf1 | |||
825efa8721 | |||
3a9cf3f2ba | |||
152d99eef0 | |||
b635fe80cc | |||
b44b14368f | |||
d0672c252e | |||
3938563565 | |||
00ea3983e3 | |||
ae93ba1140 | |||
2e21997016 | |||
24c61cb63e | |||
d0ca7c792d | |||
6c88eb7477 | |||
0fa76219ac | |||
6af9b8fb92 | |||
0b5f480eca | |||
2905bf5548 | |||
e8d3246c6e | |||
7e3137e7ed | |||
c7f1b0a97f | |||
8ca208ff59 | |||
089bfdf95f | |||
d92fb25161 | |||
aaf8145c48 | |||
04d13429f0 | |||
230e32905c | |||
c4dd2d115b | |||
4ca95641ee | |||
8e8e89a119 | |||
f84c4b066a | |||
2f1a862b83 | |||
24c06091f2 | |||
364250e7a6 | |||
00ce9aab5b | |||
8e73f9b0aa | |||
f7960c024c | |||
9873356bd0 | |||
0f9230d018 | |||
19dfadb717 | |||
0bcb2320ba | |||
0cab43785b | |||
54289aec2d | |||
57c8f78c8f | |||
8c80b851c8 | |||
ceea0b418c | |||
f730c72318 | |||
63523f7964 | |||
a9242c4fc2 | |||
94aeeec1dc | |||
645e305733 | |||
f53d0fd2d0 | |||
96a828993f | |||
71498a407a | |||
8cba4e1f6b | |||
5a07aa484d | |||
3f6bf6dfd1 | |||
c3c0df9d56 | |||
cb34514d05 | |||
017bf0b794 | |||
f348deae92 | |||
10217bb3bc | |||
a181e8e7d8 | |||
6ae0084255 | |||
2271f200d7 | |||
4e13700ad2 | |||
d9ce8a4ab5 | |||
42262e4e8c | |||
bea85ffe9c | |||
5268ae61a0 | |||
98f86de8da | |||
f4c536ae36 | |||
182e2c7449 | |||
cd1277cfb7 | |||
9277afce61 | |||
410151b07f | |||
073d258deb | |||
9f5288dad3 | |||
e3d5d41140 | |||
0df719a461 | |||
4229b41057 | |||
d7f7826363 | |||
9b93bd625f | |||
1f8325d6c4 | |||
5650e3847b | |||
11eef85133 | |||
f957c7c1cd | |||
e575892774 | |||
f9bb53a761 | |||
c1d5fbd0ad | |||
ca591641c7 | |||
2ba799ddc7 | |||
22294dfad1 | |||
d1b7d36646 | |||
0629ebd9e9 | |||
45c2429d30 | |||
78146c1890 | |||
e1f51eaa55 | |||
e5905bb035 | |||
b9251fd707 | |||
c0ec1d63ff | |||
4bde40f7c2 | |||
4271d35dc4 | |||
506f478f08 | |||
8a3a556c0c | |||
ce2713f5b1 | |||
7edfcf948f | |||
83291f01b0 | |||
725148a44d | |||
696e520842 | |||
5fee9daa5b | |||
1a56cd5c0b | |||
60e9d2da4f | |||
ca9b3eed9e | |||
a48d288ff8 | |||
d9c39dcab0 | |||
ca2462cff7 | |||
ab6036272c | |||
1794a8e42a | |||
86a3f90954 | |||
2bfb6a02e2 | |||
bd3164f88a | |||
b3edf494a4 | |||
5f1b6372c7 | |||
5d824c4153 | |||
ca755a6b72 | |||
2deac0a412 | |||
9147092a15 | |||
8027b3e19b | |||
3a836c362d | |||
ee603a3b01 | |||
b0c1282fbe | |||
446e3573e3 | |||
0d6c9d36a1 | |||
205a45e9a8 | |||
7a7781e925 | |||
b2962db4cb | |||
bd2ce9cd56 | |||
6a8cca7975 | |||
6a1441f727 | |||
d1d0f4a1ad | |||
70177e544b | |||
4f9c935473 | |||
ea70d41ac2 | |||
e2e637d70a | |||
911e0b8820 | |||
6c018001d3 | |||
0aa0f11a2b | |||
f6ee1c2219 | |||
d6b474f2f8 | |||
ac3dc3cfc6 | |||
bc6c671e6b | |||
b0578061ce | |||
54058ba3a7 | |||
91c7b451d5 | |||
387fbb8106 | |||
5b32f55a3a | |||
b507d076be | |||
cc2e4b639b | |||
6227d0bb3b | |||
ddadb8e22c | |||
def73a6728 | |||
f98093a30d | |||
77aff0b7bb | |||
712d60e467 | |||
3ea8d651cc | |||
faf8fdde14 | |||
4191344cb4 | |||
a80637e9a1 | |||
b71cd7b4ee | |||
147a15a419 | |||
1eb7e9b804 | |||
17c4ed9d0f | |||
675f3909d7 | |||
3e4698564a | |||
8c37cdc38a | |||
ad642e31cd | |||
09975120fd | |||
39bfd1a11f | |||
4e8c2c3422 | |||
ef85336719 | |||
138ca5a246 | |||
db62ccf9eb | |||
b0eefc872e | |||
4f0110e75a | |||
f24fd56ed1 | |||
411c505dae | |||
1102b02406 | |||
00bf636afa | |||
82c77ce232 | |||
632847d34d | |||
e682b4453c | |||
84be7c52dc | |||
98cf3e8fcd | |||
cb9ee3411f | |||
d144a3bd91 | |||
66b87cef33 | |||
c65ac7fbad | |||
ed12d7e949 | |||
cf40105fc0 | |||
38a3a5a1f1 | |||
902a53a4f6 | |||
e38115536f | |||
6d35c5094a | |||
4a2fb86b1e | |||
8bbf481d60 | |||
c5bba8d9f2 | |||
e02684e609 | |||
ec56354306 | |||
5c13feebfd | |||
30b04424a3 | |||
f8cdda63d4 | |||
b6f48dbe19 | |||
609024f93d | |||
9c056b974a | |||
c0ec8425c2 | |||
b02cb3dc01 | |||
2e66ddfdce | |||
7fbe138b1f | |||
0c47dc0466 | |||
2bd9214435 | |||
433b7b02a4 | |||
a4f3f3f81d | |||
6233cd55f7 | |||
c3aea737ff | |||
eaa49bdc04 | |||
96b76dc3f1 | |||
afd2417ecd | |||
699ecac2c2 | |||
c7ff728723 | |||
d96f62fdc4 | |||
b9fead7f83 | |||
648adb1894 | |||
9810c6c0f9 | |||
8e83b3bec1 | |||
3246399bff | |||
0f4f315f8e | |||
0a530e6b47 | |||
dc5577dcb1 | |||
a6809e0e7d | |||
ddb935fac7 | |||
afd4a4ed4d | |||
60afe88bcc | |||
2d372f48db | |||
45c6360e5a | |||
6b39c9cf32 | |||
c5799491e7 | |||
b14537a004 | |||
630aaa6bfb | |||
7c8f4e3202 | |||
15eb1e0ce1 | |||
780081def0 | |||
5a724b34bd | |||
03d914a6c2 | |||
98f8b0f328 | |||
5a1d21ebb4 | |||
cbd5d28f71 | |||
9f54d76ef5 | |||
e5201f92fc | |||
3487055d10 | |||
1c07061246 | |||
d11b0c0c41 | |||
1293da1cf7 | |||
7c1f73ac7b | |||
0e201ea9d8 | |||
53be333439 | |||
19081dc9a3 | |||
9e4c0bd815 | |||
deca6a60dd | |||
63013f1aeb | |||
8bfaaf164a | |||
1f469cd7bb | |||
7041e61562 | |||
7316212c1e | |||
aaa16f286d | |||
3e569767e3 | |||
abf69dec5b | |||
701da0099b | |||
f9497bf28b | |||
d7e5535d00 | |||
8d3d75e454 | |||
39345b6fae | |||
06859f1335 | |||
717aa7c6e4 | |||
9cd90532c1 | |||
ff2a55f14f | |||
0abd5f5f03 | |||
cd6581e4f0 | |||
76110d71d3 | |||
a4fb0486c1 | |||
8a13f6b278 | |||
ee7c5ed620 | |||
2ff3d2d421 | |||
33016b8929 | |||
b2c03b8cd4 | |||
fd4c939394 | |||
6759aa68dc | |||
ab4be7bf80 | |||
2b6e107b1e | |||
6a55ba28b2 | |||
33524d9d9c | |||
b99a070f88 | |||
799a5a4915 | |||
4b2407a4db | |||
ed19464be0 | |||
c67f6a7e60 | |||
d4c4a89431 | |||
12c9bd257d | |||
e8768acacc | |||
303eae918d | |||
50f7ab2a06 | |||
22b89ea58a | |||
e8921365b7 | |||
009acd2a6c | |||
333bfa0ffb | |||
eb0e29b269 | |||
71daa11357 | |||
a81fd5f750 | |||
57f7996b6d | |||
27ba4ac982 | |||
6c76dfc568 | |||
78ba503fb9 | |||
1df9908579 | |||
c456b73302 | |||
632669f069 | |||
33963ca0d3 | |||
7b27009e20 | |||
d46a7c8468 | |||
71ec99856a | |||
e958447100 | |||
931d356a10 | |||
e4c1c88cbc | |||
1e5a818719 | |||
e57ed61448 | |||
aaa8a3a957 | |||
80161d5033 | |||
6a66af7a27 | |||
9745f55a65 | |||
c9810064cb | |||
1727fe24fb | |||
4eb6b02f08 | |||
96b800c8bc | |||
dd69e4e780 | |||
401b8eedd5 | |||
8badf9808a | |||
f8c7c3c09c | |||
b17d1a9aa3 | |||
60f6d9e733 | |||
416b0d29b9 | |||
2b836c81a2 | |||
ac3ce0d793 | |||
6c33058856 | |||
50fb629012 | |||
309ffe7e16 | |||
fea2a0f2ac | |||
e0dcd11a49 | |||
3514543e4b | |||
d9162a872d | |||
06056b4a6d | |||
3c11646dd3 | |||
a2f8f5595f | |||
a28b3e3359 | |||
495a4c1754 | |||
17f7bdbd60 | |||
531fa00992 | |||
c412374854 | |||
9724247ad8 | |||
568140fb03 | |||
7951c4feb2 | |||
0f1da49b86 | |||
a5c9fa3c8f | |||
6feef368f6 | |||
c34c223122 | |||
26a8c5961e | |||
41225289d7 | |||
3612ddb433 | |||
09fab58109 | |||
b3102b9de1 | |||
cfe6581fc8 | |||
bef5043a5a | |||
b5295ad277 | |||
769d960db1 | |||
21be0fb926 | |||
9bcc1e8dce | |||
a06f0340d2 | |||
66b72bfa58 | |||
00075647be | |||
ce789b75a4 | |||
7baf45fe88 | |||
f3e0cc89ed | |||
cfa6e8e008 | |||
02debebcff | |||
ed8d60d060 | |||
9ea0d64d8b | |||
dfcf759e33 | |||
21835af70c | |||
2790352d04 | |||
bb6a3632f6 | |||
2d859a8c3a | |||
70fffba054 | |||
e185d3a4ad | |||
6f3052b799 | |||
c18fa7b5bd | |||
693b350567 | |||
0b27c09b51 | |||
861d6f1523 | |||
dc10355d61 | |||
6cd3743b44 | |||
a24f4b51b3 | |||
84baa0bb08 | |||
e721c08c7f | |||
37a154e4e6 | |||
415de9a291 | |||
b3dda0ebc1 | |||
41737bb4d3 | |||
afe3e72601 | |||
5e3bbf79a6 | |||
d2b64cc008 | |||
9eb8274991 | |||
17b3f11e07 | |||
10734ac607 | |||
68a9fe817c | |||
64e5628897 | |||
849b327986 | |||
a827bc2e3a | |||
083fb99033 | |||
55ea8da6eb | |||
7ea0d1bd3a | |||
bdcbd9ed4b | |||
b48d6e1b13 | |||
68f9d705f8 | |||
229f035969 | |||
c9f7cdaafd | |||
7b55ba58b9 | |||
cd449021c1 | |||
4bb0259bc0 | |||
66239b9d09 | |||
a770aa231d | |||
cf4718c366 | |||
07aeafa75c | |||
7a67f8935d | |||
bc88816c10 | |||
0d0445063a | |||
ddfdf3cd26 | |||
d6d081e120 | |||
38c778e371 | |||
3249020466 | |||
d6e27a41ed | |||
1a4d4a0e13 | |||
3121409957 | |||
fd122b0739 | |||
9a364a82fb | |||
a530ed11e8 | |||
2d7435daae | |||
b460b26308 | |||
ea90435a6b | |||
ea0e832e5f | |||
7c4afb0da7 | |||
603df13b14 | |||
f9b7b6d2f1 | |||
dafbbf8b64 | |||
d59f02d902 | |||
20bf4ca382 | |||
aae6f7b40b | |||
5f50562be5 | |||
efcd6af17d | |||
56c345baec | |||
19ff32036e | |||
37cc514f0f | |||
067657c1e9 | |||
8714daf276 | |||
d5e3f2c64b | |||
bc99b774ba | |||
a3ec058f6b | |||
4605df83e1 | |||
c0ad9e104d | |||
a9020a028f | |||
e769f9cfe4 | |||
4a665ca50b | |||
e9fab63385 | |||
5454227057 | |||
0244a2433e | |||
86aba1e8f3 | |||
ae4a86e3b5 | |||
ce4da3f8e5 | |||
e79f57a6b8 | |||
c439e14d39 | |||
a8d84660e5 | |||
4525619a73 | |||
4742385e95 | |||
d87b035ebb | |||
b759d63389 | |||
fe759ee0cf | |||
105cfaf5e4 | |||
2ab194c999 | |||
7b5d326d77 | |||
8e70ca39cc | |||
9d090cb3db | |||
3d5b98631a | |||
e8df000e97 | |||
604f37b679 | |||
4d912b6b12 | |||
bf2db12fc9 | |||
dfb220ea6b | |||
04b5ea089c | |||
7561698675 | |||
8ef690c342 | |||
3facdebd07 | |||
1db8bf312e | |||
f7738ad8d6 | |||
fc8048ddaf | |||
b2aadffbbc | |||
8ed13a37f0 | |||
1877e6c3f8 | |||
1a9ab2727e | |||
bf0704d685 | |||
1fb670e06c | |||
f50928f5b7 | |||
fe448e8222 | |||
7c297e05f3 | |||
487d4157ac | |||
90df7de54d | |||
8ef46f38f4 | |||
7b70760c8d | |||
6ab8c0b371 | |||
80379697e2 | |||
a5c747f46d | |||
410ccacf38 | |||
e76cf8c775 | |||
9be4ab51ea | |||
4990b935b4 | |||
08231f0bfa | |||
a3e105487d | |||
2064508876 | |||
0c59342cd0 | |||
018477e2c4 | |||
1f0eadfab6 | |||
f2dc32e5c7 | |||
019e65abfb | |||
0ffa2f2e73 | |||
a5a35ff54a | |||
7b20cec986 | |||
eb00a37eb8 | |||
75748d6044 | |||
9a7f5601fa | |||
955e4e704e | |||
73da2792c9 | |||
1625d86178 | |||
c4c34fe60e | |||
29fae6de08 | |||
ccb70e1c64 | |||
940fbf796c | |||
ec01594e97 | |||
ac0553e802 | |||
fe76494759 | |||
9d4b7d7d41 | |||
fa8669ac00 | |||
3f32c0e674 | |||
b7c17ff207 | |||
c5daaa91cf | |||
360730ce59 | |||
fca1724ebf | |||
3c53713616 | |||
c09d0ed627 | |||
af52536419 | |||
1c251e59d7 | |||
ec8b74da56 | |||
6085f335e8 | |||
7315a68ac6 | |||
e6117a3a49 | |||
a8b432d55d | |||
37b9f06f1e | |||
9d1423df7e | |||
df354d1b34 | |||
4227126305 | |||
e20a29a153 | |||
76119b84dc | |||
defc30c7ab | |||
869e1cdcec | |||
ed4675e5a1 | |||
4b39bdf7e5 | |||
146256a4e0 | |||
1d88c2bb81 | |||
99aa9674b2 | |||
6b6fdffc12 | |||
a29ce57732 | |||
4b9eb6185f | |||
ca20f571b8 | |||
a5b8420234 | |||
49dccf4bfc | |||
3a6ba00286 | |||
c37ec8b255 | |||
fc305305e1 | |||
b012ab210b | |||
b3ffdf92c5 | |||
7b0e9eddd1 | |||
a746b5b1ea | |||
b6f6b1178f | |||
37c5a26421 | |||
142ac41cac | |||
d4728c40d9 | |||
a68b1a1894 | |||
014841dfef | |||
63d18064fe | |||
fd5cd100a3 | |||
aa6db0d191 | |||
b14df413eb | |||
22c71b69ce | |||
d95e059480 | |||
ad9415af1d | |||
4f2773eaef | |||
f4f20daee3 | |||
36a1550e00 | |||
5ad2097be8 | |||
809452b921 | |||
f535f31d78 | |||
e3a401d20c | |||
423ac01dcf | |||
c7e4931f32 | |||
b73e02005b | |||
9a1959269f | |||
f71dae8f63 | |||
941c99ad7f | |||
3ef2002bd8 | |||
479ae51d1f | |||
eccbc785b3 | |||
29f57e315e | |||
c866c11bf8 | |||
15e84950ec | |||
7060d9038b | |||
14ce8a9c31 | |||
f856a6597b | |||
887faffa25 | |||
0bd4261f23 | |||
f96efd1c98 | |||
22ddbf4b02 | |||
268c3fe816 | |||
dc6192c8e5 | |||
7102ea80a9 | |||
6b98b534c8 | |||
c5d9035bab | |||
d5a8be76f2 | |||
9c1ced102e | |||
54286b8c27 | |||
84406e4d6d | |||
c29d2a4f16 | |||
84f3dfbca4 | |||
3bee0f684d | |||
881807dc36 | |||
20a9dbef8e | |||
25166d4f41 | |||
6215799055 | |||
ff9550542c | |||
69265b7b5d | |||
b446095c4d | |||
1efad3772e | |||
e8bb8f4912 | |||
4486dabf01 | |||
01577b0bed | |||
7c57293bee | |||
3063547975 | |||
72ecc45363 | |||
7d174969c2 | |||
79e2ca0c0e | |||
586234bb01 | |||
5fded9fcc8 | |||
866d500324 | |||
04cf4ef0c7 | |||
aa57bdbf90 | |||
78adcfe0ee | |||
48214e2a05 | |||
95989a12dd | |||
c5f1d08a43 | |||
3403027698 | |||
c875851bb4 | |||
d2f015f57e | |||
05a9090ded | |||
bfc40da6aa | |||
43ce6ec84a | |||
842d615928 | |||
a352b73962 | |||
fa82d2d6f1 | |||
83ba587c18 | |||
dcafddefb8 | |||
c0757d1d44 | |||
a06824aef6 | |||
ba602dbaec | |||
b1df9a30f4 | |||
3e5c1bcb9f | |||
b50283ed67 | |||
a23a0bc3a4 | |||
7ac58bec8a | |||
ff8e4dddb2 | |||
f01d1c4c8d | |||
b5629d98d8 | |||
ac76e5d8dd | |||
0bc26fc4e8 | |||
c532646f5b | |||
9fe522f3e2 | |||
4a1640bdd5 | |||
8cd72441f1 | |||
ea09430039 | |||
cd83a43462 | |||
1d4dde2adc | |||
58198075f2 | |||
2e43e15e12 | |||
5874247494 | |||
d207c4894a | |||
5fdf24e843 | |||
03d2e5cb1d | |||
2b974d4012 | |||
3a6e443e19 | |||
cb20b3b40a | |||
f7c867ebc2 | |||
76979e12c9 | |||
772b24ccc3 | |||
91a161aa13 | |||
efa10e33a9 | |||
daf8251998 | |||
a6ae759b46 | |||
827e89cfc4 | |||
40833ba54b | |||
34bdebcdd2 | |||
034de06ab1 | |||
2dd44d712d | |||
f16fca41d6 | |||
b8d87490f5 | |||
d127d05dc3 | |||
7b944c46d3 | |||
c4c3c1231b | |||
41de05e1ae | |||
dad5a258b8 | |||
ce68b4d839 | |||
dc335194ab | |||
f380263393 | |||
5a4c402663 | |||
262ba67525 | |||
dc9f0af080 | |||
8f8f9a6e61 | |||
25a2fef303 | |||
dbd9ecfd4c | |||
f01247f0a4 | |||
846c431eb7 | |||
edb6c2d814 | |||
3cb497c6ac | |||
bd65f58784 | |||
1930e8a072 | |||
7a11242388 | |||
65de0d6d0e | |||
ef1b9e6d71 | |||
65d3ddabf3 | |||
0b8aad2ca0 | |||
0071048cf9 | |||
9f7a9c607e | |||
22880eae16 | |||
3d48cde3b1 | |||
61495a138d | |||
319ed5168a | |||
f79cd5963e | |||
350802b207 | |||
10ba91b1d3 | |||
f75acbd99b | |||
395fb186a4 | |||
f0989b786b | |||
c64b13e593 | |||
7bae49b419 | |||
929fe029c2 | |||
ba6aa93aa3 | |||
f0f81f482e | |||
3144bf4d73 | |||
bb050a8ae0 | |||
75357ecb32 | |||
c1392ce618 | |||
15c065f9a0 | |||
fafabc0b92 | |||
ad4a9bf03f | |||
43181ea568 | |||
9dac04ff50 | |||
7f3e3a8c45 | |||
6ccf743627 | |||
230a941c3f | |||
7c20bf8845 | |||
82820b0b2c | |||
1778bd3470 | |||
33f71e8ce3 | |||
cbfc1f238e | |||
c7fe3a92de | |||
9ca356559b | |||
7c1b9ff5ec | |||
599e2e22bc | |||
2df2168c0a | |||
8043db570f | |||
de036d29e3 | |||
94223a09e5 | |||
65d839da03 | |||
32ae84da28 | |||
93a7836f7a | |||
9defc00b14 | |||
1145bdb478 | |||
f4d652568d | |||
3cc9ba24c6 | |||
3f2b51b837 | |||
d8704a3069 | |||
64e6aaa4f1 | |||
e1aaa7ec48 | |||
0ea216b993 | |||
ebffde7143 | |||
9ae14db343 | |||
95d9aa22ef | |||
df627e65df | |||
72d043f669 | |||
be121bba85 | |||
58436fd81a | |||
3336de0970 | |||
d0b6622b9a | |||
13b96ac91d | |||
623fd3fb5e | |||
bcdd4b5729 | |||
05c25ccca7 | |||
cfb2d176f8 | |||
d0e81eb593 | |||
09d894c283 | |||
81c3104f76 | |||
68da4658ff | |||
b9eb662c4a | |||
04ae1251c7 | |||
1832e0f293 | |||
9cecb0b5d2 | |||
bca0b44ff2 | |||
e5e4e63e71 | |||
96b597cfd0 | |||
669b4410f2 | |||
1eccf64b15 | |||
2d804198d5 | |||
fd4e1d69ee | |||
02ee8c7bc5 | |||
67ad8a2632 | |||
25aae64274 | |||
eb39633823 | |||
71d0eeb966 | |||
295a143ae0 | |||
ad6475ffac | |||
3c1a1620e3 | |||
a4638d5a81 | |||
ae16378ee7 | |||
73b9cd75b9 | |||
71e64e93e6 | |||
d8ae8993d8 | |||
19afb791b4 | |||
5e68e35112 | |||
745c9c5ca7 | |||
a834c745d7 | |||
4131715df5 | |||
692ddfcbb5 | |||
e0f3fd72dd | |||
00a8b07896 | |||
80c7aff5cc | |||
6788d86709 | |||
ababc5b4a4 | |||
af8d58cb51 | |||
9e82cebe5b | |||
90b304612e | |||
caefc5d4c4 | |||
1923c2f99c | |||
a17fd43fd5 | |||
0cc5804169 | |||
55b144bdf5 | |||
980bb52d36 | |||
6b511a33f6 | |||
3c7ce823a3 | |||
fdca0013d5 | |||
1e6ed52cba | |||
04a1923af7 | |||
911599d9a3 | |||
c1094cf46f | |||
2e3cc45c74 | |||
6fcf286344 | |||
fcc8c5690f | |||
8accc98d28 | |||
aa8d0809d3 | |||
80a5934af6 | |||
7cbc36fdac | |||
63e5d2787b | |||
83fd66d1d0 | |||
627cecdfe2 | |||
b41da03f00 | |||
65c2deacbb | |||
841a1d32e1 | |||
362c41de89 | |||
cf848c6ea0 | |||
47574fef11 | |||
b0afc4c638 | |||
1df3aefb81 | |||
8cec4b3ff7 | |||
9e5d1357fe | |||
3bb3d6d3e6 | |||
3d39100c85 | |||
3842dd6a6d | |||
36df9056af | |||
2c6a6f18c2 | |||
423b39e216 | |||
a529f53031 | |||
99d8582882 | |||
d2742cf473 | |||
f8b67712bc | |||
3477610f6d | |||
09af7ea4f5 | |||
dba2a406fd | |||
fb194d5146 | |||
0a4811c4ad | |||
13685131bc | |||
1a326d5690 | |||
28bdeeef3e | |||
6fa4235543 | |||
6d057cc05d | |||
2f27a8051b | |||
77eee42963 | |||
553f80ff46 | |||
5cafd44654 | |||
cb0a8b566f | |||
cf6d63ca63 | |||
1d20088291 | |||
7e895b9179 | |||
39d0311e4e | |||
644e7a28d8 | |||
f8b9e61469 | |||
2ea030c2c5 | |||
49fb8c3cb0 | |||
0c7581da89 | |||
06ec95f2ef | |||
91b7152852 | |||
fc8f4f8029 | |||
2afc40608d | |||
ac58d01a8e | |||
d68a98f0cd | |||
08de52b9f0 | |||
cffd86260a | |||
497619f25d | |||
c0dac184cd | |||
e6a00be014 | |||
4f46bfb779 | |||
a5ea55a636 | |||
0d6fdec4bd | |||
54ca24b47d | |||
8c3f1717a8 | |||
8d15dd8b70 | |||
2424184d42 | |||
eeb560ac88 | |||
1b0580a9ec | |||
673ac2945c | |||
81df5dcfc0 | |||
6050cd0c1b | |||
0cb02d906e | |||
0957d8cb3f | |||
1b82e11e69 | |||
cdabda1fc0 | |||
188f20fb16 | |||
3eec314ba9 | |||
e6c51b3e06 | |||
f358188ec1 | |||
5db3a6b198 | |||
94b8aaeba8 | |||
fe8301c462 | |||
e5861e1c79 | |||
2bf0d1a56f | |||
2ca77da4ca | |||
a9afe629c7 | |||
1e64f37257 | |||
99e3a04ea2 | |||
570f735a2a | |||
872a3656fe | |||
9ec8aa5eb7 | |||
5f2ae784da | |||
0a95f8af9f | |||
531aa5f8db | |||
bfee33edb9 | |||
1941d7c743 | |||
21b5940abd | |||
2852beaded | |||
206a21704d | |||
46e6363686 | |||
457e07ccb1 | |||
05a14f8a8b | |||
19f13b1ad4 | |||
d29f781685 | |||
0770978dfb | |||
863dbeeb7c | |||
425e0ee416 | |||
81329c85b3 | |||
fcd1f61476 | |||
e9bedc63bb | |||
7115e7c427 | |||
aadc332be2 | |||
c916b360bf | |||
fed8c1d160 | |||
fb9a4a668c | |||
f7591f1302 | |||
44de68ce40 | |||
2c00cb8f0f | |||
1ff3699d99 | |||
0e4705aec3 | |||
6e4ef91ceb | |||
ceada7785e | |||
d91ea2c499 | |||
faf0b255d0 | |||
90670252de | |||
94f042beba | |||
9d109929be | |||
e0d2ca261b | |||
4b7264f60f | |||
6f9dd1bf28 | |||
c3fadadaa9 | |||
b65fe62be1 | |||
f2a734bd06 | |||
00e24b3000 | |||
1950e2d9ba | |||
7660d0d74a | |||
264ef72800 | |||
f889317f93 | |||
df3cea41de | |||
36284713b2 | |||
ce83231ce9 | |||
2caa419990 | |||
71fa1f2a45 | |||
50732e1564 | |||
3de06dd794 | |||
9ce0c23c77 | |||
08f55b35a5 | |||
2b9811dad4 | |||
df74da02c6 | |||
8d90142a0f | |||
851cf16134 | |||
353362f5a4 | |||
0e6f799aec | |||
6709db9677 | |||
43081a01d8 | |||
e3032a0d17 | |||
01bb3c5820 | |||
43467c95ab | |||
69ecb96569 | |||
e991d825f5 | |||
ed032e08c1 | |||
ae8b7b1fdb | |||
62a13e795a | |||
22d3226491 | |||
5ebc0da640 | |||
eed59b713a | |||
b2a6bf2a80 | |||
0709f8411d | |||
d42f32cc61 | |||
2ea4f690e4 | |||
d4add5428b | |||
8f15cdbc7c | |||
baf103c98f | |||
3f73dfa151 | |||
7c5c1fae62 | |||
89eac702b5 | |||
5a2c3ff8b5 | |||
ed0cf7e2cb | |||
4ceb655c11 | |||
5a6f0d0af9 | |||
979582a2ed | |||
63b744bb6a | |||
fe4d811086 | |||
4142db0828 | |||
7a6237bc50 | |||
ebaceb37e0 | |||
62c0deac42 | |||
57034aa13d | |||
cec1fa04c2 | |||
0d1e065a1c | |||
8d11627e6c | |||
4a92fa9471 | |||
744b0205e2 | |||
40da1be1e1 | |||
c10d86cbc0 | |||
b91a25bfb2 | |||
e11ac7f24b | |||
4aa189da67 | |||
dde7e2f253 | |||
8edd9cd6c0 | |||
76a6eacb4e | |||
9ef8d2b823 | |||
07fb4b5677 | |||
728fe69625 | |||
7219639ff3 | |||
f2621dbb37 | |||
3c7fdc6a9e | |||
5cdbdc9ee0 | |||
16a78f97f5 | |||
ee74835619 | |||
5a257d02a6 | |||
e4fb93c28a | |||
b7738ef9e4 | |||
463a7894ae | |||
fc88a79b32 | |||
a98d66078d | |||
1e5012b2cc | |||
3d522716c4 | |||
52d3795336 | |||
4dfcbc6afa | |||
71b9d5539b | |||
7a22019b3d | |||
f6805de8eb | |||
72c36956de | |||
895a8d6f3b | |||
814ee260f5 | |||
bfd48d156d | |||
5c4d95541e | |||
8930f60a4b | |||
36902e2f0e | |||
ec6e7303dd | |||
1b33142595 | |||
1b6d8a78b0 | |||
6656328538 | |||
9efb39c8a2 | |||
f640941e1d | |||
c0b383590e | |||
35e45dc894 | |||
b35ef184a7 | |||
b1e099b657 | |||
a9c881e243 | |||
038303eed1 | |||
a227c528ca | |||
0eef958735 | |||
51a592cdfc | |||
fdc6e159b4 | |||
7d9aa67d8c | |||
495a9dd445 | |||
778d5739e2 | |||
66ce3b2f2f | |||
76cedb8bf3 | |||
ad499628cb | |||
24f5428187 | |||
a228d65412 | |||
dc8e461303 | |||
eeadb37b19 | |||
41e68f7a7a | |||
dabcb3e17b | |||
bcf17bc91c | |||
d45d3a3ef9 | |||
f99a668b04 | |||
70e426ba1b | |||
ec414b432e | |||
9af18c2fd0 | |||
2bb518c694 | |||
b87bf39eb4 | |||
227f7e44d6 | |||
22f76df8f2 | |||
e18a52e24a | |||
f38deb0f07 | |||
d940b5541f | |||
8e75a40735 | |||
59cc724e3b | |||
8ced999e47 | |||
4c8d17ffd4 | |||
3e6a1f0bc4 | |||
40d64b6b58 | |||
c84739dc55 | |||
bb94434d85 | |||
ebac5dba38 | |||
29513296fb | |||
98e5af1480 | |||
66335c36e6 | |||
6e16338302 | |||
9a3739142f | |||
e98d508df2 | |||
5639891e90 | |||
9d81bd39ca | |||
9d3dae42e9 | |||
1699c88655 | |||
074400da60 | |||
7d954dffd0 | |||
cac9199d7c | |||
a789a3f532 | |||
5dbc7d9a63 | |||
fd8dbd5e40 | |||
7033f39c61 | |||
3deda898d0 | |||
f8c70011b1 | |||
adfc55e2c3 | |||
a1f36e5f14 | |||
3b48d13af8 | |||
f7c551e16b | |||
e4f67dfe66 | |||
d83307adab | |||
873750609f | |||
664ea50b46 | |||
99886bd159 | |||
3d5a919ac5 | |||
ef6728207b | |||
2da82db3bc | |||
7421534873 | |||
7496630a94 | |||
6e949f9e98 | |||
6ad1c47df8 | |||
76144f156c | |||
fdc2b0bf77 | |||
54532dfdf1 | |||
2a02f4beb2 | |||
bf97d3b73e | |||
46aec4a58f | |||
c522e03fe9 | |||
b2811e50c5 | |||
e2c98fbe11 | |||
02975e9166 | |||
3414316fc8 | |||
67a41d8bff | |||
e50c5293fc | |||
056d35c97c | |||
465abab213 | |||
c1fb9c265c | |||
d4ecffe475 | |||
736cfa4e09 | |||
cbd626413c | |||
317cc922ac | |||
f9b103825a | |||
32c61f434c | |||
22a43cff4d | |||
9098225ff0 | |||
9f9024b7a1 | |||
03c8528fcb | |||
5430d2bc66 | |||
a95e81978b | |||
5552661fd7 | |||
030350f53e | |||
583061d043 | |||
0a564c3158 | |||
b9854e582f | |||
cf8770f3cc | |||
d8f2318811 | |||
1fd673504c | |||
8f1198ffcd | |||
fe9b3ea251 | |||
50df897fdc | |||
33e49c2894 | |||
ea1b5c100f | |||
18a9afc738 | |||
589dd479e2 | |||
661a98aeda | |||
988243437a | |||
3b9553bb17 | |||
522e4ea898 | |||
b6819fe9bb | |||
6c3b57a968 | |||
37f8263430 | |||
a84a9ba705 | |||
d73734dcb7 | |||
e0fbe8611e | |||
94e305f48e | |||
1964be0b17 | |||
41b2499f17 | |||
da85cee07c | |||
2fc5f002e0 | |||
19a2b783cf | |||
9e5016c845 | |||
070fca1591 | |||
d336bff200 | |||
f99082fd3c | |||
75074d009f | |||
197676a6dd | |||
1fb6731285 | |||
1df8be5573 | |||
6324ad45e7 | |||
7439b46c5a | |||
9a965c9145 | |||
351ef2a6de | |||
0b6eaca3c2 | |||
058aafcc0c | |||
7980f1d2ea | |||
6bd20e8b2f | |||
366a6bf192 | |||
5b08a880f7 | |||
7db035842d | |||
9dabeea807 | |||
73dcd72afb | |||
7bdf3fe41c | |||
38343a2388 | |||
45bf911df8 | |||
ab2bf83398 | |||
2b9cc8503d | |||
a58fd210e9 | |||
6940992932 | |||
c1c87462fd | |||
73616ab237 | |||
a0cdefb5fb | |||
f8ad4d1e99 | |||
5a582a8afd | |||
e172e97e13 | |||
0d6913f037 | |||
896cf35afb | |||
1f7d3b9a57 | |||
8a08ff1571 | |||
50cf2ac6d8 | |||
80967ce82c | |||
1a85de302d | |||
808898d015 | |||
f59f18c13e | |||
a570fdf0f0 | |||
e7d5c12ea4 | |||
1e5e62ef56 | |||
bac71ef419 | |||
da1d19b40f | |||
9a81f0d9a8 | |||
c61ea1d5bd | |||
47665c9937 | |||
3b7a571cc5 | |||
f983e99fb2 | |||
4f009e7a03 | |||
29bff0f02e | |||
3a31a2795e | |||
ce3a746644 | |||
bc02e31185 | |||
6072ca87e1 | |||
9460218f36 | |||
850b86749c | |||
a24120011e | |||
d49d1e7d73 | |||
2e5752eb06 | |||
da8ee29e72 | |||
693045165c | |||
e62eeed7d4 | |||
06e5bf1661 | |||
60fecc1284 | |||
b6510a320b | |||
fa53150692 | |||
b5c2ef2877 | |||
ddd8cd0573 | |||
cfb41452ce | |||
f1fb62d1e5 | |||
d12db4e114 | |||
68bdbf0520 | |||
857fcfe048 | |||
60fb27c4ab | |||
4c0104c846 | |||
72f2428cd8 | |||
d577b8df75 | |||
cd0451305a | |||
e8495b460f | |||
2c9f0139a3 | |||
fc881390d0 | |||
1ec01d6758 | |||
4bb5f638bc | |||
0897ebac9e | |||
657cf733a2 | |||
d6aca79410 | |||
e4c899e4ba | |||
5e6e96d844 | |||
9c2f6d72d6 | |||
638375b7ca | |||
c5b67b95b7 | |||
78bc21c63a | |||
48a03fcc80 | |||
6fff74e576 | |||
978ffa9d32 | |||
6a9a48b0ac | |||
da2880d7c4 | |||
fca185e191 | |||
e082fc24b2 | |||
133fe5e561 | |||
2afbcafab7 | |||
605f450251 | |||
9260b5e0b4 | |||
9a128a8068 | |||
cd51775390 | |||
fe4d3a1619 | |||
b73d6781da | |||
0c6fa1df52 | |||
ce51dfb499 | |||
8ebdb437dc | |||
b0caf02d4f | |||
091a8a6fd5 | |||
61bc61fc59 | |||
df292c2ce0 | |||
51e716b6f2 | |||
94893accdb | |||
6c6d43086f | |||
8c3f98fdbb | |||
89a39bb22a | |||
12f509c218 | |||
76104f395f | |||
18ccfc6d73 | |||
3ea9f0974a | |||
a100472b5d | |||
a6f7fe394a | |||
e31afb7118 | |||
d505468fb7 | |||
f854eb7dec | |||
b0f3c20a4c | |||
26a8c095d0 | |||
bccf8da35f | |||
acb2caced0 | |||
96f4969a2b | |||
aebec4b156 | |||
9277142d54 | |||
b78351cc7e | |||
885f1af509 | |||
b05baa59e0 | |||
ad6569c744 | |||
feebe03523 | |||
e8a57f0ee6 | |||
a6ba789599 | |||
3bafc002ae | |||
afaea110c7 | |||
dffcb9cda3 | |||
ee60c7679a | |||
e0e92cfef6 | |||
65e72e958e | |||
76ed13bffe | |||
7374dfd1fa | |||
c5ab3e8fd2 | |||
142553abc6 | |||
6003145422 | |||
3cf1b62722 | |||
5a0deb8d69 | |||
4694c93315 | |||
94c0b7a362 | |||
0136274f33 | |||
8934b736c8 | |||
11325bad4a | |||
d0c3e252a3 | |||
e1e4887feb | |||
6f9881f85f | |||
6beeb76ac0 | |||
1f904bffbc | |||
9b2b9b3bef | |||
91a8a4fb28 | |||
582395b8f5 | |||
76580b98f0 | |||
5609764886 | |||
29e3144269 | |||
d68ad3e617 | |||
d6cfe2ed7e | |||
eb1aae4043 | |||
935ce63b73 | |||
31fdff7121 | |||
c7d1890aaa | |||
c7346bfdba | |||
d2b2d813d5 | |||
72fc0a747d | |||
cea3b8f885 | |||
5e7c71e51c | |||
4e17212d44 | |||
c3aa24c3f9 | |||
1de4031d9c | |||
1c39ad38d3 | |||
0b9094ec63 | |||
ac157170c8 | |||
f4a9f5dae8 | |||
2a6108af97 | |||
37b716b298 | |||
f6c91c5a5a | |||
b621a69cda | |||
3fba6eff79 | |||
b9c6df6da7 | |||
1a7f92c423 | |||
a0840242d7 | |||
090801532e | |||
b541c48688 | |||
b432eb1cae | |||
cc5fb914bc | |||
d72ae7b71e | |||
aaa97f11d7 | |||
4b5b1f6d16 | |||
c2f19515d6 | |||
6e7c46af1b | |||
917c09cfc8 | |||
f5471107d9 | |||
e6ab55daa0 | |||
7db05c408c | |||
483f8250bf | |||
8e530a03b6 | |||
b47c43af45 | |||
4fc41517d1 | |||
c80071dd59 | |||
98472da03f | |||
7ac8b02ec5 | |||
0199e26167 | |||
17291e66a0 | |||
7de7b7a16a | |||
bb5ddee710 | |||
04ca3bcf10 | |||
c1dacdd890 | |||
9de9c8ad03 | |||
4613864fc8 | |||
ac5f5ed0a6 | |||
8122970f63 | |||
8473d68ea8 | |||
4caf6540d1 | |||
a75c734471 | |||
e775313188 | |||
996435b79a | |||
45880532bf | |||
e08feb7e54 | |||
8a3cebde8b | |||
d80c32310a | |||
3ac249b2ab | |||
e94e7eef4c | |||
654055b22f | |||
0efbb37381 | |||
6b0c1a71fa | |||
4c9aff5695 | |||
224d78765f | |||
7adcbb320f | |||
e7f43386a6 | |||
411de252d7 | |||
b61dafaeac | |||
929334b0bf | |||
fb7816fed4 | |||
5d3dcfc6ad | |||
0bd9deb9f5 | |||
13d23f315b | |||
48555f95c6 | |||
d026b675be | |||
7eb2c41fb2 | |||
3f2ebbd7ab | |||
38b4d15227 | |||
176b3f12f4 | |||
8a05199fb9 | |||
51a0bd2e75 | |||
1b0b36d143 | |||
e268a0579a | |||
1f1e77b641 | |||
880b4aabdb | |||
5fee444fea | |||
1e6c9be86c | |||
a9790018df | |||
1dc95c41eb | |||
a0a3648e7a | |||
7df9040c05 | |||
5638c1d507 | |||
755c8091af | |||
59f64dd361 | |||
27431e0e1e | |||
b7d0ab7de3 | |||
460be795cf | |||
c4f7727408 | |||
d1de9ff313 | |||
707c6828b5 | |||
3f64e87ed1 | |||
62e45cef2d | |||
c34eee4e8e | |||
9b91beed69 | |||
eea2b0f288 | |||
13eb57a59f | |||
0b3ae3d70c | |||
4b67b0af3e | |||
bba5e2632e | |||
c5ce4e62c6 | |||
509aa61619 | |||
cdd737e28b | |||
5da55d6246 | |||
50a91ba28c | |||
077a5fb04b | |||
bc0ee01d09 | |||
326b464d20 | |||
8a7498e0ef | |||
07ada7f3d9 | |||
880e8a5cfc | |||
a0585c9a9a | |||
a833b98fd0 | |||
4b70a4e905 | |||
f2a1c66031 | |||
cfb8c17511 | |||
99d0e27587 | |||
b08f3acf09 | |||
3ab25ab078 | |||
0604527199 | |||
8f8572fd3e | |||
e8f7241366 | |||
a20b2f72f2 | |||
f48a00fb0c | |||
24fa0b7583 | |||
12c317603a | |||
7901cd8cfb | |||
69198ba37b | |||
8684fb5804 | |||
999bd5ba86 | |||
cdfe8f4d69 | |||
2c9b6c0c1f | |||
17e702bf8b | |||
b04bc5d06c | |||
1c93afe956 | |||
4774a1abff | |||
8d0a3cef98 | |||
8fdd702245 | |||
1b6c4e7ae0 | |||
d766ad01db | |||
f57916c0d9 | |||
e98c57a404 | |||
4bf8d64c56 | |||
9bfe42840b | |||
4c1cd1bb78 | |||
062c7af4f3 | |||
8042140742 | |||
a433baf99a | |||
87d7b747d2 | |||
85866defa4 | |||
c986d3dcf4 | |||
3444aee5da | |||
e94975d109 | |||
d132baede3 | |||
94f17e9038 | |||
44ec66d0a0 | |||
b5b229dbe4 | |||
4376ec207c | |||
52544ffaa3 | |||
84084b1bdb | |||
11600255fb | |||
a72633891b | |||
dfbf6d72b0 | |||
ea10a3abe5 | |||
f8096d4993 | |||
7dab458884 | |||
f4a797db24 | |||
4df82bdbc1 | |||
b00aeeff37 | |||
f1c9d6a81f | |||
df123e0410 | |||
023bd31965 | |||
b39efdd9d6 | |||
f9545d1b1a | |||
0b78f54d4f | |||
522919a537 | |||
650c5a02ac | |||
d0d351cccb | |||
a9543457ef | |||
a8ebc837ea | |||
7fae9114c8 | |||
5d34657198 | |||
d32939d51a | |||
d528e30cef | |||
8f8c5ba12e | |||
cba92db6bf | |||
c6ae72987b | |||
31006f734e | |||
3680aef801 | |||
5902a4629c | |||
ad26cd6d0c | |||
fdf39985f0 | |||
44dfa606ed | |||
3970d00edd | |||
10c7b89f14 | |||
0397e08153 | |||
6b96931576 | |||
e269274bcd | |||
8313ffc38d | |||
ffe1b4d819 | |||
e5c10c3d91 | |||
e3a2ca5ad9 | |||
1cc08b4a4a | |||
e3180818b0 | |||
f00af3ea08 | |||
5256a91fb2 | |||
7fabe4429d | |||
37c05bd575 | |||
9c7fb0dfe1 | |||
2380b975c6 | |||
28ceca0163 | |||
fc6dc78fe9 | |||
042463fffb | |||
cabf1c7105 | |||
93820b493c | |||
dc1ed3c47e | |||
b69ec48d77 | |||
098a787161 | |||
053b43d308 | |||
6980631631 | |||
452668b581 | |||
ceb14deb60 | |||
3cb6dad6d5 | |||
fb6a31cbd6 | |||
3290fc3365 | |||
30a3b49830 | |||
50687e11cf | |||
bf57e9d781 | |||
05cdfb90e9 | |||
16d26e5f38 | |||
f5c0b30256 | |||
2182be48c4 | |||
54e4bdb842 | |||
9e7a8f6e89 | |||
44dd764d6d | |||
255e672295 | |||
84ad0ccfa0 | |||
f0341142b8 | |||
b0c75611d6 | |||
2a35471abe | |||
055dc2d9a2 | |||
15ca1bbd11 | |||
cab5927bd5 | |||
f6a67c9a84 | |||
dcb44e6dea | |||
6316051967 | |||
5657126d86 | |||
aa48810d80 | |||
352c582f98 | |||
6bd28e6063 | |||
7a6eb9de46 | |||
f013c57186 | |||
913563a41d | |||
8fa7e93c30 | |||
cad67148b1 | |||
c71d7b5633 | |||
4da739a970 | |||
21d13dd15a | |||
8e9858fadb | |||
159ab1c257 | |||
7f221d8d2a | |||
d63d53f5ad | |||
7c52d10e5c | |||
160cace336 | |||
ca1c430f30 | |||
091a504377 | |||
4f61832d1c | |||
6740d0de74 | |||
8a63f6e245 | |||
917a7884be | |||
2ccf5c4ffe | |||
dacf58eb99 | |||
21f6daf0bb | |||
95f8b63265 | |||
4f81a7c590 | |||
55e24d2602 | |||
a315dedb85 | |||
f514ac3da2 | |||
0ae8c08b3c | |||
276bdd1f3e | |||
d553ec2f36 | |||
cdf5cacdc0 | |||
dfdaaf6a0d | |||
b82f62a11d | |||
8973dd5a7e | |||
4b5cd721c1 | |||
6abbaaed89 | |||
dfdc2adbc6 | |||
fa0c65efe5 | |||
271fcb0f3e | |||
af952cad62 | |||
27b196f585 | |||
2adf03e54a | |||
dca1535cb5 | |||
b2f73ddb64 | |||
33977a2ad5 | |||
445f7896c1 | |||
24ebdbd04b | |||
821fecb413 | |||
26433509f9 | |||
68074df0a2 | |||
8f425701e4 | |||
0d8ab323a7 | |||
345bdd3db0 | |||
d70a7f3ac9 | |||
cd858323f2 | |||
2bc39860bb | |||
1279a503a1 | |||
20cef5078d | |||
ccc77ca441 | |||
f52600e261 | |||
4b9948c1be | |||
faca8b1382 | |||
a3ee08968e | |||
b6dbcf93a0 | |||
9062b391a2 | |||
c07afd9db1 | |||
b25f06ee7c | |||
8973f12ee4 | |||
486f69fcac | |||
145121a75d | |||
130ae158c4 | |||
295e0f65a1 | |||
89bf06c28c | |||
0d4149c736 | |||
862697d4bd | |||
7524c99be2 | |||
7f17c70fd0 | |||
bd864fb274 | |||
e31992c112 | |||
c61a8b7b14 | |||
b2d6f43b49 | |||
f0b0d64453 | |||
8e644d99fc | |||
159788685a | |||
cfb67edd85 | |||
b5ed403bc4 | |||
46bc910ecb | |||
56f8c23adf | |||
6cf3c2b682 | |||
d3c08e74f6 | |||
4f9374951d | |||
20a2bae1d3 | |||
7d598801f0 | |||
7ad6b0378c | |||
0cf49c8de3 | |||
6552471c49 | |||
75723d5c89 | |||
06d4a0c46e | |||
7ec05b4d8c | |||
8eb102ab10 | |||
2a39425e48 | |||
7d89cff545 | |||
6f5c124fe9 | |||
931a636bcc | |||
a082f6484a | |||
d84705121a | |||
f3f2ef4a2a | |||
a1470c94a6 | |||
f5f323dae0 | |||
35e02ad5e0 | |||
a566e52ca4 | |||
01fd0cd878 | |||
973ebdc0ea | |||
a088b8c203 | |||
0df914e1e9 | |||
912b0529c1 | |||
bf3ac41e36 | |||
b55e1c2ba9 | |||
64f6820660 | |||
4526b3ef50 | |||
49c73bc170 | |||
4a70b669be | |||
b93c1dffa1 | |||
84ce45ca16 | |||
0c6e1f4a1b | |||
64a34616d8 | |||
c96dea27ce | |||
1fa5478fef | |||
eb17502a7c | |||
c8a8dcfc6e | |||
3983d04b1c | |||
d40af0c137 | |||
73f6ed9be1 | |||
67f4a5d4bd | |||
26842491c6 | |||
1b84b11cf5 | |||
63e125986c | |||
1439071b7e | |||
32c5be97b0 | |||
aedc343003 | |||
9129f9ac9b | |||
412e47d311 | |||
c331fc6f0c | |||
2389a68ea3 | |||
81a5ceb6d4 | |||
ed36c68cdb | |||
88c30e231a | |||
eb99753e4a | |||
4effb89ae8 | |||
49537458ea | |||
140217546d | |||
65775a36d7 | |||
6e89b1c1cd | |||
23bc8edf24 | |||
36e7bf1b7b | |||
816ec0b1c3 | |||
4354fce2bb | |||
653eb5949d | |||
2d51579a87 | |||
419fa172ff | |||
8ceea0f238 | |||
e024f2f8b7 | |||
619b8ab822 | |||
dde1d67232 | |||
3c34b8b4f1 | |||
11a8bd8aca | |||
57dae161c3 | |||
d819c00fee | |||
9e391e010c | |||
7773d7f552 | |||
8424f587b0 | |||
5d4bb290c2 | |||
3074f0e436 | |||
7076773360 | |||
0340ba47df | |||
44d0296bab | |||
39e426cde3 | |||
60e403bf6d | |||
23b06af940 | |||
78e3a4c97c | |||
5d82c73da6 | |||
1cca27d823 | |||
d35d164ece | |||
f7ba4b2ff9 | |||
572fd7a79a | |||
04f902fca5 | |||
d1227ec800 | |||
198797bcf6 | |||
4622d0b23a | |||
0487fbe236 | |||
d0e8020506 | |||
a7ba05ad82 | |||
d62da4da12 | |||
b09e03b28d | |||
2fce701ced | |||
32157115da | |||
c2f30542e7 | |||
d767e0b2c0 | |||
1db53da0d3 | |||
f45aedcbf0 | |||
4001bb44d2 | |||
30f12f2887 | |||
89b8c88389 | |||
330ecfbed0 | |||
bc0fbfc93e | |||
a4462c24fa | |||
69c7488927 | |||
9e5223eaba | |||
3c9ad1d231 | |||
dc300c5c41 | |||
bf71b107b3 | |||
0d9b27ff26 | |||
c8c8648abf | |||
8ce59a583b | |||
573fb783e1 | |||
d666370e16 | |||
a72250bace | |||
026b7e34b3 | |||
4390e10dfd | |||
e56c8bf8d1 | |||
ca40565f9a | |||
975c269752 | |||
34306c356e | |||
2a7210e382 | |||
391767fb8f | |||
bf3beb5959 | |||
01917733a1 | |||
859da3af50 | |||
a43998c089 | |||
20729b3378 | |||
cf1ebdc079 | |||
893c1735dd | |||
81e975ad93 | |||
20ea5b5634 | |||
4222b63639 | |||
b5dbf5154e | |||
92e80af875 | |||
a4934a74b6 | |||
91bffa9c53 | |||
60800da6c1 | |||
b07bd30b70 | |||
4f965ad2a1 | |||
848f4148c0 | |||
65943b458f | |||
6574e61062 | |||
ee12e725c0 | |||
3ec7c5081d | |||
e22a302cad | |||
92b05652b2 | |||
4756324b5c | |||
ce5242462b | |||
1c9e526a83 | |||
8a626288a6 | |||
bf6ac6cef8 | |||
3da82338d1 | |||
f8f1168fa6 | |||
a752971bca | |||
f0c4f31771 | |||
a63fd2d0f5 | |||
d97994b27f | |||
c31e78f670 | |||
bc652a2943 | |||
e6e590479e | |||
123da1a8c2 | |||
7695dbd0bd | |||
9741f5b8cf | |||
1b97971eb7 | |||
0ada23a5fb | |||
6b1780d77e | |||
7865abf667 | |||
efa443bba3 | |||
f5a0ec0d7c | |||
5247594e86 | |||
095b6e8113 | |||
8b9249a670 | |||
f80c6008af | |||
b278ea1f09 | |||
1810cdf2c3 | |||
97ef8ae9e7 | |||
99c5db1fb1 | |||
e5c9f7a507 | |||
9729e8f4b9 | |||
78b6f88cb3 | |||
552836ebf0 | |||
2f36a9591d | |||
83c9bff242 | |||
4efb460127 | |||
ac1988d8e6 | |||
edb50a2f51 | |||
c89045fb77 | |||
1258ec041d | |||
499e303ea3 | |||
e618032d53 | |||
b9eeb1c383 | |||
1529ecd8fa | |||
51f26cb4e0 | |||
0d972d9bbf | |||
19546c234e | |||
791d192e63 | |||
15e671ec5a | |||
3567e81175 | |||
ff2ee644b4 | |||
b57ce9299a | |||
9e26216c40 | |||
a4398aa17f | |||
53e4e0c1a3 | |||
5e769d9a25 | |||
931a363612 | |||
3ca1a57f81 | |||
297c54ebb3 | |||
dc2464eaaa | |||
7dbc103cbe | |||
93837e9545 | |||
6c5c97b2f9 | |||
099d1a67a0 | |||
6744b19297 | |||
f9a4abb6dc | |||
4e4bca6bbc | |||
d0037b22ef | |||
d568d7a352 | |||
86d41a1db9 | |||
e6a0c45674 | |||
7d2a746090 | |||
c13f46c7c5 | |||
516af6c531 | |||
9c2d0d0b24 | |||
64647af1a6 | |||
c016066d9b | |||
beabfb7960 | |||
804fb99d66 | |||
387db75003 | |||
c40677a4f5 | |||
d4b46e271a | |||
53bae68617 | |||
952ca59336 | |||
affcbbdd7e | |||
496372dd30 | |||
e9e804fb02 | |||
aed95fd8c7 | |||
aca8ea9c0b | |||
4a01ada291 | |||
10618752e6 | |||
c60418b1f4 | |||
c78c221028 | |||
1aca54da06 | |||
f5d5a3df59 | |||
f017b26e5d | |||
c4ad83e7cd | |||
cf6ea283bb | |||
ea0a99610d | |||
df6a8b28de | |||
3b9bc73db4 | |||
18b6d580c5 | |||
03417df54e | |||
61cd5f7c0f | |||
68dfa04f8a | |||
6902977665 | |||
bc68b592b1 | |||
a64859b4bc | |||
2f30bbb495 | |||
603e7935aa | |||
030d43b9f3 | |||
dff10085e8 | |||
e804143183 | |||
bec4ca0c73 | |||
81acbad058 | |||
360be02c0e | |||
adce5064b0 | |||
1918f8d5b5 | |||
eb5d3088a4 | |||
683d53db4b | |||
a2929dfd57 | |||
911bfef04c | |||
aadbc8a9d3 | |||
2e7b5c5d64 | |||
86580a8460 | |||
8634d0bcd8 | |||
492576114d | |||
ca1e538752 | |||
afbee736ea | |||
84e311038d | |||
4dfa71f018 | |||
4e9f2e5895 | |||
081f95c812 | |||
152ca66eba | |||
17586f1e94 | |||
6712492dc2 | |||
9f4299d47b | |||
ad6771dcd4 | |||
2c25d29b25 | |||
ec29fd3e7b | |||
d042c4afe0 | |||
5d740785a9 | |||
68b2211e64 | |||
332394d87c | |||
62b4ff5250 | |||
634e9e970a | |||
678c28175e | |||
87a7f2dcb9 | |||
8fc4ae51fb | |||
66be3c9f51 | |||
b95089db20 | |||
8a4ec8e565 | |||
95743e3a64 | |||
9ad54d74d2 | |||
0e1cceed50 | |||
23648b052a | |||
91d2368e37 | |||
ede65dbede | |||
578e4c7642 | |||
96770e5c6b | |||
1130e48541 | |||
2a869271f6 | |||
c0bf222a05 | |||
d72d50d83e | |||
ef6f1605db | |||
ea7ec4a6b3 | |||
72f3d99920 | |||
f6991dec3b | |||
0367d14044 | |||
8bf51db3e7 | |||
4f250726aa | |||
86d3099141 | |||
d4c3742e25 | |||
95993e1dd5 | |||
d52d82d744 | |||
d2e6d6978e | |||
da4a28e692 | |||
b876356527 | |||
07509da78d | |||
9ff8155cd9 | |||
56f44be0aa | |||
d50d400231 | |||
19fcfc3d00 | |||
c048358cf9 | |||
8171a2ab94 | |||
2fd4c372d5 | |||
f76ce84ae1 | |||
f3859130f2 | |||
0f274d65c4 | |||
cb71b93351 | |||
4b51d31aea | |||
40bbfbf961 | |||
30f319a11f | |||
5d7ba57dd5 | |||
9cd8327051 | |||
1d8f939c96 | |||
2e28d9f012 | |||
7c730fe5b3 | |||
f233131974 | |||
aefa06f7df | |||
d878f3df93 | |||
f8741c0985 | |||
5e2ce9b2a6 | |||
d725ab5142 | |||
f1a860fbf7 | |||
141f9b2386 | |||
95f852e856 | |||
2c7386c961 | |||
d5cbcef0ea | |||
b0476f308b | |||
9dc52d9d04 | |||
297dc2bc02 | |||
0cc9842bf6 | |||
54ea10288e | |||
1880c9531f | |||
13a803d4f7 | |||
f6c2db818e | |||
67789f10ef | |||
b83f1300bd | |||
6e16a17015 | |||
d744dd70e0 | |||
4e91ead40b | |||
7f39f37003 | |||
bf9ab53f12 | |||
d99f661af7 | |||
5d58a31d86 | |||
07b89902d5 | |||
ce6948fc1b | |||
38d626a3fa | |||
9b8a244a15 | |||
1bbf28ad19 | |||
3b24e0edb6 | |||
b647608c96 | |||
31c462ae3f | |||
da39fd70d2 | |||
ee0b857172 | |||
e0d6782d26 | |||
2f9e957523 | |||
38dbae9ca0 | |||
5a3077f46c | |||
d0cc019c1a | |||
26e8032bd0 | |||
84af7b065d | |||
83dc3c0ee0 | |||
5952775a03 | |||
57531737e5 | |||
3fd50f07fd | |||
4237c34c78 | |||
361eaf1888 | |||
cca89ec36e | |||
e4c7f369f2 | |||
d573a14119 | |||
ff767dd153 | |||
34c6ce6b08 | |||
6737e91974 | |||
1006eab482 | |||
a9f2952882 | |||
100c7eff25 | |||
dc7349915d | |||
213c25fb08 | |||
615a515bba | |||
838a3f204f | |||
15c2467dbd | |||
74ea4e9b5d | |||
4481571999 | |||
2132c8f461 | |||
2b3cac5b31 | |||
8d5e3e6981 | |||
30f1dc002a | |||
5da3b00222 | |||
631998b2df | |||
30d6233e83 | |||
6468711e16 | |||
d698b0eadf | |||
1f3331f5e6 | |||
b6c9678f21 | |||
4c2ce4e8ba | |||
bb0f95b6fb | |||
853faf4c71 | |||
00c7db02d1 | |||
13143b850e | |||
c1724062f1 | |||
7570f7222f | |||
f1e3d5125d | |||
3511f08a81 | |||
982bc7f2aa | |||
3903e5ebe7 | |||
0918adf39d | |||
42c331bbf2 | |||
0bae97a726 | |||
c5949f85ef | |||
24521f549c | |||
4bd9f53e8f | |||
2a78dcbd5a | |||
2ea57cdcc3 | |||
31022cbecf | |||
ce8053103e | |||
0b885ecaf7 | |||
1700bd6f08 | |||
b89bc37170 | |||
39df4dbde7 | |||
716d887e51 | |||
5b4cf38166 | |||
4c0ad5238e | |||
9e8903ada1 | |||
aa55d88408 | |||
07fc4c2464 | |||
b9bd95b3b2 | |||
3f89aeb80a | |||
6c530d3a85 | |||
03bf0d6b41 | |||
d4cee514f6 | |||
331989cea3 | |||
bbf96db2f2 | |||
72c2578d14 | |||
1a666dea61 | |||
7634c1cb31 | |||
95914a0fbf | |||
9c50891d6e | |||
624433c51d | |||
09cc458bfc | |||
efe0c5f371 | |||
d9d226087c | |||
7bad1d356d | |||
0add00a743 | |||
d557f1d9de | |||
665627e254 | |||
a609bf50ed | |||
f8195e5e3d | |||
65b209359a | |||
3a65c9ad4e | |||
77e58c6179 | |||
23d625172a | |||
c3643615fc | |||
638aaecc7d | |||
5a79decba4 | |||
225162aa6c | |||
a43b80a4c9 | |||
beebf7fe14 | |||
0ef1f7ef0d | |||
fc6dad40ac | |||
ecd473bbce | |||
8a3fd58cad | |||
8024857d4c | |||
3fa876c5e7 | |||
516515d9e3 | |||
948f507ba0 | |||
81a8ee1ddb | |||
5e58da14f0 | |||
fa8e633be5 | |||
be337a2e52 | |||
4d164b6ca4 | |||
371ffef4ce | |||
fdfedceeec | |||
9e5d440a0b | |||
0f7d2ca7a8 | |||
81c9720acb | |||
ea2cfbbd2e | |||
2326b9c294 | |||
41de0e0d98 | |||
f6a2dbf4f5 | |||
b115374601 | |||
7d82053117 |
97
.bazelignore
Normal file
97
.bazelignore
Normal file
@ -0,0 +1,97 @@
|
||||
# Bazel does not yet support wildcards or other .gitignore semantics for
|
||||
# .bazelignore. Two issues for this feature request are outstanding:
|
||||
# https://github.com/bazelbuild/bazel/issues/7093
|
||||
# https://github.com/bazelbuild/bazel/issues/8106
|
||||
.git
|
||||
node_modules
|
||||
dist
|
||||
aio/content
|
||||
aio/node_modules
|
||||
aio/tools/examples/shared/node_modules
|
||||
packages/bazel/node_modules
|
||||
integration/bazel/bazel-bazel
|
||||
integration/bazel/bazel-bin
|
||||
integration/bazel/bazel-out
|
||||
integration/bazel/bazel-testlogs
|
||||
integration/bazel-schematics/demo
|
||||
# All integration test node_modules folders
|
||||
integration/bazel/node_modules
|
||||
integration/bazel-schematics/node_modules
|
||||
integration/cli-hello-world/node_modules
|
||||
integration/cli-hello-world-ivy-compat/node_modules
|
||||
integration/cli-hello-world-ivy-i18n/node_modules
|
||||
integration/cli-hello-world-ivy-minimal/node_modules
|
||||
integration/cli-hello-world-lazy/node_modules
|
||||
integration/cli-hello-world-lazy-rollup/node_modules
|
||||
integration/dynamic-compiler/node_modules
|
||||
integration/hello_world__closure/node_modules
|
||||
integration/hello_world__systemjs_umd/node_modules
|
||||
integration/i18n/node_modules
|
||||
integration/injectable-def/node_modules
|
||||
integration/ivy-i18n/node_modules
|
||||
integration/language_service_plugin/node_modules
|
||||
integration/ng_elements/node_modules
|
||||
integration/ng_elements_schematics/node_modules
|
||||
integration/ng_update/node_modules
|
||||
integration/ng_update_migrations/node_modules
|
||||
integration/ngcc/node_modules
|
||||
integration/platform-server/node_modules
|
||||
integration/service-worker-schema/node_modules
|
||||
integration/side-effects/node_modules
|
||||
integration/terser/node_modules
|
||||
integration/typings_test_ts36/node_modules
|
||||
integration/typings_test_ts37/node_modules
|
||||
# All integration test .yarn_local_cache folders
|
||||
integration/bazel/.yarn_local_cache
|
||||
integration/bazel-schematics/.yarn_local_cache
|
||||
integration/cli-hello-world/.yarn_local_cache
|
||||
integration/cli-hello-world-ivy-compat/.yarn_local_cache
|
||||
integration/cli-hello-world-ivy-i18n/.yarn_local_cache
|
||||
integration/cli-hello-world-ivy-minimal/.yarn_local_cache
|
||||
integration/cli-hello-world-lazy/.yarn_local_cache
|
||||
integration/cli-hello-world-lazy-rollup/.yarn_local_cache
|
||||
integration/dynamic-compiler/.yarn_local_cache
|
||||
integration/hello_world__closure/.yarn_local_cache
|
||||
integration/hello_world__systemjs_umd/.yarn_local_cache
|
||||
integration/i18n/.yarn_local_cache
|
||||
integration/injectable-def/.yarn_local_cache
|
||||
integration/ivy-i18n/.yarn_local_cache
|
||||
integration/language_service_plugin/.yarn_local_cache
|
||||
integration/ng_elements/.yarn_local_cache
|
||||
integration/ng_elements_schematics/.yarn_local_cache
|
||||
integration/ng_update/.yarn_local_cache
|
||||
integration/ng_update_migrations/.yarn_local_cache
|
||||
integration/ngcc/.yarn_local_cache
|
||||
integration/platform-server/.yarn_local_cache
|
||||
integration/service-worker-schema/.yarn_local_cache
|
||||
integration/side-effects/.yarn_local_cache
|
||||
integration/terser/.yarn_local_cache
|
||||
integration/typings_test_ts36/.yarn_local_cache
|
||||
integration/typings_test_ts37/.yarn_local_cache
|
||||
# All integration test NPM_PACKAGE_MANIFEST.json folders
|
||||
integration/bazel/NPM_PACKAGE_MANIFEST.json
|
||||
integration/bazel-schematics/NPM_PACKAGE_MANIFEST.json
|
||||
integration/cli-hello-world/NPM_PACKAGE_MANIFEST.json
|
||||
integration/cli-hello-world-ivy-compat/NPM_PACKAGE_MANIFEST.json
|
||||
integration/cli-hello-world-ivy-i18n/NPM_PACKAGE_MANIFEST.json
|
||||
integration/cli-hello-world-ivy-minimal/NPM_PACKAGE_MANIFEST.json
|
||||
integration/cli-hello-world-lazy/NPM_PACKAGE_MANIFEST.json
|
||||
integration/cli-hello-world-lazy-rollup/NPM_PACKAGE_MANIFEST.json
|
||||
integration/dynamic-compiler/NPM_PACKAGE_MANIFEST.json
|
||||
integration/hello_world__closure/NPM_PACKAGE_MANIFEST.json
|
||||
integration/hello_world__systemjs_umd/NPM_PACKAGE_MANIFEST.json
|
||||
integration/i18n/NPM_PACKAGE_MANIFEST.json
|
||||
integration/injectable-def/NPM_PACKAGE_MANIFEST.json
|
||||
integration/ivy-i18n/NPM_PACKAGE_MANIFEST.json
|
||||
integration/language_service_plugin/NPM_PACKAGE_MANIFEST.json
|
||||
integration/ng_elements/NPM_PACKAGE_MANIFEST.json
|
||||
integration/ng_elements_schematics/NPM_PACKAGE_MANIFEST.json
|
||||
integration/ng_update/NPM_PACKAGE_MANIFEST.json
|
||||
integration/ng_update_migrations/NPM_PACKAGE_MANIFEST.json
|
||||
integration/ngcc/NPM_PACKAGE_MANIFEST.json
|
||||
integration/platform-server/NPM_PACKAGE_MANIFEST.json
|
||||
integration/service-worker-schema/NPM_PACKAGE_MANIFEST.json
|
||||
integration/side-effects/NPM_PACKAGE_MANIFEST.json
|
||||
integration/terser/NPM_PACKAGE_MANIFEST.json
|
||||
integration/typings_test_ts36/NPM_PACKAGE_MANIFEST.json
|
||||
integration/typings_test_ts37/NPM_PACKAGE_MANIFEST.json
|
155
.bazelrc
Normal file
155
.bazelrc
Normal file
@ -0,0 +1,155 @@
|
||||
# Enable debugging tests with --config=debug
|
||||
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
||||
|
||||
###############################
|
||||
# Filesystem interactions #
|
||||
###############################
|
||||
|
||||
# Create symlinks in the project:
|
||||
# - dist/bin for outputs
|
||||
# - dist/testlogs, dist/genfiles
|
||||
# - bazel-out
|
||||
# NB: bazel-out should be excluded from the editor configuration.
|
||||
# The checked-in /.vscode/settings.json does this for VSCode.
|
||||
# Other editors may require manual config to ignore this directory.
|
||||
# In the past, we say a problem where VSCode traversed a massive tree, opening file handles and
|
||||
# eventually a surprising failure with auto-discovery of the C++ toolchain in
|
||||
# MacOS High Sierra.
|
||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||
build --symlink_prefix=dist/
|
||||
|
||||
# Turn off legacy external runfiles
|
||||
build --nolegacy_external_runfiles
|
||||
run --nolegacy_external_runfiles
|
||||
test --nolegacy_external_runfiles
|
||||
|
||||
# Turn on --incompatible_strict_action_env which was on by default
|
||||
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
|
||||
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
|
||||
# This flag is needed to so that the bazel cache is not invalidated
|
||||
# when running bazel via `yarn bazel`.
|
||||
# See https://github.com/angular/angular/issues/27514.
|
||||
build --incompatible_strict_action_env
|
||||
run --incompatible_strict_action_env
|
||||
test --incompatible_strict_action_env
|
||||
|
||||
# Do not build runfile trees by default. If an execution strategy relies on runfile
|
||||
# symlink teee, the tree is created on-demand. See: https://github.com/bazelbuild/bazel/issues/6627
|
||||
# and https://github.com/bazelbuild/bazel/commit/03246077f948f2790a83520e7dccc2625650e6df
|
||||
build --nobuild_runfile_links
|
||||
|
||||
###############################
|
||||
# Release support #
|
||||
# Turn on these settings with #
|
||||
# --config=release #
|
||||
###############################
|
||||
|
||||
# Releases should always be stamped with version control info
|
||||
# This command assumes node on the path and is a workaround for
|
||||
# https://github.com/bazelbuild/bazel/issues/4802
|
||||
build:release --workspace_status_command="yarn -s ng-dev release build-env-stamp"
|
||||
build:release --stamp
|
||||
|
||||
###############################
|
||||
# Output #
|
||||
###############################
|
||||
|
||||
# A more useful default output mode for bazel query
|
||||
# Prints eg. "ng_module rule //foo:bar" rather than just "//foo:bar"
|
||||
query --output=label_kind
|
||||
|
||||
# By default, failing tests don't print any output, it goes to the log file
|
||||
test --test_output=errors
|
||||
|
||||
################################
|
||||
# Settings for CircleCI #
|
||||
################################
|
||||
|
||||
# Bazel flags for CircleCI are in /.circleci/bazel.linux.rc and /.circleci/bazel.windows.rc
|
||||
|
||||
##################################
|
||||
# Settings for integration tests #
|
||||
##################################
|
||||
|
||||
# Trick bazel into treating BUILD files under integration/bazel as being regular files
|
||||
# This lets us glob() up all the files inside this integration test to make them inputs to tests
|
||||
# (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it)
|
||||
build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
|
||||
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
|
||||
|
||||
################################
|
||||
# Temporary Settings for Ivy #
|
||||
################################
|
||||
# To determine if the compiler used should be Ivy instead of ViewEngine, one can use `--config=ivy`
|
||||
# on any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
|
||||
build --define=angular_ivy_enabled=False
|
||||
|
||||
build:view-engine --define=angular_ivy_enabled=False
|
||||
build:ivy --define=angular_ivy_enabled=True
|
||||
|
||||
##################################
|
||||
# Remote Build Execution support #
|
||||
# Turn on these settings with #
|
||||
# --config=remote #
|
||||
##################################
|
||||
|
||||
# The following --define=EXECUTOR=remote will be able to be removed
|
||||
# once https://github.com/bazelbuild/bazel/issues/7254 is fixed
|
||||
build:remote --define=EXECUTOR=remote
|
||||
|
||||
# Set a higher timeout value, just in case.
|
||||
build:remote --remote_timeout=600
|
||||
|
||||
# Increase the default number of jobs by 50% because our build has lots of
|
||||
# parallelism
|
||||
build:remote --jobs=150
|
||||
build:remote --google_default_credentials
|
||||
|
||||
# Force remote exeuctions to consider the entire run as linux
|
||||
build:remote --cpu=k8
|
||||
build:remote --host_cpu=k8
|
||||
|
||||
# Toolchain and platform related flags
|
||||
build:remote --host_javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||
build:remote --javabase=@rbe_ubuntu1604_angular//java:jdk
|
||||
build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||
build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||
build:remote --crosstool_top=@rbe_ubuntu1604_angular//cc:toolchain
|
||||
build:remote --extra_toolchains=@rbe_ubuntu1604_angular//config:cc-toolchain
|
||||
build:remote --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
||||
build:remote --host_platform=//tools:rbe_ubuntu1604-angular
|
||||
build:remote --platforms=//tools:rbe_ubuntu1604-angular
|
||||
|
||||
# Remote instance and caching
|
||||
build:remote --remote_instance_name=projects/internal-200822/instances/default_instance
|
||||
build:remote --project_id=internal-200822
|
||||
build:remote --remote_cache=remotebuildexecution.googleapis.com
|
||||
build:remote --remote_executor=remotebuildexecution.googleapis.com
|
||||
|
||||
##################################
|
||||
# Saucelabs tests settings #
|
||||
# Turn on these settings with #
|
||||
# --config=saucelabs #
|
||||
##################################
|
||||
|
||||
# For saucelabs tests we don't want to enable flaky test attempts. Karma has its own integrated
|
||||
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
|
||||
test:saucelabs --flaky_test_attempts=1
|
||||
|
||||
###############################
|
||||
# NodeJS rules settings
|
||||
# These settings are required for rules_nodejs
|
||||
###############################
|
||||
|
||||
# Turn on managed directories feature in Bazel
|
||||
# This allows us to avoid installing a second copy of node_modules
|
||||
common --experimental_allow_incremental_repository_updates
|
||||
|
||||
####################################################
|
||||
# User bazel configuration
|
||||
# NOTE: This needs to be the *last* entry in the config.
|
||||
####################################################
|
||||
|
||||
# Load any settings which are specific to the current user. Needs to be *last* statement
|
||||
# in this config, as the user configuration should be able to overwrite flags from this file.
|
||||
try-import .bazelrc.user
|
3
.bazelversion
Normal file
3
.bazelversion
Normal file
@ -0,0 +1,3 @@
|
||||
3.2.0
|
||||
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
||||
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
@ -12,8 +12,8 @@ We use this as a symmetric AES encryption key to encrypt tokens like
|
||||
a GitHub token that enables publishing snapshots.
|
||||
|
||||
To create the github_token file, we take this approach:
|
||||
- Find the angular-builds:token in http://valentine
|
||||
- Go inside the ngcontainer docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it angular/ngcontainer`
|
||||
- Find the angular-builds:token in the internal pw database
|
||||
- Go inside the CircleCI default docker image so you use the same version of openssl as we will at runtime: `docker run --rm -it circleci/node:10.12`
|
||||
- echo "https://[token]:@github.com" > credentials
|
||||
- openssl aes-256-cbc -e -in credentials -out .circleci/github_token -k $KEY
|
||||
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`
|
||||
- If needed, base64-encode the result so you can copy-paste it out of docker: `base64 github_token`
|
||||
|
15
.circleci/bazel.common.rc
Normal file
15
.circleci/bazel.common.rc
Normal file
@ -0,0 +1,15 @@
|
||||
# Settings in this file should be OS agnostic. Use the bazel.<OS>.rc files for OS specific settings.
|
||||
|
||||
# Don't be spammy in the logs
|
||||
build --noshow_progress
|
||||
|
||||
# Print all the options that apply to the build.
|
||||
# This helps us diagnose which options override others
|
||||
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
|
||||
build --announce_rc
|
||||
|
||||
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||
test --flaky_test_attempts=2
|
||||
|
||||
# More details on failures
|
||||
build --verbose_failures=true
|
30
.circleci/bazel.linux.rc
Normal file
30
.circleci/bazel.linux.rc
Normal file
@ -0,0 +1,30 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Import config items common to both Linux and Windows setups.
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
build --repository_cache=/home/circleci/bazel_repository_cache
|
||||
|
||||
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
||||
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||
build --local_cpu_resources=8
|
||||
build --local_ram_resources=14336
|
||||
|
||||
# All build executed remotely should be done using our RBE configuration.
|
||||
build:remote --google_default_credentials
|
||||
|
||||
# Upload to GCP's Build Status viewer to allow for us to have better viewing of execution/build
|
||||
# logs. This is only done on CI as the BES (GCP's Build Status viewer) API requires credentials
|
||||
# from service accounts, rather than end user accounts.
|
||||
build:remote --bes_backend=buildeventservice.googleapis.com
|
||||
build:remote --bes_timeout=30s
|
||||
build:remote --bes_results_url="https://source.cloud.google.com/results/invocations/"
|
||||
|
||||
build --config=remote
|
@ -1,33 +0,0 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||
# See remote cache documentation in /docs/BAZEL.md
|
||||
|
||||
# Don't be spammy in the logs
|
||||
# TODO(gmagolan): Hide progress again once build performance improves
|
||||
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||
# error: Too long with no output (exceeded 10m0s)
|
||||
# build --noshow_progress
|
||||
|
||||
# Don't run manual tests
|
||||
test --test_tag_filters=-manual
|
||||
|
||||
# Print all the options that apply to the build.
|
||||
# This helps us diagnose which options override others
|
||||
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
|
||||
build --announce_rc
|
||||
|
||||
# Create dist/bin symlink to $(bazel info bazel-bin)
|
||||
# We use this when uploading artifacts after the build finishes
|
||||
build --symlink_prefix=dist/
|
||||
|
||||
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
||||
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||
build --local_resources=14336,8.0,1.0
|
||||
|
||||
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||
test --flaky_test_attempts=2
|
||||
|
||||
# More details on failures
|
||||
build --verbose_failures=true
|
21
.circleci/bazel.windows.rc
Normal file
21
.circleci/bazel.windows.rc
Normal file
@ -0,0 +1,21 @@
|
||||
# These options are enabled when running on CI
|
||||
# We do this by copying this file to $env:ProgramData\bazel.bazelrc at the start of the build.
|
||||
# See documentation in /docs/BAZEL.md
|
||||
|
||||
# Import config items common to both Linux and Windows setups.
|
||||
# https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics
|
||||
try-import %workspace%/.circleci/bazel.common.rc
|
||||
|
||||
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
||||
|
||||
# Manually set the local resources used in windows CI runs
|
||||
build --local_ram_resources=13500
|
||||
build --local_cpu_resources=4
|
||||
|
||||
# All windows jobs run on master and should use http caching
|
||||
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||
build --remote_accept_cached=true
|
||||
build --remote_upload_local_results=true
|
||||
build --google_default_credentials
|
File diff suppressed because it is too large
Load Diff
73
.circleci/env-helpers.inc.sh
Normal file
73
.circleci/env-helpers.inc.sh
Normal file
@ -0,0 +1,73 @@
|
||||
####################################################################################################
|
||||
# Helpers for defining environment variables for CircleCI.
|
||||
#
|
||||
# In CircleCI, each step runs in a new shell. The way to share ENV variables across steps is to
|
||||
# export them from `$BASH_ENV`, which is automatically sourced at the beginning of every step (for
|
||||
# the default `bash` shell).
|
||||
#
|
||||
# See also https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables.
|
||||
####################################################################################################
|
||||
|
||||
# Set and print an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are public, i.e. it is OK for them to be
|
||||
# visible to anyone through the CI logs.
|
||||
#
|
||||
# Usage: `setPublicVar <name> <value>`
|
||||
function setPublicVar() {
|
||||
setSecretVar $1 "$2";
|
||||
echo "$1=$2";
|
||||
}
|
||||
|
||||
# Set (without printing) an environment variable.
|
||||
#
|
||||
# Use this function for setting environment variables that are secret, i.e. should not be visible to
|
||||
# everyone through the CI logs.
|
||||
#
|
||||
# Usage: `setSecretVar <name> <value>`
|
||||
function setSecretVar() {
|
||||
# WARNING: Secrets (e.g. passwords, access tokens) should NOT be printed.
|
||||
# (Keep original shell options to restore at the end.)
|
||||
local -r originalShellOptions=$(set +o);
|
||||
set +x -eu -o pipefail;
|
||||
|
||||
echo "export $1=\"${2:-}\";" >> $BASH_ENV;
|
||||
|
||||
# Restore original shell options.
|
||||
eval "$originalShellOptions";
|
||||
}
|
||||
|
||||
|
||||
# Create a function to set an environment variable, when called.
|
||||
#
|
||||
# Use this function for creating setter for public environment variables that require expensive or
|
||||
# time-consuming computaions and may not be needed. When needed, you can call this function to set
|
||||
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
|
||||
#
|
||||
# Arguments:
|
||||
# - `<name>`: The name of the environment variable. The generated setter function will be
|
||||
# `setPublicVar_<name>`.
|
||||
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
|
||||
# executed lazily, it must be properly escaped. For example:
|
||||
# ```sh
|
||||
# # DO NOT do this:
|
||||
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
|
||||
#
|
||||
# # DO this isntead:
|
||||
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
|
||||
# ```
|
||||
#
|
||||
# Usage: `createPublicVarSetter <name> <code>`
|
||||
#
|
||||
# Example:
|
||||
# ```sh
|
||||
# createPublicVarSetter MY_VAR 'echo "FOO"';
|
||||
# echo $MY_VAR; # Not defined
|
||||
#
|
||||
# setPublicVar_MY_VAR;
|
||||
# source $BASH_ENV;
|
||||
# echo $MY_VAR; # FOO
|
||||
# ```
|
||||
function createPublicVarSetter() {
|
||||
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
|
||||
}
|
113
.circleci/env.sh
Executable file
113
.circleci/env.sh
Executable file
@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Variables
|
||||
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
|
||||
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
|
||||
readonly bashEnvCachePath="$projectDir/.circleci/bash_env_cache";
|
||||
|
||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||
source $envHelpersPath;
|
||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define PUBLIC environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
||||
####################################################################################################
|
||||
setPublicVar CI "$CI"
|
||||
setPublicVar PROJECT_ROOT "$projectDir";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||
# `CI_COMMIT_RANGE` is only used on push builds (a.k.a. non-PR, non-scheduled builds and rerun
|
||||
# workflows of such builds).
|
||||
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
|
||||
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
|
||||
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
|
||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
|
||||
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define "lazy" PUBLIC environment variables for CircleCI.
|
||||
# (I.e. functions to set an environment variable when called.)
|
||||
####################################################################################################
|
||||
createPublicVarSetter CI_STABLE_BRANCH "\$(npm info @angular/core dist-tags.latest | sed -r 's/^\\s*([0-9]+\\.[0-9]+)\\.[0-9]+.*$/\\1.x/')";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SECRET environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define SauceLabs environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setPublicVar SAUCE_USERNAME "angular-framework";
|
||||
setSecretVar SAUCE_ACCESS_KEY "0c731274ed5f-cbc9-16f4-021a-9835e39f";
|
||||
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
|
||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-framework-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
|
||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Define environment variables for the `angular/components` repo unit tests job.
|
||||
####################################################################################################
|
||||
# We specifically use a directory within "/tmp" here because we want the cloned repo to be
|
||||
# completely isolated from angular/angular in order to avoid any bad interactions between
|
||||
# their separate build setups. **NOTE**: When updating the temporary directory, also update
|
||||
# the `save_cache` path configuration in `config.yml`
|
||||
setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
|
||||
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
|
||||
setPublicVar COMPONENTS_REPO_BRANCH "master"
|
||||
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
|
||||
setPublicVar COMPONENTS_REPO_COMMIT "189d98e8b01b33974328255f085de04251d61567"
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Decrypt GCP Credentials and store them as the Google default credentials.
|
||||
####################################################################################################
|
||||
mkdir -p "$HOME/.config/gcloud";
|
||||
openssl aes-256-cbc -d -in "${projectDir}/.circleci/gcp_token" \
|
||||
-md md5 -k "$CIRCLE_PROJECT_REPONAME" -out "$HOME/.config/gcloud/application_default_credentials.json"
|
||||
####################################################################################################
|
||||
# Set bazel configuration for CircleCI runs.
|
||||
####################################################################################################
|
||||
cp "${projectDir}/.circleci/bazel.linux.rc" "$HOME/.bazelrc";
|
||||
|
||||
####################################################################################################
|
||||
# Create shell script in /tmp for Bazel actions to access CI envs without
|
||||
# busting the cache. Used by payload-size.sh script in integration tests.
|
||||
####################################################################################################
|
||||
readonly bazelVarEnv="/tmp/bazel-ci-env.sh"
|
||||
echo "# Setup by /.circle/env.sh" > $bazelVarEnv
|
||||
echo "export PROJECT_ROOT=\"${PROJECT_ROOT}\";" >> $bazelVarEnv
|
||||
echo "export CI_BRANCH=\"${CI_BRANCH}\";" >> $bazelVarEnv
|
||||
echo "export CI_BUILD_URL=\"${CI_BUILD_URL}\";" >> $bazelVarEnv
|
||||
echo "export CI_COMMIT=\"${CI_COMMIT}\";" >> $bazelVarEnv
|
||||
echo "export CI_COMMIT_RANGE=\"${CI_COMMIT_RANGE}\";" >> $bazelVarEnv
|
||||
echo "export CI_PULL_REQUEST=\"${CI_PULL_REQUEST}\";" >> $bazelVarEnv
|
||||
echo "export CI_REPO_NAME=\"${CI_REPO_NAME}\";" >> $bazelVarEnv
|
||||
echo "export CI_REPO_OWNER=\"${CI_REPO_OWNER}\";" >> $bazelVarEnv
|
||||
echo "export CI_SECRET_PAYLOAD_FIREBASE_TOKEN=\"${CI_SECRET_PAYLOAD_FIREBASE_TOKEN}\";" >> $bazelVarEnv
|
||||
|
||||
####################################################################################################
|
||||
####################################################################################################
|
||||
## Source `$BASH_ENV` to make the variables available immediately. ##
|
||||
## ***NOTE: This must remain the the last action in this script*** ##
|
||||
####################################################################################################
|
||||
####################################################################################################
|
||||
source $BASH_ENV;
|
Binary file not shown.
Binary file not shown.
@ -1,77 +0,0 @@
|
||||
# These options are enabled when running on CI with Remote Build Execution.
|
||||
|
||||
################################################################
|
||||
# Toolchain related flags for remote build execution. #
|
||||
################################################################
|
||||
# Remote Build Execution requires a strong hash function, such as SHA256.
|
||||
startup --host_jvm_args=-Dbazel.DigestFunction=SHA256
|
||||
|
||||
# Depending on how many machines are in the remote execution instance, setting
|
||||
# this higher can make builds faster by allowing more jobs to run in parallel.
|
||||
# Setting it too high can result in jobs that timeout, however, while waiting
|
||||
# for a remote machine to execute them.
|
||||
build --jobs=150
|
||||
|
||||
# Set several flags related to specifying the platform, toolchain and java
|
||||
# properties.
|
||||
# These flags are duplicated rather than imported from (for example)
|
||||
# %workspace%/configs/ubuntu16_04_clang/1.0/toolchain.bazelrc to make this
|
||||
# bazelrc a standalone file that can be copied more easily.
|
||||
# These flags should only be used as is for the rbe-ubuntu16-04 container
|
||||
# and need to be adapted to work with other toolchain containers.
|
||||
build --host_javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:jdk8
|
||||
build --javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:jdk8
|
||||
build --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||
build --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
|
||||
build --crosstool_top=@bazel_toolchains//configs/ubuntu16_04_clang/1.0/bazel_0.15.0/default:toolchain
|
||||
build --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
|
||||
# Platform flags:
|
||||
# The toolchain container used for execution is defined in the target indicated
|
||||
# by "extra_execution_platforms", "host_platform" and "platforms".
|
||||
# If you are using your own toolchain container, you need to create a platform
|
||||
# target with "constraint_values" that allow for the toolchain specified with
|
||||
# "extra_toolchains" to be selected (given constraints defined in
|
||||
# "exec_compatible_with").
|
||||
# More about platforms: https://docs.bazel.build/versions/master/platforms.html
|
||||
build --extra_toolchains=@bazel_toolchains//configs/ubuntu16_04_clang/1.0/bazel_0.15.0/cpp:cc-toolchain-clang-x86_64-default
|
||||
build --extra_execution_platforms=//tools:rbe_ubuntu1604-angular
|
||||
build --host_platform=//tools:rbe_ubuntu1604-angular
|
||||
build --platforms=//tools:rbe_ubuntu1604-angular
|
||||
|
||||
# Set various strategies so that all actions execute remotely. Mixing remote
|
||||
# and local execution will lead to errors unless the toolchain and remote
|
||||
# machine exactly match the host machine.
|
||||
build --spawn_strategy=remote
|
||||
build --strategy=Javac=remote
|
||||
build --strategy=Closure=remote
|
||||
build --genrule_strategy=remote
|
||||
build --define=EXECUTOR=remote
|
||||
|
||||
# Enable the remote cache so action results can be shared across machines,
|
||||
# developers, and workspaces.
|
||||
build --remote_cache=remotebuildexecution.googleapis.com
|
||||
|
||||
# Enable remote execution so actions are performed on the remote systems.
|
||||
build --remote_executor=remotebuildexecution.googleapis.com
|
||||
|
||||
# Remote instance.
|
||||
build --remote_instance_name=projects/internal-200822/instances/default_instance
|
||||
|
||||
# Enable encryption.
|
||||
build --tls_enabled=true
|
||||
|
||||
# Enforce stricter environment rules, which eliminates some non-hermetic
|
||||
# behavior and therefore improves both the remote cache hit rate and the
|
||||
# correctness and repeatability of the build.
|
||||
build --experimental_strict_action_env=true
|
||||
|
||||
# Set a higher timeout value, just in case.
|
||||
build --remote_timeout=3600
|
||||
|
||||
# Enable authentication. This will pick up application default credentials by
|
||||
# default. You can use --auth_credentials=some_file.json to use a service
|
||||
# account credential instead.
|
||||
build --auth_enabled=true
|
||||
|
||||
# Do not accept remote cache.
|
||||
build --remote_accept_cached=false
|
105
.circleci/trigger-webhook.js
Normal file
105
.circleci/trigger-webhook.js
Normal file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Usage (cli):
|
||||
* ```
|
||||
* node create-preview <build-number> <job-name> <webhook-url>
|
||||
* ```
|
||||
*
|
||||
* Usage (JS):
|
||||
* ```js
|
||||
* require('./trigger-webhook').
|
||||
* triggerWebhook(buildNumber, jobName, webhookUrl).
|
||||
* then(...);
|
||||
* ```
|
||||
*
|
||||
* Triggers a notification webhook with CircleCI specific info.
|
||||
*
|
||||
* It can be used for notifying external servers and trigger operations based on CircleCI job status
|
||||
* (e.g. triggering the creation of a preview based on previously stored build atrifacts).
|
||||
*
|
||||
* The body of the sent payload is of the form:
|
||||
* ```json
|
||||
* {
|
||||
* "payload": {
|
||||
* "build_num": ${buildNumber}
|
||||
* "build_parameters": {
|
||||
* "CIRCLE_JOB": "${jobName}"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* When used from JS, it returns a promise which resolves to an object of the form:
|
||||
* ```json
|
||||
* {
|
||||
* "statucCode": ${statusCode},
|
||||
* "responseText": "${responseText}"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* NOTE:
|
||||
* - When used from the cli, the command will exit with an error code if the response's status code
|
||||
* is outside the [200, 400) range.
|
||||
* - When used from JS, the returned promise will be resolved, even if the response's status code is
|
||||
* outside the [200, 400) range. It is up to the caller to decide how this should be handled.
|
||||
*/
|
||||
|
||||
// Imports
|
||||
const {request} = require('https');
|
||||
|
||||
// Exports
|
||||
module.exports = {
|
||||
triggerWebhook,
|
||||
};
|
||||
|
||||
// Run
|
||||
if (require.resolve === module) {
|
||||
_main(process.argv.slice(2));
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function _main(args) {
|
||||
triggerWebhook(...args)
|
||||
.then(
|
||||
({statusCode, responseText}) => (200 <= statusCode && statusCode < 400) ?
|
||||
console.log(`Status: ${statusCode}\n${responseText}`) :
|
||||
Promise.reject(new Error(`Request failed (status: ${statusCode}): ${responseText}`)))
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
function postJson(url, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const opts = {method: 'post', headers: {'Content-Type': 'application/json'}};
|
||||
const onResponse = res => {
|
||||
const statusCode = res.statusCode || -1;
|
||||
let responseText = '';
|
||||
|
||||
res.on('error', reject)
|
||||
.on('data', d => responseText += d)
|
||||
.on('end', () => resolve({statusCode, responseText}));
|
||||
};
|
||||
|
||||
request(url, opts, onResponse).on('error', reject).end(JSON.stringify(data));
|
||||
});
|
||||
}
|
||||
|
||||
async function triggerWebhook(buildNumber, jobName, webhookUrl) {
|
||||
if (!buildNumber || !jobName || !webhookUrl || isNaN(buildNumber)) {
|
||||
throw new Error(
|
||||
'Missing or invalid arguments.\n' +
|
||||
'Expected: buildNumber (number), jobName (string), webhookUrl (string)');
|
||||
}
|
||||
|
||||
const data = {
|
||||
payload: {
|
||||
build_num: +buildNumber,
|
||||
build_parameters: {CIRCLE_JOB: jobName},
|
||||
},
|
||||
};
|
||||
|
||||
return postJson(webhookUrl, data);
|
||||
}
|
56
.circleci/windows-env.ps1
Normal file
56
.circleci/windows-env.ps1
Normal file
@ -0,0 +1,56 @@
|
||||
# Install Bazel pre-reqs on Windows
|
||||
# https://docs.bazel.build/versions/master/install-windows.html
|
||||
# https://docs.bazel.build/versions/master/windows.html
|
||||
# Install MSYS2 and packages
|
||||
choco install msys2 --version 20180531.0.0 --no-progress --package-parameters "/NoUpdate"
|
||||
C:\tools\msys64\usr\bin\bash.exe -l -c "pacman --needed --noconfirm -S zip unzip patch diffutils git"
|
||||
|
||||
# Add PATH modifications to the Powershell profile. This is the win equivalent of .bash_profile.
|
||||
# https://docs.microsoft.com/en-us/previous-versions//bb613488(v=vs.85)
|
||||
new-item -path $profile -itemtype file -force
|
||||
# Paths for nodejs, npm, yarn, and msys2. Use single quotes to prevent interpolation.
|
||||
# Add before the original path to use msys2 instead of the installed gitbash.
|
||||
Add-Content $profile '$Env:path = "${Env:ProgramFiles}\nodejs\;C:\Users\circleci\AppData\Roaming\npm\;${Env:ProgramFiles(x86)}\Yarn\bin\;C:\Users\circleci\AppData\Local\Yarn\bin\;C:\tools\msys64\usr\bin\;" + $Env:path'
|
||||
# Environment variables for Bazel
|
||||
Add-Content $profile '$Env:BAZEL_SH = "C:\tools\msys64\usr\bin\bash.exe"'
|
||||
|
||||
# Get the bazelisk version devdep and store it in a global var for use in the circleci job.
|
||||
$bazeliskVersion = & ${Env:ProgramFiles}\nodejs\node.exe -e "console.log(require('./package.json').devDependencies['@bazel/bazelisk'])"
|
||||
# This is a tricky situation: we want $bazeliskVersion to be evaluated but not $Env:BAZELISK_VERSION.
|
||||
# Formatting works https://stackoverflow.com/questions/32127583/expand-variable-inside-single-quotes
|
||||
$bazeliskVersionGlobalVar = '$Env:BAZELISK_VERSION = "{0}"' -f $bazeliskVersion
|
||||
Add-Content $profile $bazeliskVersionGlobalVar
|
||||
|
||||
# Remove the CircleCI checkout SSH override, because it breaks cloning repositories through Bazel.
|
||||
# See https://circleci.com/gh/angular/angular/401454 for an example.
|
||||
# TODO: is this really needed? Maybe there's a better way. It doesn't happen on Linux or on Codefresh.
|
||||
git config --global --unset url.ssh://git@github.com.insteadOf
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Decrypt GCP Credentials and store them as the Google default credentials.
|
||||
####################################################################################################
|
||||
mkdir ${env:APPDATA}\gcloud
|
||||
openssl aes-256-cbc -d -in .circleci\gcp_token -md md5 -out "$env:APPDATA\gcloud\application_default_credentials.json" -k "$env:CIRCLE_PROJECT_REPONAME"
|
||||
|
||||
####################################################################################################
|
||||
# Set bazel configuration for CircleCI runs.
|
||||
####################################################################################################
|
||||
copy .circleci\bazel.windows.rc ${Env:USERPROFILE}\.bazelrc
|
||||
|
||||
####################################################################################################
|
||||
# Install specific version of node.
|
||||
####################################################################################################
|
||||
choco install nodejs --version 12.14.1 --no-progress
|
||||
|
||||
# These Bazel prereqs aren't needed because the CircleCI image already includes them.
|
||||
# choco install yarn --version 1.16.0 --no-progress
|
||||
# choco install vcredist2015 --version 14.0.24215.20170201
|
||||
|
||||
# We don't need VS Build Tools for the tested bazel targets.
|
||||
# If it's needed again, uncomment these lines.
|
||||
# VS Build Tools are needed for Bazel C++ targets (like com_google_protobuf)
|
||||
# choco install visualstudio2019buildtools --version 16.1.2.0 --no-progress --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.Component.VC.Runtime.UCRTSDK --add Microsoft.VisualStudio.Component.Windows10SDK.17763"
|
||||
# Add-Content $profile '$Env:BAZEL_VC = "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\VC\"'
|
||||
# Python is needed for Bazel Python targets
|
||||
# choco install python --version 3.5.1 --no-progress
|
31
.devcontainer/README.md
Normal file
31
.devcontainer/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# VSCode Remote Development - Developing inside a Containers
|
||||
|
||||
This folder contains configuration files that can be used to opt into working on this repository in a [Docker container](https://www.docker.com/resources/what-container) via [VSCode](https://code.visualstudio.com/)'s Remote Development feature (see below).
|
||||
|
||||
Info on remote development and developing inside a container with VSCode:
|
||||
- [VSCode: Remote Development](https://code.visualstudio.com/docs/remote/remote-overview)
|
||||
- [VSCode: Developing inside a Container](https://code.visualstudio.com/docs/remote/containers)
|
||||
- [VSCode: Remote Development FAQ](https://code.visualstudio.com/docs/remote/faq)
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
_Prerequisite: [Install Docker](https://docs.docker.com/install) on your local environment._
|
||||
|
||||
To get started, read and follow the instuctions in [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). The [.devcontainer/](.) directory contains pre-configured `devcontainer.json` and `Dockerfile` files, which you can use to set up remote development with a docker container.
|
||||
|
||||
In a nutshell, you need to:
|
||||
- Install the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
|
||||
- Copy [recommended-Dockerfile](./recommended-Dockerfile) to `Dockerfile` (and optionally tweak to suit your needs).
|
||||
- Copy [recommended-devcontainer.json](./recommended-devcontainer.json) to `devcontainer.json` (and optionally tweak to suit your needs).
|
||||
- Open VSCode and bring up the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||
- Type `Remote-Containers: Open Folder in Container` and choose your local clone of [angular/angular](https://github.com/angular/angular).
|
||||
|
||||
The `.devcontainer/devcontainer.json` and `.devcontainer/Dockerfile` files are ignored by git, so you can have your own local versions. We may occasionally update the template files ([recommended-devcontainer.json](./recommended-devcontainer.json), [recommended-Dockerfile](./recommended-Dockerfile)), in which case you will need to manually update your local copies (if desired).
|
||||
|
||||
|
||||
## Updating `recommended-devcontainer.json` and `recommended-Dockerfile`
|
||||
|
||||
You can update and commit the recommended config files (which people use as basis for their local configs), if you find that something is broken, out-of-date or can be improved.
|
||||
|
||||
Please, keep in mind that any changes you make will potentially be used by many people on different environments. Try to keep these config files cross-platform compatible and free of personal preferences.
|
24
.devcontainer/recommended-Dockerfile
Normal file
24
.devcontainer/recommended-Dockerfile
Normal file
@ -0,0 +1,24 @@
|
||||
# Image metadata and config.
|
||||
FROM circleci/node:10-browsers # Ideally, the image version should be what we use on CI.
|
||||
# See `executors > browsers-executor` in `.circleci/config.yml`.
|
||||
|
||||
LABEL name="Angular dev environment" \
|
||||
description="This image can be used to create a dev environment for building Angular." \
|
||||
vendor="angular" \
|
||||
version="1.0"
|
||||
|
||||
EXPOSE 4000 4200 4433 5000 8080 9876
|
||||
|
||||
|
||||
# Switch to `root` (CircleCI images use `circleci` as the user).
|
||||
USER root
|
||||
|
||||
|
||||
# Configure `Node.js`/`npm` and install utilities.
|
||||
RUN npm config --global set user root
|
||||
RUN npm install --global yarn@latest # Ideally, the version should be what we use on CI.
|
||||
# See `commands > overwrite_yarn` in `.circleci/config.yml`.
|
||||
|
||||
|
||||
# Go! (And keep going.)
|
||||
CMD ["tail", "--follow", "/dev/null"]
|
16
.devcontainer/recommended-devcontainer.json
Normal file
16
.devcontainer/recommended-devcontainer.json
Normal file
@ -0,0 +1,16 @@
|
||||
// Reference: https://code.visualstudio.com/docs/remote/containers#_devcontainerjson-reference
|
||||
{
|
||||
"name": "Angular dev container",
|
||||
"dockerFile": "Dockerfile",
|
||||
"appPort": [4000, 4200, 4433, 5000, 8080, 9876],
|
||||
"postCreateCommand": "yarn install",
|
||||
"extensions": [
|
||||
"devondcarew.bazel-code",
|
||||
"gkalpak.aio-docs-utils",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||
//"angular.ng-template",
|
||||
//"dbaeumer.vscode-eslint",
|
||||
],
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
# http://editorconfig.org
|
||||
# https://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -5,5 +5,8 @@
|
||||
*.js eol=lf
|
||||
*.ts eol=lf
|
||||
|
||||
# API guardian patch must always use LF for tests to work
|
||||
*.patch eol=lf
|
||||
|
||||
# Must keep Windows line ending to be parsed correctly
|
||||
scripts/windows/packages.txt eol=crlf
|
||||
|
61
.github/ISSUE_TEMPLATE.md
vendored
61
.github/ISSUE_TEMPLATE.md
vendored
@ -1,59 +1,10 @@
|
||||
<!--
|
||||
PLEASE HELP US PROCESS GITHUB ISSUES FASTER BY PROVIDING THE FOLLOWING INFORMATION.
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION.
|
||||
-->
|
||||
Please help us process issues more efficiently by filing an
|
||||
issue using one of the following templates:
|
||||
|
||||
## I'm submitting a...
|
||||
<!-- Check one of the following options with "x" -->
|
||||
<pre><code>
|
||||
[ ] Regression (a behavior that used to work and stopped working in a new release)
|
||||
[ ] Bug report <!-- Please search GitHub for a similar issue or PR before submitting -->
|
||||
[ ] Performance issue
|
||||
[ ] Feature request
|
||||
[ ] Documentation issue or request
|
||||
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
||||
[ ] Other... Please describe:
|
||||
</code></pre>
|
||||
https://github.com/angular/angular/issues/new/choose
|
||||
|
||||
## Current behavior
|
||||
<!-- Describe how the issue manifests. -->
|
||||
Thank you!
|
||||
|
||||
|
||||
## Expected behavior
|
||||
<!-- Describe what the desired behavior would be. -->
|
||||
|
||||
|
||||
## Minimal reproduction of the problem with instructions
|
||||
<!--
|
||||
For bug reports please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
|
||||
https://stackblitz.com or similar (you can use this template as a starting point: https://stackblitz.com/fork/angular-gitter).
|
||||
-->
|
||||
|
||||
## What is the motivation / use case for changing the behavior?
|
||||
<!-- Describe the motivation or the concrete use case. -->
|
||||
|
||||
|
||||
## Environment
|
||||
|
||||
<pre><code>
|
||||
Angular version: X.Y.Z
|
||||
<!-- Check whether this is still an issue in the most recent Angular version -->
|
||||
|
||||
Browser:
|
||||
- [ ] Chrome (desktop) version XX
|
||||
- [ ] Chrome (Android) version XX
|
||||
- [ ] Chrome (iOS) version XX
|
||||
- [ ] Firefox version XX
|
||||
- [ ] Safari (desktop) version XX
|
||||
- [ ] Safari (iOS) version XX
|
||||
- [ ] IE version XX
|
||||
- [ ] Edge version XX
|
||||
|
||||
For Tooling issues:
|
||||
- Node version: XX <!-- run `node --version` -->
|
||||
- Platform: <!-- Mac, Linux, Windows -->
|
||||
|
||||
Others:
|
||||
<!-- Anything else relevant? Operating system version, IDE, package manager, HTTP server, ... -->
|
||||
</code></pre>
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
Normal file
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
name: "\U0001F41EBug report"
|
||||
about: Report a bug in the Angular Framework
|
||||
---
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Oh hi there! 😄
|
||||
|
||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
|
||||
# 🐞 bug report
|
||||
|
||||
### Affected Package
|
||||
<!-- Can you pin-point one or more @angular/* packages as the source of the bug? -->
|
||||
<!-- ✍️edit: --> The issue is caused by package @angular/....
|
||||
|
||||
|
||||
### Is this a regression?
|
||||
|
||||
<!-- Did this behavior use to work in the previous version? -->
|
||||
<!-- ✍️--> Yes, the previous version in which this bug was not present was: ....
|
||||
|
||||
|
||||
### Description
|
||||
|
||||
<!-- ✍️--> A clear and concise description of the problem...
|
||||
|
||||
|
||||
## 🔬 Minimal Reproduction
|
||||
<!--
|
||||
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
|
||||
-->
|
||||
<!-- ✍️--> https://stackblitz.com/...
|
||||
|
||||
<!--
|
||||
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
|
||||
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
|
||||
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
||||
|
||||
Issues that don't have enough info and can't be reproduced will be closed.
|
||||
|
||||
You can read more about issue submission guidelines here: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue
|
||||
-->
|
||||
|
||||
## 🔥 Exception or Error
|
||||
<pre><code>
|
||||
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
||||
<!-- ✍️-->
|
||||
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 🌍 Your Environment
|
||||
|
||||
**Angular Version:**
|
||||
<pre><code>
|
||||
<!-- run `ng version` and paste output below -->
|
||||
<!-- ✍️-->
|
||||
|
||||
</code></pre>
|
||||
|
||||
**Anything else relevant?**
|
||||
<!-- ✍️Is this a browser specific issue? If so, please specify the browser and version. -->
|
||||
|
||||
<!-- ✍️Do any of these matter: operating system, IDE, package manager, HTTP server, ...? If so, please mention it below. -->
|
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
name: "\U0001F680Feature request"
|
||||
about: Suggest a feature for Angular Framework
|
||||
|
||||
---
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Oh hi there! 😄
|
||||
|
||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
|
||||
# 🚀 feature request
|
||||
|
||||
### Relevant Package
|
||||
<!-- Can you pin-point one or more @angular/* packages the are relevant for this feature request? -->
|
||||
<!-- ✍️edit: --> This feature request is for @angular/....
|
||||
|
||||
|
||||
### Description
|
||||
<!-- ✍️--> A clear and concise description of the problem or missing capability...
|
||||
|
||||
|
||||
### Describe the solution you'd like
|
||||
<!-- ✍️--> If you have a solution in mind, please describe it.
|
||||
|
||||
|
||||
### Describe alternatives you've considered
|
||||
<!-- ✍️--> Have you considered any alternative solutions or workarounds?
|
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
Normal file
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
name: "📚 Docs or angular.io issue report"
|
||||
about: Report an issue in Angular's documentation or angular.io application
|
||||
|
||||
---
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Oh hi there! 😄
|
||||
|
||||
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
# 📚 Docs or angular.io bug report
|
||||
|
||||
### Description
|
||||
|
||||
<!-- ✍️edit:--> A clear and concise description of the problem...
|
||||
|
||||
|
||||
## 🔬 Minimal Reproduction
|
||||
|
||||
### What's the affected URL?**
|
||||
<!-- ✍️edit:--> https://angular.io/...
|
||||
|
||||
### Reproduction Steps**
|
||||
<!-- If applicable please list the steps to take to reproduce the issue -->
|
||||
<!-- ✍️edit:-->
|
||||
|
||||
### Expected vs Actual Behavior**
|
||||
<!-- If applicable please describe the difference between the expected and actual behavior after following the repro steps. -->
|
||||
<!-- ✍️edit:-->
|
||||
|
||||
|
||||
## 📷Screenshot
|
||||
<!-- Often a screenshot can help to capture the issue better than a long description. -->
|
||||
<!-- ✍️upload a screenshot:-->
|
||||
|
||||
|
||||
## 🔥 Exception or Error
|
||||
<pre><code>
|
||||
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
||||
<!-- ✍️-->
|
||||
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 🌍 Your Environment
|
||||
|
||||
### Browser info
|
||||
<!-- ✍️Is this a browser specific issue? If so, please specify the device, browser, and version. -->
|
||||
|
||||
### Anything else relevant?
|
||||
<!-- ✍️Please provide additional info if necessary. -->
|
11
.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
name: ⚠️ Security issue disclosure
|
||||
about: Report a security issue in Angular Framework, Material, or CLI
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please read https://angular.io/guide/security#report-issues on how to disclose security related issues.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
name: "❓Support request"
|
||||
about: Questions and requests for support
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please do not file questions or support requests on the GitHub issues tracker.
|
||||
|
||||
You can get your questions answered using other communication channels. Please see:
|
||||
https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
||||
|
||||
Thank you!
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
name: "\U0001F6E0️Angular CLI"
|
||||
about: Issues and feature requests for Angular CLI
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please file any Angular CLI issues at: https://github.com/angular/angular-cli/issues/new
|
||||
|
||||
For the time being, we keep Angular CLI issues in a separate repository.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
name: "\U0001F48EAngular Components"
|
||||
about: Issues and feature requests for Angular Components
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please file any Angular Components issues at: https://github.com/angular/components/issues/new
|
||||
|
||||
For the time being, we keep Angular Components issues in a separate repository.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
30
.github/PULL_REQUEST_TEMPLATE.md
vendored
30
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -10,17 +10,17 @@ Please check if your PR fulfills the following requirements:
|
||||
What kind of change does this PR introduce?
|
||||
|
||||
<!-- Please check the one that applies to this PR using "x". -->
|
||||
```
|
||||
[ ] Bugfix
|
||||
[ ] Feature
|
||||
[ ] Code style update (formatting, local variables)
|
||||
[ ] Refactoring (no functional changes, no api changes)
|
||||
[ ] Build related changes
|
||||
[ ] CI related changes
|
||||
[ ] Documentation content changes
|
||||
[ ] angular.io application / infrastructure changes
|
||||
[ ] Other... Please describe:
|
||||
```
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Feature
|
||||
- [ ] Code style update (formatting, local variables)
|
||||
- [ ] Refactoring (no functional changes, no api changes)
|
||||
- [ ] Build related changes
|
||||
- [ ] CI related changes
|
||||
- [ ] Documentation content changes
|
||||
- [ ] angular.io application / infrastructure changes
|
||||
- [ ] Other... Please describe:
|
||||
|
||||
|
||||
## What is the current behavior?
|
||||
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
||||
@ -32,10 +32,10 @@ Issue Number: N/A
|
||||
|
||||
|
||||
## Does this PR introduce a breaking change?
|
||||
```
|
||||
[ ] Yes
|
||||
[ ] No
|
||||
```
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
|
||||
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
|
||||
|
||||
|
69
.github/angular-robot.yml
vendored
69
.github/angular-robot.yml
vendored
@ -4,7 +4,7 @@
|
||||
size:
|
||||
disabled: false
|
||||
maxSizeIncrease: 2000
|
||||
circleCiStatusName: "ci/circleci: test"
|
||||
circleCiStatusName: "ci/circleci: test_ivy_aot"
|
||||
|
||||
# options for the merge plugin
|
||||
merge:
|
||||
@ -30,25 +30,47 @@ merge:
|
||||
# text to show when the status is success
|
||||
successDesc: "Does not affect google3"
|
||||
# link to use for the details
|
||||
url: "http://go/angular-g3sync"
|
||||
url: "http://go/angular/g3sync"
|
||||
# list of patterns to check for the files changed by the PR
|
||||
# this list must be manually kept in sync with google3/third_party/javascript/angular2/copy.bara.sky
|
||||
include:
|
||||
- "LICENSE"
|
||||
- "modules/**"
|
||||
- "modules/benchmarks/**"
|
||||
- "modules/system.d.ts"
|
||||
- "packages/**"
|
||||
# list of patterns to ignore for the files changed by the PR
|
||||
exclude:
|
||||
- "packages/*"
|
||||
- "packages/bazel/*"
|
||||
- "packages/bazel/src/api-extractor/**"
|
||||
- "packages/bazel/src/builders/**"
|
||||
- "packages/bazel/src/ng_package/**"
|
||||
- "packages/bazel/src/protractor/**"
|
||||
- "packages/bazel/src/schematics/**"
|
||||
- "packages/compiler-cli/ngcc/**"
|
||||
- "packages/docs/**"
|
||||
- "packages/elements/schematics/**"
|
||||
- "packages/examples/**"
|
||||
- "packages/language-service/**"
|
||||
- "packages/localize/**"
|
||||
- "packages/private/**"
|
||||
- "packages/service-worker/**"
|
||||
- "**/.gitignore"
|
||||
- "**/.gitkeep"
|
||||
- "**/yarn.lock"
|
||||
- "**/package.json"
|
||||
- "**/third_party/**"
|
||||
- "**/tsconfig-build.json"
|
||||
- "**/tsconfig.json"
|
||||
- "**/rollup.config.js"
|
||||
- "**/BUILD.bazel"
|
||||
- "**/*.md"
|
||||
- "packages/**/integrationtest/**"
|
||||
- "packages/**/test/**"
|
||||
- "packages/zone.js/*"
|
||||
- "packages/zone.js/doc/**"
|
||||
- "packages/zone.js/example/**"
|
||||
- "packages/zone.js/scripts/**"
|
||||
|
||||
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
|
||||
@ -57,13 +79,17 @@ merge:
|
||||
# label to monitor
|
||||
mergeLabel: "PR action: merge"
|
||||
|
||||
# adding any of these labels will also add the merge label
|
||||
mergeLinkedLabels:
|
||||
- "PR action: merge-assistance"
|
||||
|
||||
# list of checks that will determine if the merge label can be added
|
||||
checks:
|
||||
|
||||
# require that the PR has reviews from all requested reviewers
|
||||
#
|
||||
# This enables us to request reviews from both eng and tech writers, or multiple eng folks, and prevents accidental merges.
|
||||
# Rather than merging PRs with pending reviews, if all PullApprove requirements are satisfied and additional reviews are not needed pending reviewers should be removed via GitHub UI (this also leaves an audit trail behind these decisions).
|
||||
# Rather than merging PRs with pending reviews, if all approvals are obtained and additional reviews are not needed, any pending reviewers should be removed via GitHub UI (this also leaves an audit trail behind these decisions).
|
||||
requireReviews: true,
|
||||
|
||||
# whether the PR shouldn't have a conflict with the base branch
|
||||
@ -83,10 +109,14 @@ merge:
|
||||
|
||||
# list of PR statuses that need to be successful
|
||||
requiredStatuses:
|
||||
- "continuous-integration/travis-ci/pr"
|
||||
- "code-review/pullapprove"
|
||||
- "ci/circleci: build"
|
||||
- "ci/circleci: lint"
|
||||
- "ci/circleci: publish_snapshot"
|
||||
- "ci/angular: size"
|
||||
- "cla/google"
|
||||
- "google3"
|
||||
- "pullapprove"
|
||||
|
||||
|
||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||
@ -124,3 +154,30 @@ triage:
|
||||
-
|
||||
- "type: RFC / Discussion / question"
|
||||
- "comp: *"
|
||||
|
||||
# options for the triage PR plugin
|
||||
triagePR:
|
||||
# set to true to disable
|
||||
disabled: false
|
||||
# number of the milestone to apply when the PR has not been triaged yet
|
||||
needsTriageMilestone: 83,
|
||||
# number of the milestone to apply when the PR is triaged
|
||||
defaultMilestone: 82,
|
||||
# arrays of labels that determine if a PR has been triaged by the caretaker
|
||||
l1TriageLabels:
|
||||
-
|
||||
- "comp: *"
|
||||
# arrays of labels that determine if a PR has been fully triaged
|
||||
l2TriageLabels:
|
||||
-
|
||||
- "type: *"
|
||||
- "effort*"
|
||||
- "risk*"
|
||||
- "comp: *"
|
||||
|
||||
# options for rerunning CI
|
||||
rerunCircleCI:
|
||||
# set to true to disable
|
||||
disabled: false
|
||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
||||
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
||||
|
15
.github/workflows/lock-closed.yml
vendored
Normal file
15
.github/workflows/lock-closed.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: Lock closed inactive issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run at 16:00 every day
|
||||
- cron: '0 16 * * *'
|
||||
|
||||
jobs:
|
||||
lock_closed:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@66462f6
|
||||
with:
|
||||
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
|
24
.gitignore
vendored
24
.gitignore
vendored
@ -1,22 +1,28 @@
|
||||
.DS_STORE
|
||||
|
||||
/dist/
|
||||
bazel-*
|
||||
e2e_test.*
|
||||
/bazel-out
|
||||
/integration/bazel/bazel-*
|
||||
*.log
|
||||
node_modules
|
||||
bower_components
|
||||
tools/gulp-tasks/cldr/cldr-data/
|
||||
|
||||
# Include when developing application packages.
|
||||
pubspec.lock
|
||||
.c9
|
||||
.idea/
|
||||
.devcontainer/*
|
||||
!.devcontainer/README.md
|
||||
!.devcontainer/recommended-devcontainer.json
|
||||
!.devcontainer/recommended-Dockerfile
|
||||
.settings/
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
.vscode/tasks.json
|
||||
*.swo
|
||||
modules/.settings
|
||||
.bazelrc
|
||||
.vscode
|
||||
modules/.vscode
|
||||
.vimrc
|
||||
.nvimrc
|
||||
|
||||
# Don't check in secret files
|
||||
*secret.js
|
||||
@ -30,3 +36,9 @@ yarn-error.log
|
||||
|
||||
# rollup-test output
|
||||
/modules/rollup-test/dist/
|
||||
|
||||
# User specific bazel settings
|
||||
.bazelrc.user
|
||||
|
||||
.notes.md
|
||||
baseline.json
|
||||
|
118
.ng-dev/config.ts
Normal file
118
.ng-dev/config.ts
Normal file
@ -0,0 +1,118 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
|
||||
// The configuration for `ng-dev commit-message` commands.
|
||||
const commitMessage = {
|
||||
'maxLength': 120,
|
||||
'minBodyLength': 100,
|
||||
'minBodyLengthExcludes': ['docs'],
|
||||
'types': [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
],
|
||||
'scopes': [
|
||||
'animations',
|
||||
'bazel',
|
||||
'benchpress',
|
||||
'changelog',
|
||||
'common',
|
||||
'compiler',
|
||||
'compiler-cli',
|
||||
'core',
|
||||
'dev-infra',
|
||||
'docs-infra',
|
||||
'elements',
|
||||
'forms',
|
||||
'http',
|
||||
'language-service',
|
||||
'localize',
|
||||
'migrations',
|
||||
'ngcc',
|
||||
'packaging',
|
||||
'platform-browser',
|
||||
'platform-browser-dynamic',
|
||||
'platform-server',
|
||||
'platform-webworker',
|
||||
'platform-webworker-dynamic',
|
||||
'router',
|
||||
'service-worker',
|
||||
'upgrade',
|
||||
've',
|
||||
'zone.js',
|
||||
]
|
||||
};
|
||||
|
||||
// The configuration for `ng-dev format` commands.
|
||||
const format = {
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
]
|
||||
},
|
||||
'buildifier': true
|
||||
};
|
||||
|
||||
/** Github metadata information for `ng-dev` commands. */
|
||||
const github = {
|
||||
owner: 'angular',
|
||||
name: 'angular',
|
||||
};
|
||||
|
||||
// Configuration for the `ng-dev pr merge` command. The command can be used
|
||||
// for merging upstream pull requests into branches based on a PR target label.
|
||||
const merge = () => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
const config: MergeConfig = {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
commitMessageFixupLabel: 'commit message fixup',
|
||||
labels: [
|
||||
{
|
||||
pattern: 'PR target: master-only',
|
||||
branches: ['master'],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: patch-only',
|
||||
branches: [patch],
|
||||
},
|
||||
{
|
||||
pattern: 'PR target: master & patch',
|
||||
branches: ['master', patch],
|
||||
},
|
||||
],
|
||||
requiredBaseCommits: {
|
||||
// PRs that target either `master` or the patch branch, need to be rebased
|
||||
// on top of the latest commit message validation fix.
|
||||
// These SHAs are the commits that update the required license text in the header.
|
||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||
},
|
||||
};
|
||||
return config;
|
||||
};
|
||||
|
||||
// Export function to build ng-dev configuration object.
|
||||
module.exports = {
|
||||
commitMessage,
|
||||
format,
|
||||
github,
|
||||
merge,
|
||||
};
|
1679
.pullapprove.yml
1679
.pullapprove.yml
File diff suppressed because it is too large
Load Diff
78
.travis.yml
78
.travis.yml
@ -1,78 +0,0 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
dist: trusty
|
||||
node_js:
|
||||
- '10.9.0'
|
||||
|
||||
addons:
|
||||
# firefox: "38.0"
|
||||
apt:
|
||||
sources:
|
||||
# needed to install g++ that is used by npms's native modules
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# needed to install g++ that is used by npms's native modules
|
||||
- g++-4.8
|
||||
|
||||
branches:
|
||||
except:
|
||||
- g3
|
||||
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- ./node_modules
|
||||
- ./.chrome/chromium
|
||||
- ./aio/node_modules
|
||||
|
||||
env:
|
||||
global:
|
||||
# GITHUB_TOKEN_ANGULAR=<github token, a personal access token of the angular-builds account, account access in valentine>
|
||||
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
|
||||
- secure: "aCdHveZuY8AT4Jr1JoJB4LxZsnGWRe/KseZh1YXYe5UtufFCtTVHvUcLn0j2aLBF0KpdyS+hWf0i4np9jthKu2xPKriefoPgCMpisYeC0MFkwbmv+XlgkUbgkgVZMGiVyX7DCYXVahxIoOUjVMEDCbNiHTIrfEuyq24U3ok2tHc="
|
||||
# FIREBASE_TOKEN
|
||||
# This is needed for publishing builds to the "aio-staging" and "angular-io" firebase projects.
|
||||
# This token was generated using the aio-deploy@angular.io account using `firebase login:ci` and password from valentine
|
||||
- secure: "L5CyQmpwWtoR4Qi4xlWQh/cL1M6ZeJL4W4QAr4HdKFMgYt9h+Whqkymyh2NxwmCbPvWa7yUd+OiLQUDCY7L2VIg16hTwoe2CgYDyQA0BEwLzxtRrJXl93TfwMlrUx5JSIzAccD6D4sjtz8kSFMomK2Nls33xOXOukwyhVMjd0Cg="
|
||||
# ANGULAR_PAYLOAD_FIREBASE_TOKEN
|
||||
# This is for payload size data to "angular-payload-size" firebase project
|
||||
# This token was generated using the payload@angular.io account using `firebase login:ci` and password from valentine
|
||||
- secure: "SxotP/ymNy6uWAVbfwM9BlwETPEBpkRvU/F7fCtQDDic99WfQHzzUSQqHTk8eKk3GrGAOSL09vT0WfStQYEIGEoS5UHWNgOnelxhw+d5EnaoB8vQ0dKQBTK092hQg4feFprr+B/tCasyMV6mVwpUzZMbIJNn/Rx7H5g1bp+Gkfg="
|
||||
matrix:
|
||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
||||
- CI_MODE=e2e
|
||||
- CI_MODE=js
|
||||
- CI_MODE=saucelabs_required
|
||||
# deactivated, see #19768
|
||||
# - CI_MODE=browserstack_required
|
||||
- CI_MODE=saucelabs_optional
|
||||
- CI_MODE=browserstack_optional
|
||||
- CI_MODE=aio_tools_test
|
||||
- CI_MODE=aio
|
||||
- CI_MODE=aio_local
|
||||
- CI_MODE=aio_e2e AIO_SHARD=0
|
||||
- CI_MODE=aio_e2e AIO_SHARD=1
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: "CI_MODE=aio_local"
|
||||
- env: "CI_MODE=saucelabs_optional"
|
||||
- env: "CI_MODE=browserstack_optional"
|
||||
|
||||
before_install:
|
||||
# source the env.sh script so that the exported variables are available to other scripts later on
|
||||
- source ./scripts/ci/env.sh print
|
||||
|
||||
install:
|
||||
- ./scripts/ci/install.sh
|
||||
|
||||
script:
|
||||
- ./scripts/ci/build.sh
|
||||
- ./scripts/ci/test.sh
|
||||
# deploy is part of 'script' and not 'after_success' so that we fail the build if the deployment fails
|
||||
- ./scripts/ci/deploy.sh
|
||||
- ./scripts/ci/angular.sh
|
||||
# all the scripts under this line will not quickly abort in case ${TRAVIS_TEST_RESULT} is 1 (job failure)
|
||||
- ./scripts/ci/cleanup.sh
|
||||
- ./scripts/ci/print-logs.sh
|
25
.vscode/README.md
vendored
Normal file
25
.vscode/README.md
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# VSCode Configuration
|
||||
|
||||
This folder contains opt-in [Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings), [Tasks](https://code.visualstudio.com/docs/editor/tasks), [Launch Configurations](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations) and [Extension Recommendations](https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions) that the Angular team recommends using when working on this repository.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the recommended configurations follow the steps below:
|
||||
|
||||
- install the recommneded extensions in `.vscode/extensions.json`
|
||||
- copy (or link) `.vscode/recommended-settings.json` to `.vscode/settings.json`
|
||||
- copy (or link) `.vscode/recommended-launch.json` to `.vscode/launch.json`
|
||||
- copy (or link) `.vscode/recommended-tasks.json` to `.vscode/tasks.json`
|
||||
- restart the editor
|
||||
|
||||
If you already have your custom workspace settings you should instead manually merge the file contents.
|
||||
|
||||
This isn't an automatic process so you will need to repeat it when settings are updated.
|
||||
|
||||
To see the recommended extensions select "Extensions: Show Recommended Extensions" in the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||
|
||||
## Editing `.vscode/recommended-*.json` files
|
||||
|
||||
If you wish to add extra configuration items please keep in mind any modifications you make here will be used by many users.
|
||||
|
||||
Try to keep these settings/configuations to things that help facilitate the development process and avoid altering the user workflow whenever possible.
|
15
.vscode/extensions.json
vendored
Normal file
15
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"devondcarew.bazel-code",
|
||||
"gkalpak.aio-docs-utils",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"xaver.clang-format",
|
||||
// The following extensions are useful when working on angular.io (i.e. inside the `aio/` directory).
|
||||
//"angular.ng-template",
|
||||
//"dbaeumer.vscode-eslint",
|
||||
],
|
||||
}
|
85
.vscode/recommended-launch.json
vendored
Normal file
85
.vscode/recommended-launch.json
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach to bazel test ... --config=debug",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 9229,
|
||||
"address": "localhost",
|
||||
"restart": false,
|
||||
"sourceMaps": true,
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": "${workspaceRoot}",
|
||||
"stopOnEntry": false,
|
||||
"timeout": 600000,
|
||||
},
|
||||
{
|
||||
"name": "Attach to bazel test ... --config=debug (no source maps)",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 9229,
|
||||
"address": "localhost",
|
||||
"restart": false,
|
||||
"sourceMaps": false,
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": "${workspaceRoot}",
|
||||
"stopOnEntry": false,
|
||||
"timeout": 600000,
|
||||
},
|
||||
{
|
||||
"name": "IVY:packages/core/test/acceptance",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test/acceptance",
|
||||
"--config=debug"
|
||||
],
|
||||
"port": 9229,
|
||||
"address": "localhost",
|
||||
"restart": true,
|
||||
"sourceMaps": true,
|
||||
"timeout": 600000,
|
||||
},
|
||||
{
|
||||
"name": "IVY:packages/core/test/render3",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test/render3",
|
||||
"--config=debug"
|
||||
],
|
||||
"port": 9229,
|
||||
"address": "localhost",
|
||||
"restart": true,
|
||||
"sourceMaps": true,
|
||||
"timeout": 600000,
|
||||
},
|
||||
{
|
||||
"name": "IVY:packages/core/test",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test",
|
||||
"--config=debug"
|
||||
],
|
||||
"port": 9229,
|
||||
"address": "localhost",
|
||||
"restart": true,
|
||||
"sourceMaps": true,
|
||||
"timeout": 600000,
|
||||
},
|
||||
]
|
||||
}
|
31
.vscode/recommended-settings.json
vendored
Normal file
31
.vscode/recommended-settings.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
// Format js and ts files on save with `clang-format.executable`
|
||||
// If `clang-format.executable` is not being used, these two settings should be removed otherwise it will break existing formatting.
|
||||
// You can instead run `yarn gulp format` to manually format your code.
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
// Please install https://marketplace.visualstudio.com/items?itemName=xaver.clang-format to take advantage of `clang-format` in VSCode.
|
||||
// (See https://clang.llvm.org/docs/ClangFormat.html for more info `clang-format`.)
|
||||
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
|
||||
// Exclude third party modules and build artifacts from the editor watchers/searches.
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/bazel-out/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/aio/src/generated/**": true,
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/bower_components": true,
|
||||
"**/bazel-out": true,
|
||||
"**/dist": true,
|
||||
"**/aio/src/generated": true,
|
||||
},
|
||||
"git.ignoreLimitWarning": true,
|
||||
}
|
113
.vscode/recommended-tasks.json
vendored
Normal file
113
.vscode/recommended-tasks.json
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "IVY:packages/core/test/...",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test",
|
||||
"packages/core/test/acceptance",
|
||||
"packages/core/test/render3",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "VE:packages/core/test/...",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"packages/core/test",
|
||||
"packages/core/test/acceptance",
|
||||
"packages/core/test/render3",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "IVY:packages/core/test/acceptance",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test/acceptance",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "VE:packages/core/test/acceptance",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"packages/core/test/acceptance",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "IVY:packages/core/test",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "VE:packages/core/test",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"packages/core/test",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "IVY:packages/core/test/render3",
|
||||
"type": "shell",
|
||||
"command": "${workspaceFolder}/node_modules/.bin/bazelisk",
|
||||
"args": [
|
||||
"test",
|
||||
"--config=ivy",
|
||||
"packages/core/test/render3",
|
||||
],
|
||||
"group": "test",
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
13
.yarn/README.md
Normal file
13
.yarn/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Yarn Vendoring
|
||||
We utilize Yarn's `yarn-path` configuration in a shared `.yarnrc` file to enforce
|
||||
everyone using the same version of Yarn. Yarn checks the `.yarnrc` file to
|
||||
determine if yarn should delegate the command to a vendored version at the
|
||||
provided path.
|
||||
|
||||
## How to update
|
||||
To update to the latest version of Yarn as our vendored version:
|
||||
- Run this command
|
||||
```sh
|
||||
yarn policies set-version latest
|
||||
```
|
||||
- Remove the previous version
|
147391
.yarn/releases/yarn-1.22.4.js
vendored
Executable file
147391
.yarn/releases/yarn-1.22.4.js
vendored
Executable file
File diff suppressed because one or more lines are too long
5
.yarnrc
Normal file
5
.yarnrc
Normal file
@ -0,0 +1,5 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
yarn-path ".yarn/releases/yarn-1.22.4.js"
|
50
BUILD.bazel
50
BUILD.bazel
@ -1,45 +1,49 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "node_modules_filegroup")
|
||||
|
||||
exports_files([
|
||||
"tsconfig.json",
|
||||
"LICENSE",
|
||||
"protractor-perf.conf.js",
|
||||
"karma-js.conf.js",
|
||||
"browser-providers.conf.js",
|
||||
"scripts/ci/track-payload-size.sh",
|
||||
"scripts/ci/payload-size.sh",
|
||||
"scripts/ci/payload-size.js",
|
||||
"package.json",
|
||||
])
|
||||
|
||||
# Developers should always run `bazel run :install`
|
||||
# This ensures that package.json in subdirectories get installed as well.
|
||||
alias(
|
||||
name = "install",
|
||||
actual = "@nodejs//:yarn",
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "node_modules",
|
||||
actual = "@angular_deps//:node_modules",
|
||||
name = "tsconfig.json",
|
||||
actual = "//packages:tsconfig-build.json",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "web_test_bootstrap_scripts",
|
||||
# do not sort
|
||||
srcs = [
|
||||
"@angular_deps//:node_modules/reflect-metadata/Reflect.js",
|
||||
"@angular_deps//:node_modules/zone.js/dist/zone.js",
|
||||
"@angular_deps//:node_modules/zone.js/dist/zone-testing.js",
|
||||
"@angular_deps//:node_modules/zone.js/dist/task-tracking.js",
|
||||
"@npm//:node_modules/core-js/client/core.js",
|
||||
"//packages/zone.js/dist:zone.js",
|
||||
"//packages/zone.js/dist:zone-testing.js",
|
||||
"//packages/zone.js/dist:task-tracking.js",
|
||||
"//:test-events.js",
|
||||
"//:third_party/shims_for_IE.js",
|
||||
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
||||
"@npm//:node_modules/systemjs/dist/system.src.js",
|
||||
"@npm//:node_modules/reflect-metadata/Reflect.js",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "angularjs_scripts",
|
||||
srcs = [
|
||||
"@angular_deps//:node_modules/angular-1.5/angular.js",
|
||||
"@angular_deps//:node_modules/angular-1.6/angular.js",
|
||||
"@angular_deps//:node_modules/angular-mocks-1.5/angular-mocks.js",
|
||||
"@angular_deps//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
||||
"@angular_deps//:node_modules/angular-mocks/angular-mocks.js",
|
||||
"@angular_deps//:node_modules/angular/angular.js",
|
||||
# We also declare the unminfied AngularJS files since these can be used for
|
||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||
"@npm//:node_modules/angular/angular.js",
|
||||
"@npm//:node_modules/angular/angular.min.js",
|
||||
"@npm//:node_modules/angular-1.5/angular.js",
|
||||
"@npm//:node_modules/angular-1.5/angular.min.js",
|
||||
"@npm//:node_modules/angular-1.6/angular.js",
|
||||
"@npm//:node_modules/angular-1.6/angular.min.js",
|
||||
"@npm//:node_modules/angular-mocks/angular-mocks.js",
|
||||
"@npm//:node_modules/angular-mocks-1.5/angular-mocks.js",
|
||||
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
||||
],
|
||||
)
|
||||
|
2970
CHANGELOG.md
2970
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ Do not open issues for general support questions as we want to keep GitHub issue
|
||||
Stack Overflow is a much better place to ask questions since:
|
||||
|
||||
- there are thousands of people willing to help on Stack Overflow
|
||||
- questions and answers stay available for public viewing so your question / answer might help someone else
|
||||
- questions and answers stay available for public viewing so your question/answer might help someone else
|
||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
||||
|
||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||
@ -42,7 +42,9 @@ Please consider what kind of change it is:
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
|
||||
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
|
||||
and help you to craft the change so that it is successfully accepted into the project.
|
||||
and help you to craft the change so that it is successfully accepted into the project. **Note**:
|
||||
Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major
|
||||
feature.
|
||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
@ -51,19 +53,15 @@ and help you to craft the change so that it is successfully accepted into the pr
|
||||
|
||||
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||
|
||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co. Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like:
|
||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction. Having a minimal reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions.
|
||||
|
||||
- version of Angular used
|
||||
- 3rd-party libraries and their versions
|
||||
- and most importantly - a use-case that fails
|
||||
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
||||
|
||||
A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem. If plunker is not a suitable way to demonstrate the problem (for example for issues related to our npm packaging), please create a standalone git repository demonstrating the problem.
|
||||
We will be insisting on a minimal reproduction scenario in order to save maintainers' time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
||||
|
||||
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
|
||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
|
||||
|
||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.
|
||||
|
||||
You can file new issues by filling out our [new issue form](https://github.com/angular/angular/issues/new).
|
||||
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
||||
|
||||
|
||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||
@ -72,7 +70,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
|
||||
that relates to your submission. You don't want to duplicate effort.
|
||||
1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||
Discussing the design up front helps to ensure that we're ready to accept your work.
|
||||
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
||||
1. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without this. Make sure you sign with the primary email address of the Git identity that has been granted access to the Angular repository.
|
||||
1. Fork the angular/angular repo.
|
||||
@ -87,8 +85,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
1. Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
||||
and ensure that all tests pass.
|
||||
1. Commit your changes using a descriptive commit message that follows our
|
||||
[commit message conventions](#commit). Adherence to these conventions
|
||||
is necessary because release notes are automatically generated from these messages.
|
||||
[commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
@ -172,7 +169,7 @@ format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
|
||||
to read on GitHub as well as in various git tools.
|
||||
|
||||
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||
@ -183,19 +180,19 @@ Samples: (even more [samples](https://github.com/angular/angular/commits/master)
|
||||
docs(changelog): update changelog to beta.5
|
||||
```
|
||||
```
|
||||
fix(release): need to depend on latest rxjs and zone.js
|
||||
fix(release): need to depend on the latest rxjs and zone.js
|
||||
|
||||
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
||||
```
|
||||
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
@ -205,11 +202,13 @@ Must be one of the following:
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
### Scope
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages.
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||
|
||||
The following is the list of supported scopes:
|
||||
|
||||
* **animations**
|
||||
* **bazel**
|
||||
* **benchpress**
|
||||
* **common**
|
||||
* **compiler**
|
||||
* **compiler-cli**
|
||||
@ -218,6 +217,7 @@ The following is the list of supported scopes:
|
||||
* **forms**
|
||||
* **http**
|
||||
* **language-service**
|
||||
* **localize**
|
||||
* **platform-browser**
|
||||
* **platform-browser-dynamic**
|
||||
* **platform-server**
|
||||
@ -226,6 +226,7 @@ The following is the list of supported scopes:
|
||||
* **router**
|
||||
* **service-worker**
|
||||
* **upgrade**
|
||||
* **zone.js**
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
@ -235,6 +236,10 @@ There are currently a few exceptions to the "use package name" rule:
|
||||
* **changelog**: used for updating the release notes in CHANGELOG.md
|
||||
* **docs-infra**: used for docs-app (angular.io) related changes within the /aio directory of the
|
||||
repo
|
||||
* **dev-infra**: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
* **migrations**: used for changes to the `ng update` migrations.
|
||||
* **ngcc**: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||
* **ve**: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all
|
||||
packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a
|
||||
specific package (e.g. `docs: fix typo in tutorial`).
|
||||
@ -263,8 +268,8 @@ A detailed explanation can be found in this [document][commit-message-format].
|
||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||
|
||||
* For individuals we have a [simple click-through form][individual-cla].
|
||||
* For corporations we'll need you to
|
||||
* For individuals, we have a [simple click-through form][individual-cla].
|
||||
* For corporations, we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
<hr>
|
||||
@ -276,11 +281,10 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
||||
* https://help.github.com/articles/about-commit-email-addresses/
|
||||
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
||||
|
||||
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA, before you commit changes. If not, your PR will fail the CLA check.
|
||||
Note that if you have more than one Git identity, it is important to verify that you are logged in with the same ID with which you signed the CLA before you commit changes. If not, your PR will fail the CLA check.
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2014-2018 Google, Inc. http://angular.io
|
||||
Copyright (c) 2010-2020 Google LLC. http://angular.io/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
13
README.md
13
README.md
@ -1,31 +1,26 @@
|
||||
[](https://travis-ci.org/angular/angular)
|
||||
[](https://circleci.com/gh/angular/angular/tree/master)
|
||||
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://www.npmjs.com/@angular/core)
|
||||
|
||||
|
||||
# Angular
|
||||
|
||||
Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
|
||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||
|
||||
## Quickstart
|
||||
|
||||
[Get started in 5 minutes][quickstart].
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
[Learn about the latest improvements][changelog].
|
||||
|
||||
[Learn about the latest improvements][changelog].
|
||||
|
||||
## Want to help?
|
||||
|
||||
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
||||
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||
|
||||
[browserstack]: https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06
|
||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||
[quickstart]: https://angular.io/guide/quickstart
|
||||
[quickstart]: https://angular.io/start
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[ng]: https://angular.io
|
||||
|
210
WORKSPACE
210
WORKSPACE
@ -1,160 +1,108 @@
|
||||
workspace(name = "angular")
|
||||
workspace(
|
||||
name = "angular",
|
||||
managed_directories = {"@npm": ["node_modules"]},
|
||||
)
|
||||
|
||||
#
|
||||
# Download Bazel toolchain dependencies as needed by build actions
|
||||
#
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Fetch rules_nodejs so we can install our npm dependencies
|
||||
http_archive(
|
||||
name = "build_bazel_rules_typescript",
|
||||
sha256 = "1626ee2cc9770af6950bfc77dffa027f9aedf330fe2ea2ee7e504428927bd95d",
|
||||
strip_prefix = "rules_typescript-0.17.0",
|
||||
url = "https://github.com/bazelbuild/rules_typescript/archive/0.17.0.zip",
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
|
||||
# Check the rules_nodejs version and download npm dependencies
|
||||
# Note: bazel (version 2 and after) will check the .bazelversion file so we don't need to
|
||||
# assert on that.
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
||||
|
||||
rules_typescript_dependencies()
|
||||
|
||||
http_archive(
|
||||
name = "bazel_toolchains",
|
||||
sha256 = "c3b08805602cd1d2b67ebe96407c1e8c6ed3d4ce55236ae2efe2f1948f38168d",
|
||||
strip_prefix = "bazel-toolchains-5124557861ebf4c0b67f98180bff1f8551e0b421",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/5124557861ebf4c0b67f98180bff1f8551e0b421.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-toolchains/archive/5124557861ebf4c0b67f98180bff1f8551e0b421.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "dbe9fb97d5a7833b2a733eebc78c9c1e3880f676ac8af16e58ccf2139cbcad03",
|
||||
strip_prefix = "rules_sass-1.11.0",
|
||||
url = "https://github.com/bazelbuild/rules_sass/archive/1.11.0.zip",
|
||||
)
|
||||
|
||||
# This commit matches the version of buildifier in angular/ngcontainer
|
||||
# If you change this, also check if it matches the version in the angular/ngcontainer
|
||||
# version in /.circleci/config.yml
|
||||
BAZEL_BUILDTOOLS_VERSION = "49a6c199e3fbf5d94534b2771868677d3f9c6de9"
|
||||
|
||||
http_archive(
|
||||
name = "com_github_bazelbuild_buildtools",
|
||||
sha256 = "edf39af5fc257521e4af4c40829fffe8fba6d0ebff9f4dd69a6f8f1223ae047b",
|
||||
strip_prefix = "buildtools-%s" % BAZEL_BUILDTOOLS_VERSION,
|
||||
url = "https://github.com/bazelbuild/buildtools/archive/%s.zip" % BAZEL_BUILDTOOLS_VERSION,
|
||||
)
|
||||
|
||||
# Fetching the Bazel source code allows us to compile the Skylark linter
|
||||
http_archive(
|
||||
name = "io_bazel",
|
||||
sha256 = "ace8cced3b21e64a8fdad68508e9b0644201ec848ad583651719841d567fc66d",
|
||||
strip_prefix = "bazel-0.17.1",
|
||||
url = "https://github.com/bazelbuild/bazel/archive/0.17.1.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_skydoc",
|
||||
sha256 = "7bfb5545f59792a2745f2523b9eef363f9c3e7274791c030885e7069f8116016",
|
||||
strip_prefix = "skydoc-fe2e9f888d28e567fef62ec9d4a93c425526d701",
|
||||
# TODO: switch to upstream when https://github.com/bazelbuild/skydoc/pull/103 is merged
|
||||
url = "https://github.com/alexeagle/skydoc/archive/fe2e9f888d28e567fef62ec9d4a93c425526d701.zip",
|
||||
)
|
||||
|
||||
# We have a source dependency on the Devkit repository, because it's built with
|
||||
# Bazel.
|
||||
# This allows us to edit sources and have the effect appear immediately without
|
||||
# re-packaging or "npm link"ing.
|
||||
# Even better, things like aspects will visit the entire graph including
|
||||
# ts_library rules in the devkit repository.
|
||||
http_archive(
|
||||
name = "angular_cli",
|
||||
sha256 = "8cf320ea58c321e103f39087376feea502f20eaf79c61a4fdb05c7286c8684fd",
|
||||
strip_prefix = "angular-cli-6.1.0-rc.0",
|
||||
url = "https://github.com/angular/angular-cli/archive/v6.1.0-rc.0.zip",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "org_brotli",
|
||||
sha256 = "774b893a0700b0692a76e2e5b7e7610dbbe330ffbe3fe864b4b52ca718061d5a",
|
||||
strip_prefix = "brotli-1.0.5",
|
||||
url = "https://github.com/google/brotli/archive/v1.0.5.zip",
|
||||
)
|
||||
|
||||
#
|
||||
# Point Bazel to WORKSPACEs that live in subdirectories
|
||||
#
|
||||
|
||||
local_repository(
|
||||
name = "rxjs",
|
||||
path = "node_modules/rxjs/src",
|
||||
)
|
||||
|
||||
# Point to the integration test workspace just so that Bazel doesn't descend into it
|
||||
# when expanding the //... pattern
|
||||
local_repository(
|
||||
name = "bazel_integration_test",
|
||||
path = "integration/bazel",
|
||||
)
|
||||
|
||||
#
|
||||
# Load and install our dependencies downloaded above.
|
||||
#
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||
|
||||
check_bazel_version("0.17.0", """
|
||||
If you are on a Mac and using Homebrew, there is a breaking change to the installation in Bazel 0.16
|
||||
See https://blog.bazel.build/2018/08/22/bazel-homebrew.html
|
||||
|
||||
""")
|
||||
check_rules_nodejs_version(minimum_version_string = "1.7.0")
|
||||
|
||||
# Setup the Node.js toolchain
|
||||
node_repositories(
|
||||
node_version = "10.9.0",
|
||||
node_repositories = {
|
||||
"12.14.1-darwin_amd64": ("node-v12.14.1-darwin-x64.tar.gz", "node-v12.14.1-darwin-x64", "0be10a28737527a1e5e3784d3ad844d742fe8b0718acd701fd48f718fd3af78f"),
|
||||
"12.14.1-linux_amd64": ("node-v12.14.1-linux-x64.tar.xz", "node-v12.14.1-linux-x64", "07cfcaa0aa9d0fcb6e99725408d9e0b07be03b844701588e3ab5dbc395b98e1b"),
|
||||
"12.14.1-windows_amd64": ("node-v12.14.1-win-x64.zip", "node-v12.14.1-win-x64", "1f96ccce3ba045ecea3f458e189500adb90b8bc1a34de5d82fc10a5bf66ce7e3"),
|
||||
},
|
||||
node_version = "12.14.1",
|
||||
package_json = ["//:package.json"],
|
||||
preserve_symlinks = True,
|
||||
yarn_version = "1.9.2",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
load("//integration:angular_integration_test.bzl", "npm_package_archives")
|
||||
|
||||
go_rules_dependencies()
|
||||
yarn_install(
|
||||
name = "npm",
|
||||
manual_build_file_contents = npm_package_archives(),
|
||||
package_json = "//:package.json",
|
||||
yarn_lock = "//:yarn.lock",
|
||||
)
|
||||
|
||||
go_register_toolchains()
|
||||
# Install all bazel dependencies of the @npm npm packages
|
||||
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||
install_bazel_dependencies()
|
||||
|
||||
# Load angular dependencies
|
||||
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||
|
||||
rules_angular_dev_dependencies()
|
||||
|
||||
# Load protractor dependencies
|
||||
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||
|
||||
npm_bazel_protractor_dependencies()
|
||||
|
||||
# Load karma dependencies
|
||||
load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies")
|
||||
|
||||
npm_bazel_karma_dependencies()
|
||||
|
||||
# Setup the rules_webtesting toolchain
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
|
||||
|
||||
web_test_repositories()
|
||||
|
||||
browser_repositories(
|
||||
chromium = True,
|
||||
firefox = True,
|
||||
)
|
||||
load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories")
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
||||
browser_repositories()
|
||||
|
||||
# Setup the rules_typescript tooolchain
|
||||
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
||||
|
||||
ts_setup_workspace()
|
||||
|
||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
||||
|
||||
ng_setup_workspace()
|
||||
|
||||
##################################
|
||||
# Skylark documentation generation
|
||||
|
||||
# Setup the rules_sass toolchain
|
||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||
|
||||
sass_repositories()
|
||||
|
||||
# Setup the skydoc toolchain
|
||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||
|
||||
skydoc_repositories()
|
||||
|
||||
##################################
|
||||
# Prevent Bazel from trying to build rxjs under angular devkit
|
||||
local_repository(
|
||||
name = "rxjs_ignore_nested_1",
|
||||
path = "node_modules/@angular-devkit/core/node_modules/rxjs/src",
|
||||
)
|
||||
local_repository(
|
||||
name = "rxjs_ignore_nested_2",
|
||||
path = "node_modules/@angular-devkit/schematics/node_modules/rxjs/src",
|
||||
load("@bazel_toolchains//rules:environments.bzl", "clang_env")
|
||||
load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
|
||||
|
||||
rbe_autoconfig(
|
||||
name = "rbe_ubuntu1604_angular",
|
||||
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
||||
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
||||
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||
# https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl
|
||||
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
|
||||
# Note that if you change the `digest`, you might also need to update the
|
||||
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
||||
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
||||
# the same Clang and JDK installed. Clang is needed because of the dependency on
|
||||
# @com_google_protobuf. Java is needed for the Bazel's test executor Java tool.
|
||||
digest = "sha256:f743114235a43355bf8324e2ba0fa6a597236fe06f7bc99aaa9ac703631c306b",
|
||||
env = clang_env(),
|
||||
registry = "marketplace.gcr.io",
|
||||
# We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need
|
||||
# a specific Linux kernel that comes with "libx11" in order to run headless browser tests.
|
||||
repository = "google/rbe-ubuntu16-04-webtest",
|
||||
use_checked_in_confs = "Force",
|
||||
)
|
||||
|
12
aio/.browserslistrc
Normal file
12
aio/.browserslistrc
Normal file
@ -0,0 +1,12 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# Googlebot uses an older version of Chrome
|
||||
# For additional information see: https://developers.google.com/search/docs/guides/rendering
|
||||
|
||||
> 0.5%
|
||||
last 2 major versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
IE 11
|
5
aio/.gitignore
vendored
5
aio/.gitignore
vendored
@ -26,11 +26,13 @@
|
||||
!.vscode/extensions.json
|
||||
|
||||
# misc
|
||||
/.firebase/
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
debug.log
|
||||
firebase-debug.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
||||
@ -44,6 +46,3 @@ protractor-results*.txt
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# copied dependencies
|
||||
src/assets/js/lunr*
|
||||
|
@ -14,10 +14,12 @@ Here are the most important tasks you might need to use:
|
||||
|
||||
* `yarn` - install all the dependencies.
|
||||
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
|
||||
* `yarn setup-local` - same as `setup`, but use the locally built Angular packages for aio and docs examples boilerplate.
|
||||
* `yarn setup-local` - same as `setup`, but build the Angular packages from the source code and use these locally built versions (instead of the ones fetched from npm) for aio and docs examples boilerplate.
|
||||
|
||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
||||
* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` (pre-Ivy) mode in aio.
|
||||
(Note: To turn on `ViewEngine` mode in docs examples, see `yarn boilerplate:add:viewengine` below.)
|
||||
|
||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
||||
@ -31,28 +33,29 @@ Here are the most important tasks you might need to use:
|
||||
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
||||
* `yarn docs-test` - run the unit tests for the doc generation code.
|
||||
|
||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. Add the option `--local` to use your local version of Angular contained in the "dist" folder.
|
||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
||||
* `yarn boilerplate:add:viewengine` - same as `boilerplate:add` but also turns on `ViewEngine` (pre-Ivy) mode.
|
||||
|
||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||
|
||||
* `yarn example-e2e` - run all e2e tests for examples
|
||||
- `yarn example-e2e --setup` - force webdriver update & other setup, then run tests
|
||||
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
||||
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
||||
* `yarn example-e2e` - run all e2e tests for examples. Available options:
|
||||
- `--setup`: generate boilerplate, force webdriver update & other setup, then run tests.
|
||||
- `--local`: run e2e tests with the local version of Angular contained in the "dist" folder.
|
||||
_Requires `--setup` in order to take effect._
|
||||
- `--viewengine`: run e2e tests in `ViewEngine` (pre-Ivy) mode.
|
||||
- `--filter=foo`: limit e2e tests to those containing the word "foo".
|
||||
|
||||
* `yarn build-ie-polyfills` - generates a js file of polyfills that can be loaded in Internet Explorer.
|
||||
|
||||
## Developing on Windows
|
||||
The `packages/` directory may contain Linux-specific symlinks, which are not recognized by Windows.
|
||||
These unresolved links cause the docs generation process to fail because it cannot locate certain files.
|
||||
|
||||
> Hint: The following steps require administration rights or [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) enabled!
|
||||
|
||||
To fix this problem, run `scripts/windows/create-symlinks.sh`. This command creates temporary files where the symlinks used to be. Make sure not to commit those files with your documentation changes.
|
||||
When you are done making and testing your documentation changes, you can restore the original symlinks and delete the temporary files by running `scripts/windows/remove-symlinks.sh`.
|
||||
|
||||
It's necessary to remove the temporary files, because otherwise they're displayed as local changes in your git working copy and certain operations are blocked.
|
||||
> **Note for Windows users**
|
||||
>
|
||||
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
|
||||
>
|
||||
> The affected commands are:
|
||||
> - `yarn setup` / `yarn setup-*`
|
||||
> - `yarn build` / `yarn build-*`
|
||||
> - `yarn boilerplate:add`
|
||||
> - `yarn example-e2e --setup`
|
||||
|
||||
## Using ServiceWorker locally
|
||||
|
||||
@ -101,7 +104,7 @@ You also want to see those changes displayed properly in the doc viewer
|
||||
with a quick, edit/view cycle time.
|
||||
|
||||
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
|
||||
re-processes the the files necessary to generate the docs that are related to the file that has changed.
|
||||
re-processes the files necessary to generate the docs that are related to the file that has changed.
|
||||
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
|
||||
fidelity content. For example, links to other docs and code examples may not render correctly. This is
|
||||
most particularly noticed in links to other docs and in the embedded examples, which may not always render
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Image metadata and config
|
||||
FROM debian:jessie
|
||||
FROM debian:buster
|
||||
|
||||
LABEL name="angular.io PR preview" \
|
||||
description="This image implements the PR preview functionality for angular.io." \
|
||||
@ -26,8 +26,8 @@ ARG AIO_GITHUB_ORGANIZATION=angular
|
||||
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
||||
ARG AIO_GITHUB_REPO=angular
|
||||
ARG TEST_AIO_GITHUB_REPO=test-repo
|
||||
ARG AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
||||
ARG AIO_GITHUB_TEAM_SLUGS=aio-auto-previews,aio-contributors
|
||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=test-team-1,test-team-2
|
||||
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
||||
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
||||
ARG AIO_NGINX_PORT_HTTP=80
|
||||
@ -37,10 +37,10 @@ ARG TEST_AIO_NGINX_PORT_HTTPS=4433
|
||||
ARG AIO_SIGNIFICANT_FILES_PATTERN='^(?:aio|packages)/(?!.*[._]spec\\.[jt]s$)'
|
||||
ARG TEST_AIO_SIGNIFICANT_FILES_PATTERN=$AIO_SIGNIFICANT_FILES_PATTERN
|
||||
ARG AIO_TRUSTED_PR_LABEL="aio: preview"
|
||||
ARG TEST_AIO_TRUSTED_PR_LABEL="aio: preview"
|
||||
ARG TEST_AIO_TRUSTED_PR_LABEL=$AIO_TRUSTED_PR_LABEL
|
||||
ARG AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
|
||||
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=preview.localhost
|
||||
ARG AIO_ARTIFACT_MAX_SIZE=20971520
|
||||
ARG TEST_AIO_PREVIEW_SERVER_HOSTNAME=$AIO_PREVIEW_SERVER_HOSTNAME
|
||||
ARG AIO_ARTIFACT_MAX_SIZE=26214400
|
||||
ARG TEST_AIO_ARTIFACT_MAX_SIZE=200
|
||||
ARG AIO_PREVIEW_SERVER_PORT=3000
|
||||
ARG TEST_AIO_PREVIEW_SERVER_PORT=3001
|
||||
@ -72,25 +72,29 @@ RUN mkdir /var/log/aio
|
||||
|
||||
|
||||
# Add extra package sources
|
||||
RUN apt-get update -y && apt-get install -y curl
|
||||
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_10.x | bash -
|
||||
RUN apt-get update -y && apt-get install -y curl=7.64.0-4+deb10u1
|
||||
RUN curl --silent --show-error --location https://deb.nodesource.com/setup_12.x | bash -
|
||||
RUN curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||
RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/backports.list
|
||||
|
||||
|
||||
# Install packages
|
||||
# NOTE: Some packages (such as `nginx`, `nodejs`, `openssl`) make older versions unavailable on the
|
||||
# repositories, so we cannot pin to specific versions for these packages :(
|
||||
# See for example:
|
||||
# - https://github.com/nodesource/distributions/issues/33
|
||||
# - https://askubuntu.com/questions/715104/how-can-i-downgrade-openssl-via-apt-get
|
||||
RUN apt-get update -y && apt-get install -y \
|
||||
chkconfig \
|
||||
cron \
|
||||
dnsmasq \
|
||||
nano \
|
||||
cron=3.0pl1-134+deb10u1 \
|
||||
dnsmasq=2.80-1 \
|
||||
nano=3.2-3 \
|
||||
nginx \
|
||||
nodejs \
|
||||
openssl \
|
||||
rsyslog \
|
||||
yarn
|
||||
RUN apt-get install -t jessie-backports -y nginx
|
||||
RUN yarn global add pm2@2
|
||||
rsyslog=8.1901.0-1 \
|
||||
vim=2:8.1.0875-5 \
|
||||
yarn=1.22.4-1
|
||||
RUN yarn global add pm2@4.4.0
|
||||
|
||||
|
||||
# Set up log rotation
|
||||
@ -151,8 +155,7 @@ RUN sed -i "s|{{\$AIO_PREVIEW_SERVER_PORT}}|$TEST_AIO_PREVIEW_SERVER_PORT|g" /et
|
||||
|
||||
|
||||
# Set up pm2
|
||||
RUN pm2 startup systemv -u root > /dev/null
|
||||
RUN chkconfig pm2-root on
|
||||
RUN pm2 startup --user root > /dev/null
|
||||
|
||||
|
||||
# Set up the shell scripts
|
||||
@ -164,8 +167,7 @@ RUN find $AIO_SCRIPTS_SH_DIR -maxdepth 1 -type f -printf "%P\n" \
|
||||
|
||||
# Set up the Node.js scripts
|
||||
COPY scripts-js/ $AIO_SCRIPTS_JS_DIR/
|
||||
WORKDIR $AIO_SCRIPTS_JS_DIR/
|
||||
RUN yarn install --production --frozen-lockfile
|
||||
RUN yarn --cwd="$AIO_SCRIPTS_JS_DIR/" install --production --frozen-lockfile
|
||||
|
||||
|
||||
# Set up health check
|
||||
|
@ -35,6 +35,7 @@ export class BuildCleaner {
|
||||
]);
|
||||
} catch (error) {
|
||||
this.logger.error('ERROR:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import {CircleCiApi} from '../common/circle-ci-api';
|
||||
import {GithubApi} from '../common/github-api';
|
||||
import {GithubPullRequests} from '../common/github-pull-requests';
|
||||
import {GithubTeams} from '../common/github-teams';
|
||||
import {assert, assertNotMissingOrEmpty, Logger} from '../common/utils';
|
||||
import {assert, assertNotMissingOrEmpty, computeShortSha, Logger} from '../common/utils';
|
||||
import {BuildCreator} from './build-creator';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from './build-events';
|
||||
import {BuildRetriever} from './build-retriever';
|
||||
@ -144,7 +144,10 @@ export class PreviewServerFactory {
|
||||
const artifactPath = await buildRetriever.downloadBuildArtifact(buildNum, pr, sha, cfg.buildArtifactPath);
|
||||
const isPublic = await buildVerifier.getPrIsTrusted(pr);
|
||||
await buildCreator.create(pr, sha, artifactPath, isPublic);
|
||||
|
||||
res.sendStatus(isPublic ? 201 : 202);
|
||||
logger.log(`PR:${pr}, SHA:${computeShortSha(sha)}, Build:${buildNum} - ` +
|
||||
`Successfully created ${isPublic ? 'public' : 'non-public'} preview.`);
|
||||
} catch (err) {
|
||||
logger.error('CircleCI webhook error', err);
|
||||
respondWithError(res, err);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as express from 'express';
|
||||
import {promisify} from 'util';
|
||||
import {PreviewServerError} from './preview-error';
|
||||
|
||||
/**
|
||||
@ -13,7 +12,7 @@ export async function respondWithError(res: express.Response, err: any): Promise
|
||||
}
|
||||
|
||||
res.status(err.status);
|
||||
await promisify(res.end.bind(res))(err.message);
|
||||
return new Promise(resolve => res.end(err.message, resolve));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Imports
|
||||
import * as cp from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import * as http from 'http';
|
||||
import * as path from 'path';
|
||||
import * as shell from 'shelljs';
|
||||
import {AIO_DOWNLOADS_DIR, HIDDEN_DIR_PREFIX} from '../common/constants';
|
||||
@ -94,7 +93,7 @@ class Helper {
|
||||
return fs.readFileSync(absFilePath, 'utf8');
|
||||
}
|
||||
|
||||
public runCmd(cmd: string, opts: cp.ExecFileOptions = {}): Promise<CmdResult> {
|
||||
public runCmd(cmd: string, opts: cp.ExecOptions = {}): Promise<CmdResult> {
|
||||
return new Promise(resolve => {
|
||||
const proc = cp.exec(cmd, opts, (err, stdout, stderr) => resolve({success: !err, err, stdout, stderr}));
|
||||
this.createCleanUpFn(() => proc.kill());
|
||||
@ -102,21 +101,10 @@ class Helper {
|
||||
}
|
||||
|
||||
public runForAllSupportedSchemes(suiteFactory: TestSuiteFactory): void {
|
||||
Object.keys(this.portPerScheme).forEach(scheme => suiteFactory(scheme, this.portPerScheme[scheme]));
|
||||
Object.entries(this.portPerScheme).forEach(([scheme, port]) => suiteFactory(scheme, port));
|
||||
}
|
||||
|
||||
public verifyResponse(status: number | [number, string], regex: string | RegExp = /^/): VerifyCmdResultFn {
|
||||
let statusCode: number;
|
||||
let statusText: string;
|
||||
|
||||
if (Array.isArray(status)) {
|
||||
statusCode = status[0];
|
||||
statusText = status[1];
|
||||
} else {
|
||||
statusCode = status;
|
||||
statusText = http.STATUS_CODES[statusCode] || 'UNKNOWN_STATUS_CODE';
|
||||
}
|
||||
|
||||
public verifyResponse(status: number, regex: string | RegExp = /^/): VerifyCmdResultFn {
|
||||
return (result: CmdResult) => {
|
||||
const [headers, body] = result.stdout.
|
||||
split(/(?:\r?\n){2,}/).
|
||||
@ -131,7 +119,7 @@ class Helper {
|
||||
}
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(headers).toContain(`${statusCode} ${statusText}`);
|
||||
expect(headers).toMatch(new RegExp(`HTTP/(?:1\\.1|2) ${status} `));
|
||||
expect(body).toMatch(regex);
|
||||
};
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ describe(`nginx`, () => {
|
||||
afterEach(() => h.cleanUp());
|
||||
|
||||
|
||||
it('should redirect HTTP to HTTPS', done => {
|
||||
it('should redirect HTTP to HTTPS', async () => {
|
||||
const httpHost = `${AIO_NGINX_HOSTNAME}:${AIO_NGINX_PORT_HTTP}`;
|
||||
const httpsHost = `${AIO_NGINX_HOSTNAME}:${AIO_NGINX_PORT_HTTPS}`;
|
||||
const urlMap = {
|
||||
@ -24,16 +24,15 @@ describe(`nginx`, () => {
|
||||
[`http://foo.${httpHost}/`]: `https://foo.${httpsHost}/`,
|
||||
};
|
||||
|
||||
const verifyRedirection = (httpUrl: string) => h.runCmd(`curl -i ${httpUrl}`).then(result => {
|
||||
const verifyRedirection = async (fromUrl: string, toUrl: string) => {
|
||||
const result = await h.runCmd(`curl -i ${fromUrl}`);
|
||||
h.verifyResponse(307)(result);
|
||||
|
||||
const headers = result.stdout.split(/(?:\r?\n){2,}/)[0];
|
||||
expect(headers).toContain(`Location: ${urlMap[httpUrl]}`);
|
||||
});
|
||||
expect(headers).toContain(`Location: ${toUrl}`);
|
||||
};
|
||||
|
||||
Promise.
|
||||
all(Object.keys(urlMap).map(verifyRedirection)).
|
||||
then(done);
|
||||
await Promise.all(Object.entries(urlMap).map(urls => verifyRedirection(...urls)));
|
||||
});
|
||||
|
||||
|
||||
@ -62,15 +61,15 @@ describe(`nginx`, () => {
|
||||
});
|
||||
|
||||
|
||||
it('should return /index.html', done => {
|
||||
it('should return /index.html', async () => {
|
||||
const origin = `${scheme}://pr${pr}-${shortSha9}.${host}`;
|
||||
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${origin}/index.html`).then(h.verifyResponse(200, bodyRegex)),
|
||||
h.runCmd(`curl -iL ${origin}/`).then(h.verifyResponse(200, bodyRegex)),
|
||||
h.runCmd(`curl -iL ${origin}`).then(h.verifyResponse(200, bodyRegex)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@ -90,12 +89,11 @@ describe(`nginx`, () => {
|
||||
});
|
||||
|
||||
|
||||
it('should return /foo/bar.js', done => {
|
||||
it('should return /foo/bar.js', async () => {
|
||||
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /foo/bar\\.js$`);
|
||||
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/bar.js`).
|
||||
then(h.verifyResponse(200, bodyRegex)).
|
||||
then(done);
|
||||
await h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/bar.js`).
|
||||
then(h.verifyResponse(200, bodyRegex));
|
||||
});
|
||||
|
||||
|
||||
@ -111,47 +109,46 @@ describe(`nginx`, () => {
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 403 for directories', done => {
|
||||
Promise.all([
|
||||
it('should respond with 403 for directories', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/`).then(h.verifyResponse(403)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo`).then(h.verifyResponse(403)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 for unknown paths to files', done => {
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/baz.css`).
|
||||
then(h.verifyResponse(404)).
|
||||
then(done);
|
||||
it('should respond with 404 for unknown paths to files', async () => {
|
||||
await h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}/foo/baz.css`).
|
||||
then(h.verifyResponse(404));
|
||||
});
|
||||
|
||||
|
||||
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', done => {
|
||||
it('should rewrite to \'index.html\' for unknown paths that don\'t look like files', async () => {
|
||||
const origin = `${scheme}://pr${pr}-${shortSha9}.${host}`;
|
||||
const bodyRegex = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${origin}/foo/baz`).then(h.verifyResponse(200, bodyRegex)),
|
||||
h.runCmd(`curl -iL ${origin}/foo/baz/`).then(h.verifyResponse(200, bodyRegex)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 for unknown PRs/SHAs', done => {
|
||||
it('should respond with 404 for unknown PRs/SHAs', async () => {
|
||||
const otherPr = 54321;
|
||||
const otherShortSha = computeShortSha('8'.repeat(40));
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}9-${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${otherPr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}9.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${otherShortSha}.${host}`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 if the subdomain format is wrong', done => {
|
||||
Promise.all([
|
||||
it('should respond with 404 if the subdomain format is wrong', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${scheme}://xpr${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://prx${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://xx${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
@ -160,26 +157,25 @@ describe(`nginx`, () => {
|
||||
h.runCmd(`curl -iL ${scheme}://${pr}-${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}_${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should reject PRs with leading zeros', done => {
|
||||
h.runCmd(`curl -iL ${scheme}://pr0${pr}-${shortSha9}.${host}`).
|
||||
then(h.verifyResponse(404)).
|
||||
then(done);
|
||||
it('should reject PRs with leading zeros', async () => {
|
||||
await h.runCmd(`curl -iL ${scheme}://pr0${pr}-${shortSha9}.${host}`).
|
||||
then(h.verifyResponse(404));
|
||||
});
|
||||
|
||||
|
||||
it('should accept SHAs with leading zeros (but not trim the zeros)', done => {
|
||||
it('should accept SHAs with leading zeros (but not trim the zeros)', async () => {
|
||||
const bodyRegex9 = new RegExp(`^PR: ${pr} | SHA: ${sha9} | File: /index\\.html$`);
|
||||
const bodyRegex0 = new RegExp(`^PR: ${pr} | SHA: ${sha0} | File: /index\\.html$`);
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-0${shortSha9}.${host}`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha9}.${host}`).then(h.verifyResponse(200, bodyRegex9)),
|
||||
h.runCmd(`curl -iL ${scheme}://pr${pr}-${shortSha0}.${host}`).then(h.verifyResponse(200, bodyRegex0)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -231,23 +227,23 @@ describe(`nginx`, () => {
|
||||
|
||||
describe(`${host}/health-check`, () => {
|
||||
|
||||
it('should respond with 200', done => {
|
||||
Promise.all([
|
||||
it('should respond with 200', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/health-check`).then(h.verifyResponse(200)),
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/health-check/`).then(h.verifyResponse(200)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 if the path does not match exactly', done => {
|
||||
Promise.all([
|
||||
it('should respond with 404 if the path does not match exactly', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/health-check/foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/health-check-foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/health-checknfoo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/foo/health-check`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/foo-health-check`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${scheme}://${host}/foonhealth-check`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -259,10 +255,10 @@ describe(`nginx`, () => {
|
||||
|
||||
it('should disallow non-GET requests', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iLX POST ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX PUT ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX PATCH ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX DELETE ${baseUrl}/42`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX POST ${baseUrl}/42`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX PUT ${baseUrl}/42`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX PATCH ${baseUrl}/42`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX DELETE ${baseUrl}/42`).then(h.verifyResponse(405)),
|
||||
]);
|
||||
});
|
||||
|
||||
@ -291,29 +287,28 @@ describe(`nginx`, () => {
|
||||
|
||||
describe(`${host}/circle-build`, () => {
|
||||
|
||||
it('should disallow non-POST requests', done => {
|
||||
it('should disallow non-POST requests', async () => {
|
||||
const url = `${scheme}://${host}/circle-build`;
|
||||
|
||||
Promise.all([
|
||||
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
]).then(done);
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should pass requests through to the preview server', done => {
|
||||
h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
|
||||
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/)).
|
||||
then(done);
|
||||
it('should pass requests through to the preview server', async () => {
|
||||
await h.runCmd(`curl -iLX POST ${scheme}://${host}/circle-build`).
|
||||
then(h.verifyResponse(400, /Incorrect body content. Expected JSON/));
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 for unknown paths', done => {
|
||||
it('should respond with 404 for unknown paths', async () => {
|
||||
const cmdPrefix = `curl -iLX POST ${scheme}://${host}`;
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`${cmdPrefix}/foo/circle-build/`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/foo-circle-build/`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/fooncircle-build/`).then(h.verifyResponse(404)),
|
||||
@ -322,7 +317,7 @@ describe(`nginx`, () => {
|
||||
h.runCmd(`${cmdPrefix}/circle-buildnfoo/`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/circle-build/pr`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/circle-build/42`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -332,38 +327,33 @@ describe(`nginx`, () => {
|
||||
const url = `${scheme}://${host}/pr-updated`;
|
||||
|
||||
|
||||
it('should disallow non-POST requests', done => {
|
||||
Promise.all([
|
||||
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse([405, 'Not Allowed'])),
|
||||
]).then(done);
|
||||
it('should disallow non-POST requests', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iLX GET ${url}`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX PUT ${url}`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX PATCH ${url}`).then(h.verifyResponse(405)),
|
||||
h.runCmd(`curl -iLX DELETE ${url}`).then(h.verifyResponse(405)),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should pass requests through to the preview server', done => {
|
||||
const cmdPrefix = `curl -iLX POST --header "Content-Type: application/json"`;
|
||||
|
||||
const cmd1 = `${cmdPrefix} ${url}`;
|
||||
|
||||
Promise.all([
|
||||
h.runCmd(cmd1).then(h.verifyResponse(400, /Missing or empty 'number' field/)),
|
||||
]).then(done);
|
||||
it('should pass requests through to the preview server', async () => {
|
||||
await h.runCmd(`curl -iLX POST --header "Content-Type: application/json" ${url}`).
|
||||
then(h.verifyResponse(400, /Missing or empty 'number' field/));
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 for unknown paths', done => {
|
||||
it('should respond with 404 for unknown paths', async () => {
|
||||
const cmdPrefix = `curl -iLX POST ${scheme}://${host}`;
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`${cmdPrefix}/foo/pr-updated`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/foo-pr-updated`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/foonpr-updated`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/pr-updated/foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/pr-updated-foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/pr-updatednfoo`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -374,7 +364,7 @@ describe(`nginx`, () => {
|
||||
beforeEach(() => {
|
||||
['index.html', 'foo.js', 'foo/index.html'].forEach(relFilePath => {
|
||||
const absFilePath = path.join(AIO_BUILDS_DIR, relFilePath);
|
||||
return h.writeFile(absFilePath, {content: `File: /${relFilePath}`});
|
||||
h.writeFile(absFilePath, {content: `File: /${relFilePath}`});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -105,9 +105,9 @@ describe('preview-server', () => {
|
||||
|
||||
|
||||
describe(`${host}/circle-build`, () => {
|
||||
|
||||
const curl = makeCurl(`${host}/circle-build`);
|
||||
|
||||
|
||||
it('should disallow non-POST requests', async () => {
|
||||
const bodyRegex = /^Unknown resource/;
|
||||
|
||||
@ -189,8 +189,7 @@ describe('preview-server', () => {
|
||||
});
|
||||
|
||||
it('should respond with 201 if a new public build is created', async () => {
|
||||
await curl(payload(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER))
|
||||
.then(h.verifyResponse(201));
|
||||
await curl(payload(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).then(h.verifyResponse(201));
|
||||
expect({ prNum: PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER }).toExistAsABuild();
|
||||
});
|
||||
|
||||
@ -199,7 +198,7 @@ describe('preview-server', () => {
|
||||
expect({ prNum: PrNums.TRUST_CHECK_UNTRUSTED, isPublic: false }).toExistAsABuild();
|
||||
});
|
||||
|
||||
[true].forEach(isPublic => {
|
||||
[true, false].forEach(isPublic => {
|
||||
const build = isPublic ? BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER : BuildNums.TRUST_CHECK_UNTRUSTED;
|
||||
const prNum = isPublic ? PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER : PrNums.TRUST_CHECK_UNTRUSTED;
|
||||
const label = isPublic ? 'public' : 'non-public';
|
||||
@ -364,23 +363,23 @@ describe('preview-server', () => {
|
||||
|
||||
describe(`${host}/health-check`, () => {
|
||||
|
||||
it('should respond with 200', done => {
|
||||
Promise.all([
|
||||
it('should respond with 200', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${host}/health-check`).then(h.verifyResponse(200)),
|
||||
h.runCmd(`curl -iL ${host}/health-check/`).then(h.verifyResponse(200)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 if the path does not match exactly', done => {
|
||||
Promise.all([
|
||||
it('should respond with 404 if the path does not match exactly', async () => {
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${host}/health-check/foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${host}/health-check-foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${host}/health-checknfoo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${host}/foo/health-check`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${host}/foo-health-check`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`curl -iL ${host}/foonhealth-check`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -426,18 +425,18 @@ describe('preview-server', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should respond with 404 for unknown paths', done => {
|
||||
it('should respond with 404 for unknown paths', async () => {
|
||||
const mockPayload = JSON.stringify({number: 1}); // MockExternalApiFlags.TRUST_CHECK_ACTIVE_TRUSTED_USER });
|
||||
const cmdPrefix = `curl -iLX POST --data "${mockPayload}" ${host}`;
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`${cmdPrefix}/foo/pr-updated`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/foo-pr-updated`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/foonpr-updated`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/pr-updated/foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/pr-updated-foo`).then(h.verifyResponse(404)),
|
||||
h.runCmd(`${cmdPrefix}/pr-updatednfoo`).then(h.verifyResponse(404)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@ -551,10 +550,10 @@ describe('preview-server', () => {
|
||||
|
||||
describe(`${host}/*`, () => {
|
||||
|
||||
it('should respond with 404 for requests to unknown URLs', done => {
|
||||
it('should respond with 404 for requests to unknown URLs', async () => {
|
||||
const bodyRegex = /^Unknown resource/;
|
||||
|
||||
Promise.all([
|
||||
await Promise.all([
|
||||
h.runCmd(`curl -iL ${host}/index.html`).then(h.verifyResponse(404, bodyRegex)),
|
||||
h.runCmd(`curl -iL ${host}/`).then(h.verifyResponse(404, bodyRegex)),
|
||||
h.runCmd(`curl -iL ${host}`).then(h.verifyResponse(404, bodyRegex)),
|
||||
@ -562,7 +561,7 @@ describe('preview-server', () => {
|
||||
h.runCmd(`curl -iLX POST ${host}`).then(h.verifyResponse(404, bodyRegex)),
|
||||
h.runCmd(`curl -iLX PATCH ${host}`).then(h.verifyResponse(404, bodyRegex)),
|
||||
h.runCmd(`curl -iLX DELETE ${host}`).then(h.verifyResponse(404, bodyRegex)),
|
||||
]).then(done);
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -14,42 +14,41 @@
|
||||
"predev": "yarn build || true",
|
||||
"dev": "run-p ~~build-watch ~~test-watch",
|
||||
"lint": "tslint --project tsconfig.json",
|
||||
"pretest": "yarn build",
|
||||
"pretest": "run-s build lint",
|
||||
"test": "yarn ~~test-only",
|
||||
"pretest-watch": "yarn pretest",
|
||||
"test-watch": "yarn ~~test-watch",
|
||||
"~~build": "tsc",
|
||||
"~~build-watch": "yarn ~~build --watch",
|
||||
"pre~~test-only": "yarn lint",
|
||||
"~~test-only": "node dist/test",
|
||||
"~~test-watch": "nodemon --delay 1 --exec \"yarn ~~test-only\" --watch dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.18.3",
|
||||
"delete-empty": "^2.0.0",
|
||||
"express": "^4.16.3",
|
||||
"jasmine": "^3.2.0",
|
||||
"nock": "^9.6.1",
|
||||
"node-fetch": "^2.2.0",
|
||||
"shelljs": "^0.8.2",
|
||||
"source-map-support": "^0.5.9",
|
||||
"tar-stream": "^1.6.1",
|
||||
"tslib": "^1.9.3"
|
||||
"body-parser": "^1.19.0",
|
||||
"delete-empty": "^3.0.0",
|
||||
"express": "^4.17.1",
|
||||
"jasmine": "^3.5.0",
|
||||
"nock": "^12.0.3",
|
||||
"node-fetch": "^2.6.0",
|
||||
"shelljs": "^0.8.4",
|
||||
"source-map-support": "^0.5.19",
|
||||
"tar-stream": "^2.1.2",
|
||||
"tslib": "^1.11.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/body-parser": "^1.17.0",
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/jasmine": "^2.8.8",
|
||||
"@types/nock": "^9.3.0",
|
||||
"@types/node": "^10.9.2",
|
||||
"@types/node-fetch": "^2.1.2",
|
||||
"@types/shelljs": "^0.8.0",
|
||||
"@types/supertest": "^2.0.5",
|
||||
"nodemon": "^1.18.3",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"supertest": "^3.1.0",
|
||||
"tslint": "^5.11.0",
|
||||
"@types/body-parser": "^1.19.0",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jasmine": "^3.5.10",
|
||||
"@types/nock": "^11.1.0",
|
||||
"@types/node": "^13.13.2",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/shelljs": "^0.8.7",
|
||||
"@types/supertest": "^2.0.8",
|
||||
"nodemon": "^2.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"supertest": "^4.0.2",
|
||||
"tslint": "^6.1.1",
|
||||
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
||||
"typescript": "^3.0.1"
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ const EXISTING_DOWNLOADS = [
|
||||
'20-1234567-build.zip',
|
||||
];
|
||||
const OPEN_PRS = [10, 40];
|
||||
const ANY_DATE = jasmine.any(String);
|
||||
|
||||
// Tests
|
||||
describe('BuildCleaner', () => {
|
||||
@ -77,22 +76,18 @@ describe('BuildCleaner', () => {
|
||||
let cleanerRemoveUnnecessaryDownloadsSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
cleanerGetExistingBuildNumbersSpy = spyOn(cleaner, 'getExistingBuildNumbers')
|
||||
.and.callFake(() => Promise.resolve(EXISTING_BUILDS));
|
||||
cleanerGetOpenPrNumbersSpy = spyOn(cleaner, 'getOpenPrNumbers')
|
||||
.and.callFake(() => Promise.resolve(OPEN_PRS));
|
||||
cleanerGetExistingDownloadsSpy = spyOn(cleaner, 'getExistingDownloads')
|
||||
.and.callFake(() => Promise.resolve(EXISTING_DOWNLOADS));
|
||||
cleanerGetExistingBuildNumbersSpy = spyOn(cleaner, 'getExistingBuildNumbers').and.resolveTo(EXISTING_BUILDS);
|
||||
cleanerGetOpenPrNumbersSpy = spyOn(cleaner, 'getOpenPrNumbers').and.resolveTo(OPEN_PRS);
|
||||
cleanerGetExistingDownloadsSpy = spyOn(cleaner, 'getExistingDownloads').and.resolveTo(EXISTING_DOWNLOADS);
|
||||
|
||||
cleanerRemoveUnnecessaryBuildsSpy = spyOn(cleaner, 'removeUnnecessaryBuilds');
|
||||
cleanerRemoveUnnecessaryDownloadsSpy = spyOn(cleaner, 'removeUnnecessaryDownloads');
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', async () => {
|
||||
const promise = cleaner.cleanUp();
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
|
||||
// Do not complete the test and release the spies synchronously, to avoid running the actual implementations.
|
||||
await promise;
|
||||
@ -130,52 +125,32 @@ describe('BuildCleaner', () => {
|
||||
|
||||
|
||||
it('should reject if \'getOpenPrNumbers()\' rejects', async () => {
|
||||
try {
|
||||
cleanerGetOpenPrNumbersSpy.and.callFake(() => Promise.reject('Test'));
|
||||
await cleaner.cleanUp();
|
||||
} catch (err) {
|
||||
expect(err).toBe('Test');
|
||||
}
|
||||
cleanerGetOpenPrNumbersSpy.and.rejectWith('Test');
|
||||
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should reject if \'getExistingBuildNumbers()\' rejects', async () => {
|
||||
try {
|
||||
cleanerGetExistingBuildNumbersSpy.and.callFake(() => Promise.reject('Test'));
|
||||
await cleaner.cleanUp();
|
||||
} catch (err) {
|
||||
expect(err).toBe('Test');
|
||||
}
|
||||
cleanerGetExistingBuildNumbersSpy.and.rejectWith('Test');
|
||||
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should reject if \'getExistingDownloads()\' rejects', async () => {
|
||||
try {
|
||||
cleanerGetExistingDownloadsSpy.and.callFake(() => Promise.reject('Test'));
|
||||
await cleaner.cleanUp();
|
||||
} catch (err) {
|
||||
expect(err).toBe('Test');
|
||||
}
|
||||
cleanerGetExistingDownloadsSpy.and.rejectWith('Test');
|
||||
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should reject if \'removeUnnecessaryBuilds()\' rejects', async () => {
|
||||
try {
|
||||
cleanerRemoveUnnecessaryBuildsSpy.and.callFake(() => Promise.reject('Test'));
|
||||
await cleaner.cleanUp();
|
||||
} catch (err) {
|
||||
expect(err).toBe('Test');
|
||||
}
|
||||
cleanerRemoveUnnecessaryBuildsSpy.and.rejectWith('Test');
|
||||
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should reject if \'removeUnnecessaryDownloads()\' rejects', async () => {
|
||||
try {
|
||||
cleanerRemoveUnnecessaryDownloadsSpy.and.callFake(() => Promise.reject('Test'));
|
||||
await cleaner.cleanUp();
|
||||
} catch (err) {
|
||||
expect(err).toBe('Test');
|
||||
}
|
||||
cleanerRemoveUnnecessaryDownloadsSpy.and.rejectWith('Test');
|
||||
await expectAsync(cleaner.cleanUp()).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
});
|
||||
@ -187,13 +162,15 @@ describe('BuildCleaner', () => {
|
||||
let promise: Promise<number[]>;
|
||||
|
||||
beforeEach(() => {
|
||||
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake((_: string, cb: typeof readdirCb) => readdirCb = cb);
|
||||
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake(
|
||||
((_: string, cb: typeof readdirCb) => readdirCb = cb) as unknown as typeof fs.readdir,
|
||||
);
|
||||
promise = cleaner.getExistingBuildNumbers();
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -203,43 +180,27 @@ describe('BuildCleaner', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject if an error occurs while getting the files', done => {
|
||||
promise.catch(err => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should reject if an error occurs while getting the files', async () => {
|
||||
readdirCb('Test');
|
||||
await expectAsync(promise).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the returned files (as numbers)', done => {
|
||||
promise.then(result => {
|
||||
expect(result).toEqual([12, 34, 56]);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should resolve with the returned files (as numbers)', async () => {
|
||||
readdirCb(null, ['12', '34', '56']);
|
||||
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
|
||||
});
|
||||
|
||||
|
||||
it('should remove `HIDDEN_DIR_PREFIX` from the filenames', done => {
|
||||
promise.then(result => {
|
||||
expect(result).toEqual([12, 34, 56]);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should remove `HIDDEN_DIR_PREFIX` from the filenames', async () => {
|
||||
readdirCb(null, [`${HIDDEN_DIR_PREFIX}12`, '34', `${HIDDEN_DIR_PREFIX}56`]);
|
||||
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
|
||||
});
|
||||
|
||||
|
||||
it('should ignore files with non-numeric (or zero) names', done => {
|
||||
promise.then(result => {
|
||||
expect(result).toEqual([12, 34, 56]);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should ignore files with non-numeric (or zero) names', async () => {
|
||||
readdirCb(null, ['12', 'foo', '34', 'bar', '56', '000']);
|
||||
await expectAsync(promise).toBeResolvedTo([12, 34, 56]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -259,7 +220,7 @@ describe('BuildCleaner', () => {
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -268,31 +229,15 @@ describe('BuildCleaner', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject if an error occurs while fetching PRs', done => {
|
||||
promise.catch(err => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should reject if an error occurs while fetching PRs', async () => {
|
||||
prDeferred.reject('Test');
|
||||
await expectAsync(promise).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the numbers of the fetched PRs', done => {
|
||||
promise.then(prNumbers => {
|
||||
expect(prNumbers).toEqual([1, 2, 3]);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should resolve with the numbers of the fetched PRs', async () => {
|
||||
prDeferred.resolve([{id: 0, number: 1}, {id: 1, number: 2}, {id: 2, number: 3}]);
|
||||
});
|
||||
|
||||
|
||||
it('should log the number of open PRs', () => {
|
||||
promise.then(prNumbers => {
|
||||
expect(loggerLogSpy).toHaveBeenCalledWith(
|
||||
ANY_DATE, 'BuildCleaner: ', `Open pull requests: ${prNumbers}`);
|
||||
});
|
||||
await expectAsync(promise).toBeResolvedTo([1, 2, 3]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -304,13 +249,15 @@ describe('BuildCleaner', () => {
|
||||
let promise: Promise<string[]>;
|
||||
|
||||
beforeEach(() => {
|
||||
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake((_: string, cb: typeof readdirCb) => readdirCb = cb);
|
||||
fsReaddirSpy = spyOn(fs, 'readdir').and.callFake(
|
||||
((_: string, cb: typeof readdirCb) => readdirCb = cb) as unknown as typeof fs.readdir,
|
||||
);
|
||||
promise = cleaner.getExistingDownloads();
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -320,33 +267,21 @@ describe('BuildCleaner', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject if an error occurs while getting the files', done => {
|
||||
promise.catch(err => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should reject if an error occurs while getting the files', async () => {
|
||||
readdirCb('Test');
|
||||
await expectAsync(promise).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the returned file names', done => {
|
||||
promise.then(result => {
|
||||
expect(result).toEqual(EXISTING_DOWNLOADS);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should resolve with the returned file names', async () => {
|
||||
readdirCb(null, EXISTING_DOWNLOADS);
|
||||
await expectAsync(promise).toBeResolvedTo(EXISTING_DOWNLOADS);
|
||||
});
|
||||
|
||||
|
||||
it('should ignore files that do not match the artifactPath', done => {
|
||||
promise.then(result => {
|
||||
expect(result).toEqual(['10-ABCDEF-build.zip', '30-FFFFFFF-build.zip']);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should ignore files that do not match the artifactPath', async () => {
|
||||
readdirCb(null, ['10-ABCDEF-build.zip', '20-AAAAAAA-otherfile.zip', '30-FFFFFFF-build.zip']);
|
||||
await expectAsync(promise).toBeResolvedTo(['10-ABCDEF-build.zip', '30-FFFFFFF-build.zip']);
|
||||
});
|
||||
|
||||
});
|
||||
@ -364,7 +299,7 @@ describe('BuildCleaner', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should test if the directory exists (and return if is does not)', () => {
|
||||
it('should test if the directory exists (and return if it does not)', () => {
|
||||
shellTestSpy.and.returnValue(false);
|
||||
cleaner.removeDir('/foo/bar');
|
||||
|
||||
@ -381,22 +316,19 @@ describe('BuildCleaner', () => {
|
||||
|
||||
|
||||
it('should make the directory and its content writable before removing', () => {
|
||||
shellRmSpy.and.callFake(() => expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a+w', '/foo/bar'));
|
||||
cleaner.removeDir('/foo/bar');
|
||||
|
||||
expect(shellChmodSpy).toHaveBeenCalledBefore(shellRmSpy);
|
||||
expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a+w', '/foo/bar');
|
||||
expect(shellRmSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should catch errors and log them', () => {
|
||||
shellRmSpy.and.callFake(() => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
throw 'Test';
|
||||
});
|
||||
|
||||
shellRmSpy.and.throwError('Test');
|
||||
cleaner.removeDir('/foo/bar');
|
||||
|
||||
expect(loggerErrorSpy).toHaveBeenCalledWith('ERROR: Unable to remove \'/foo/bar\' due to:', 'Test');
|
||||
expect(loggerErrorSpy).toHaveBeenCalledWith('ERROR: Unable to remove \'/foo/bar\' due to:', new Error('Test'));
|
||||
});
|
||||
|
||||
});
|
||||
@ -449,7 +381,7 @@ describe('BuildCleaner', () => {
|
||||
expect(cleanerRemoveDirSpy).toHaveBeenCalledTimes(0);
|
||||
cleanerRemoveDirSpy.calls.reset();
|
||||
|
||||
(cleaner as any).removeUnnecessaryBuilds([1, 2, 3, 4], []);
|
||||
cleaner.removeUnnecessaryBuilds([1, 2, 3, 4], []);
|
||||
expect(cleanerRemoveDirSpy).toHaveBeenCalledTimes(8);
|
||||
expect(cleanerRemoveDirSpy).toHaveBeenCalledWith(normalize('/foo/bar/1'));
|
||||
expect(cleanerRemoveDirSpy).toHaveBeenCalledWith(normalize('/foo/bar/2'));
|
||||
|
@ -45,25 +45,15 @@ describe('CircleCIApi', () => {
|
||||
const errorMessage = 'Invalid request';
|
||||
const request = nock(BASE_URL).get(`/${buildNum}?circle-token=${TOKEN}`);
|
||||
|
||||
try {
|
||||
request.replyWithError(errorMessage);
|
||||
await api.getBuildInfo(buildNum);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(
|
||||
request.replyWithError(errorMessage);
|
||||
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
|
||||
`CircleCI build info request failed ` +
|
||||
`(request to ${BASE_URL}/${buildNum}?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
|
||||
}
|
||||
|
||||
try {
|
||||
request.reply(404, errorMessage);
|
||||
await api.getBuildInfo(buildNum);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(
|
||||
request.reply(404, errorMessage);
|
||||
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
|
||||
`CircleCI build info request failed ` +
|
||||
`(request to ${BASE_URL}/${buildNum}?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -78,8 +68,7 @@ describe('CircleCIApi', () => {
|
||||
.get(`/${buildNum}/artifacts?circle-token=${TOKEN}`)
|
||||
.reply(200, [artifact0, artifact1, artifact2]);
|
||||
|
||||
const artifactUrl = await api.getBuildArtifactUrl(buildNum, 'some/path/1');
|
||||
expect(artifactUrl).toEqual('https://url/1');
|
||||
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeResolvedTo('https://url/1');
|
||||
request.done();
|
||||
});
|
||||
|
||||
@ -90,25 +79,15 @@ describe('CircleCIApi', () => {
|
||||
const errorMessage = 'Invalid request';
|
||||
const request = nock(BASE_URL).get(`/${buildNum}/artifacts?circle-token=${TOKEN}`);
|
||||
|
||||
try {
|
||||
request.replyWithError(errorMessage);
|
||||
await api.getBuildArtifactUrl(buildNum, 'some/path/1');
|
||||
throw new Error('Exception Expected');
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(
|
||||
request.replyWithError(errorMessage);
|
||||
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
|
||||
`CircleCI artifact URL request failed ` +
|
||||
`(request to ${BASE_URL}/${buildNum}/artifacts?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
|
||||
}
|
||||
|
||||
try {
|
||||
request.reply(404, errorMessage);
|
||||
await api.getBuildArtifactUrl(buildNum, 'some/path/1');
|
||||
throw new Error('Exception Expected');
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(
|
||||
request.reply(404, errorMessage);
|
||||
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
|
||||
`CircleCI artifact URL request failed ` +
|
||||
`(request to ${BASE_URL}/${buildNum}/artifacts?circle-token=${TOKEN} failed, reason: ${errorMessage})`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error if the response does not contain the specified artifact', async () => {
|
||||
@ -121,14 +100,9 @@ describe('CircleCIApi', () => {
|
||||
.get(`/${buildNum}/artifacts?circle-token=${TOKEN}`)
|
||||
.reply(200, [artifact0, artifact1, artifact2]);
|
||||
|
||||
try {
|
||||
await api.getBuildArtifactUrl(buildNum, 'some/path/3');
|
||||
throw new Error('Exception Expected');
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(
|
||||
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/3')).toBeRejectedWithError(
|
||||
`CircleCI artifact URL request failed ` +
|
||||
`(Missing artifact (some/path/3) for CircleCI build: ${buildNum})`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -118,7 +118,7 @@ describe('GithubApi', () => {
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect((api as any).getPaginated()).toEqual(jasmine.any(Promise));
|
||||
expect((api as any).getPaginated()).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -131,45 +131,30 @@ describe('GithubApi', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject if the request fails', done => {
|
||||
(api as any).getPaginated('/foo/bar').catch((err: any) => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should reject if the request fails', async () => {
|
||||
const responsePromise = (api as any).getPaginated('/foo/bar');
|
||||
deferreds[0].reject('Test');
|
||||
|
||||
await expectAsync(responsePromise).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the returned items', done => {
|
||||
it('should resolve with the returned items', async () => {
|
||||
const items = [{id: 1}, {id: 2}];
|
||||
|
||||
(api as any).getPaginated('/foo/bar').then((data: any) => {
|
||||
expect(data).toEqual(items);
|
||||
done();
|
||||
});
|
||||
|
||||
const responsePromise = (api as any).getPaginated('/foo/bar');
|
||||
deferreds[0].resolve(items);
|
||||
|
||||
await expectAsync(responsePromise).toBeResolvedTo(items);
|
||||
});
|
||||
|
||||
|
||||
it('should iteratively call \'get()\' to fetch all items', done => {
|
||||
it('should iteratively call \'get()\' to fetch all items', async () => {
|
||||
// Create an array or 250 objects.
|
||||
const allItems = '.'.repeat(250).split('').map((_, i) => ({id: i}));
|
||||
const allItems = new Array(250).fill(null).map((_, i) => ({id: i}));
|
||||
const apiGetSpy = api.get as jasmine.Spy;
|
||||
const paramsForPage = (page: number) => ({baz: 'qux', page, per_page: 100});
|
||||
|
||||
(api as any).getPaginated('/foo/bar', {baz: 'qux'}).then((data: any) => {
|
||||
const paramsForPage = (page: number) => ({baz: 'qux', page, per_page: 100});
|
||||
|
||||
expect(apiGetSpy).toHaveBeenCalledTimes(3);
|
||||
expect(apiGetSpy.calls.argsFor(0)).toEqual(['/foo/bar', paramsForPage(1)]);
|
||||
expect(apiGetSpy.calls.argsFor(1)).toEqual(['/foo/bar', paramsForPage(2)]);
|
||||
expect(apiGetSpy.calls.argsFor(2)).toEqual(['/foo/bar', paramsForPage(3)]);
|
||||
|
||||
expect(data).toEqual(allItems);
|
||||
|
||||
done();
|
||||
});
|
||||
const responsePromise = (api as any).getPaginated('/foo/bar', {baz: 'qux'});
|
||||
|
||||
deferreds[0].resolve(allItems.slice(0, 100));
|
||||
setTimeout(() => {
|
||||
@ -178,6 +163,13 @@ describe('GithubApi', () => {
|
||||
deferreds[2].resolve(allItems.slice(200));
|
||||
}, 0);
|
||||
}, 0);
|
||||
|
||||
await expectAsync(responsePromise).toBeResolvedTo(allItems);
|
||||
|
||||
expect(apiGetSpy).toHaveBeenCalledTimes(3);
|
||||
expect(apiGetSpy.calls.argsFor(0)).toEqual(['/foo/bar', paramsForPage(1)]);
|
||||
expect(apiGetSpy.calls.argsFor(1)).toEqual(['/foo/bar', paramsForPage(2)]);
|
||||
expect(apiGetSpy.calls.argsFor(2)).toEqual(['/foo/bar', paramsForPage(3)]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -217,8 +209,8 @@ describe('GithubApi', () => {
|
||||
|
||||
describe('request()', () => {
|
||||
it('should return a promise', () => {
|
||||
nock('https://api.github.com').get('').reply(200);
|
||||
expect((api as any).request()).toEqual(jasmine.any(Promise));
|
||||
nock('https://api.github.com').get('/').reply(200);
|
||||
expect((api as any).request()).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -247,9 +239,8 @@ describe('GithubApi', () => {
|
||||
nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.replyWithError('Test');
|
||||
let message = 'Failed to reject error';
|
||||
await (api as any).request('method', '/path').catch((err: any) => message = err.message);
|
||||
expect(message).toEqual('Test');
|
||||
|
||||
await expectAsync((api as any).request('method', '/path')).toBeRejectedWithError('Test');
|
||||
});
|
||||
|
||||
|
||||
@ -263,81 +254,69 @@ describe('GithubApi', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should reject if response statusCode is <200', done => {
|
||||
it('should reject if response statusCode is <200', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(199);
|
||||
const responsePromise = (api as any).request('method', '/path');
|
||||
|
||||
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('failed'));
|
||||
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('status: 199'));
|
||||
|
||||
(api as any).request('method', '/path')
|
||||
.catch((err: string) => {
|
||||
expect(err).toContain('failed');
|
||||
expect(err).toContain('status: 199');
|
||||
done();
|
||||
});
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
||||
it('should reject if response statusCode is >=400', done => {
|
||||
it('should reject if response statusCode is >=400', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(400);
|
||||
const responsePromise = (api as any).request('method', '/path');
|
||||
|
||||
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('failed'));
|
||||
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('status: 400'));
|
||||
|
||||
(api as any).request('method', '/path')
|
||||
.catch((err: string) => {
|
||||
expect(err).toContain('failed');
|
||||
expect(err).toContain('status: 400');
|
||||
done();
|
||||
});
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
||||
it('should include the response text in the rejection message', done => {
|
||||
it('should include the response text in the rejection message', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(500, 'Test');
|
||||
const responsePromise = (api as any).request('method', '/path');
|
||||
|
||||
await expectAsync(responsePromise).toBeRejectedWith(jasmine.stringMatching('Test'));
|
||||
|
||||
(api as any).request('method', '/path')
|
||||
.catch((err: string) => {
|
||||
expect(err).toContain('Test');
|
||||
done();
|
||||
});
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
||||
it('should resolve if returned statusCode is >=200 and <400', done => {
|
||||
it('should resolve if returned statusCode is >=200 and <400', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(200);
|
||||
|
||||
(api as any).request('method', '/path').then(done);
|
||||
await expectAsync((api as any).request('method', '/path')).toBeResolved();
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
||||
it('should parse the response body into an object using \'JSON.parse\'', done => {
|
||||
it('should parse the response body into an object using \'JSON.parse\'', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(300, '{"foo": "bar"}');
|
||||
|
||||
(api as any).request('method', '/path').then((data: any) => {
|
||||
expect(data).toEqual({foo: 'bar'});
|
||||
done();
|
||||
});
|
||||
await expectAsync((api as any).request('method', '/path')).toBeResolvedTo({foo: 'bar'});
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
it('should reject if the response text is malformed JSON', done => {
|
||||
it('should reject if the response text is malformed JSON', async () => {
|
||||
const requestHandler = nock('https://api.github.com')
|
||||
.intercept('/path', 'method')
|
||||
.reply(300, '}');
|
||||
|
||||
(api as any).request('method', '/path').catch((err: any) => {
|
||||
expect(err).toEqual(jasmine.any(SyntaxError));
|
||||
done();
|
||||
});
|
||||
await expectAsync((api as any).request('method', '/path')).toBeRejectedWithError(SyntaxError);
|
||||
requestHandler.done();
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Imports
|
||||
import {GithubApi} from '../../lib/common/github-api';
|
||||
import {GithubPullRequests} from '../../lib/common/github-pull-requests';
|
||||
import {GithubPullRequests, PullRequest} from '../../lib/common/github-pull-requests';
|
||||
|
||||
// Tests
|
||||
describe('GithubPullRequests', () => {
|
||||
@ -47,27 +47,21 @@ describe('GithubPullRequests', () => {
|
||||
|
||||
|
||||
it('should make a POST request to Github with the correct pathname, params and data', () => {
|
||||
githubApi.post.and.callFake(() => Promise.resolve());
|
||||
githubApi.post.and.resolveTo();
|
||||
prs.addComment(42, 'body');
|
||||
expect(githubApi.post).toHaveBeenCalledWith('/repos/foo/bar/issues/42/comments', null, {body: 'body'});
|
||||
});
|
||||
|
||||
|
||||
it('should reject if the request fails', done => {
|
||||
githubApi.post.and.callFake(() => Promise.reject('Test'));
|
||||
prs.addComment(42, 'body').catch(err => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
it('should reject if the request fails', async () => {
|
||||
githubApi.post.and.rejectWith('Test');
|
||||
await expectAsync(prs.addComment(42, 'body')).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the data from the Github POST', done => {
|
||||
githubApi.post.and.callFake(() => Promise.resolve('Test'));
|
||||
prs.addComment(42, 'body').then(data => {
|
||||
expect(data).toBe('Test');
|
||||
done();
|
||||
});
|
||||
it('should resolve with the data from the Github POST', async () => {
|
||||
githubApi.post.and.resolveTo('Test');
|
||||
await expectAsync(prs.addComment(42, 'body')).toBeResolvedTo('Test');
|
||||
});
|
||||
|
||||
});
|
||||
@ -87,13 +81,11 @@ describe('GithubPullRequests', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the data returned from GitHub', done => {
|
||||
it('should resolve with the data returned from GitHub', async () => {
|
||||
const expected: any = {number: 42};
|
||||
githubApi.get.and.callFake(() => Promise.resolve(expected));
|
||||
prs.fetch(42).then(data => {
|
||||
expect(data).toEqual(expected);
|
||||
done();
|
||||
});
|
||||
githubApi.get.and.resolveTo(expected);
|
||||
|
||||
await expectAsync(prs.fetch(42)).toBeResolvedTo(expected);
|
||||
});
|
||||
|
||||
});
|
||||
@ -125,9 +117,14 @@ describe('GithubPullRequests', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should forward the value returned by \'getPaginated()\'', () => {
|
||||
githubApi.getPaginated.and.returnValue('Test');
|
||||
expect(prs.fetchAll() as any).toBe('Test');
|
||||
it('should forward the value returned by \'getPaginated()\'', async () => {
|
||||
const mockPrs: PullRequest[] = [
|
||||
{number: 1, user: {login: 'foo'}, labels: []},
|
||||
{number: 2, user: {login: 'bar'}, labels: []},
|
||||
];
|
||||
|
||||
githubApi.getPaginated.and.resolveTo(mockPrs);
|
||||
expect(await prs.fetchAll()).toBe(mockPrs);
|
||||
});
|
||||
|
||||
});
|
||||
@ -147,13 +144,11 @@ describe('GithubPullRequests', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the data returned from GitHub', done => {
|
||||
it('should resolve with the data returned from GitHub', async () => {
|
||||
const expected: any = [{sha: 'ABCDE', filename: 'a/b/c'}, {sha: '12345', filename: 'x/y/z'}];
|
||||
githubApi.getPaginated.and.callFake(() => Promise.resolve(expected));
|
||||
prs.fetchFiles(42).then(data => {
|
||||
expect(data).toEqual(expected);
|
||||
done();
|
||||
});
|
||||
githubApi.getPaginated.and.resolveTo(expected);
|
||||
|
||||
await expectAsync(prs.fetchFiles(42)).toBeResolvedTo(expected);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {GithubApi} from '../../lib/common/github-api';
|
||||
import {GithubTeams} from '../../lib/common/github-teams';
|
||||
import {GithubTeams, Team} from '../../lib/common/github-teams';
|
||||
|
||||
// Tests
|
||||
describe('GithubTeams', () => {
|
||||
@ -16,6 +16,7 @@ describe('GithubTeams', () => {
|
||||
expect(() => new GithubTeams(githubApi, '')).
|
||||
toThrowError('Missing or empty required parameter \'githubOrg\'!');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -33,9 +34,14 @@ describe('GithubTeams', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should forward the value returned by \'getPaginated()\'', () => {
|
||||
githubApi.getPaginated.and.returnValue('Test');
|
||||
expect(teams.fetchAll() as any).toBe('Test');
|
||||
it('should forward the value returned by \'getPaginated()\'', async () => {
|
||||
const mockTeams: Team[] = [
|
||||
{id: 1, slug: 'foo'},
|
||||
{id: 2, slug: 'bar'},
|
||||
];
|
||||
|
||||
githubApi.getPaginated.and.resolveTo(mockTeams);
|
||||
expect(await teams.fetchAll()).toBe(mockTeams);
|
||||
});
|
||||
|
||||
});
|
||||
@ -50,100 +56,77 @@ describe('GithubTeams', () => {
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
githubApi.get.and.callFake(() => Promise.resolve());
|
||||
githubApi.get.and.resolveTo();
|
||||
const promise = teams.isMemberById('user', [1]);
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with false if called with an empty array', done => {
|
||||
teams.isMemberById('user', []).then(isMember => {
|
||||
expect(isMember).toBe(false);
|
||||
expect(githubApi.get).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
it('should resolve with false if called with an empty array', async () => {
|
||||
await expectAsync(teams.isMemberById('user', [])).toBeResolvedTo(false);
|
||||
expect(githubApi.get).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should call \'get()\' with the correct pathname', done => {
|
||||
githubApi.get.and.callFake(() => Promise.resolve());
|
||||
teams.isMemberById('user', [1]).then(() => {
|
||||
expect(githubApi.get).toHaveBeenCalledWith('/teams/1/memberships/user');
|
||||
done();
|
||||
});
|
||||
it('should call \'get()\' with the correct pathname', async () => {
|
||||
githubApi.get.and.resolveTo();
|
||||
await teams.isMemberById('user', [1]);
|
||||
|
||||
expect(githubApi.get).toHaveBeenCalledWith('/teams/1/memberships/user');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with false if \'get()\' rejects', done => {
|
||||
githubApi.get.and.callFake(() => Promise.reject(null));
|
||||
teams.isMemberById('user', [1]).then(isMember => {
|
||||
expect(isMember).toBe(false);
|
||||
expect(githubApi.get).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
it('should resolve with false if \'get()\' rejects', async () => {
|
||||
githubApi.get.and.rejectWith(null);
|
||||
|
||||
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(false);
|
||||
expect(githubApi.get).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with false if the membership is not active', done => {
|
||||
githubApi.get.and.callFake(() => Promise.resolve({state: 'pending'}));
|
||||
teams.isMemberById('user', [1]).then(isMember => {
|
||||
expect(isMember).toBe(false);
|
||||
expect(githubApi.get).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
it('should resolve with false if the membership is not active', async () => {
|
||||
githubApi.get.and.resolveTo({state: 'pending'});
|
||||
|
||||
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(false);
|
||||
expect(githubApi.get).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with true if the membership is active', done => {
|
||||
githubApi.get.and.callFake(() => Promise.resolve({state: 'active'}));
|
||||
teams.isMemberById('user', [1]).then(isMember => {
|
||||
expect(isMember).toBe(true);
|
||||
done();
|
||||
});
|
||||
it('should resolve with true if the membership is active', async () => {
|
||||
githubApi.get.and.resolveTo({state: 'active'});
|
||||
await expectAsync(teams.isMemberById('user', [1])).toBeResolvedTo(true);
|
||||
});
|
||||
|
||||
|
||||
it('should sequentially call \'get()\' until an active membership is found', done => {
|
||||
const trainedResponses: {[pathname: string]: Promise<{state: string}>} = {
|
||||
'/teams/1/memberships/user': Promise.resolve({state: 'pending'}),
|
||||
'/teams/2/memberships/user': Promise.reject(null),
|
||||
'/teams/3/memberships/user': Promise.resolve({state: 'active'}),
|
||||
};
|
||||
githubApi.get.and.callFake((pathname: string) => trainedResponses[pathname]);
|
||||
it('should sequentially call \'get()\' until an active membership is found', async () => {
|
||||
githubApi.get.
|
||||
withArgs('/teams/1/memberships/user').and.resolveTo({state: 'pending'}).
|
||||
withArgs('/teams/2/memberships/user').and.rejectWith(null).
|
||||
withArgs('/teams/3/memberships/user').and.resolveTo({state: 'active'});
|
||||
|
||||
teams.isMemberById('user', [1, 2, 3, 4]).then(isMember => {
|
||||
expect(isMember).toBe(true);
|
||||
await expectAsync(teams.isMemberById('user', [1, 2, 3, 4])).toBeResolvedTo(true);
|
||||
|
||||
expect(githubApi.get).toHaveBeenCalledTimes(3);
|
||||
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
|
||||
|
||||
done();
|
||||
});
|
||||
expect(githubApi.get).toHaveBeenCalledTimes(3);
|
||||
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with false if no active membership is found', done => {
|
||||
const trainedResponses: {[pathname: string]: Promise<{state: string}>} = {
|
||||
'/teams/1/memberships/user': Promise.resolve({state: 'pending'}),
|
||||
'/teams/2/memberships/user': Promise.reject(null),
|
||||
'/teams/3/memberships/user': Promise.resolve({state: 'not active'}),
|
||||
'/teams/4/memberships/user': Promise.reject(null),
|
||||
};
|
||||
githubApi.get.and.callFake((pathname: string) => trainedResponses[pathname]);
|
||||
it('should resolve with false if no active membership is found', async () => {
|
||||
githubApi.get.
|
||||
withArgs('/teams/1/memberships/user').and.resolveTo({state: 'pending'}).
|
||||
withArgs('/teams/2/memberships/user').and.rejectWith(null).
|
||||
withArgs('/teams/3/memberships/user').and.resolveTo({state: 'not active'}).
|
||||
withArgs('/teams/4/memberships/user').and.rejectWith(null);
|
||||
|
||||
teams.isMemberById('user', [1, 2, 3, 4]).then(isMember => {
|
||||
expect(isMember).toBe(false);
|
||||
await expectAsync(teams.isMemberById('user', [1, 2, 3, 4])).toBeResolvedTo(false);
|
||||
|
||||
expect(githubApi.get).toHaveBeenCalledTimes(4);
|
||||
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(3)[0]).toBe('/teams/4/memberships/user');
|
||||
|
||||
done();
|
||||
});
|
||||
expect(githubApi.get).toHaveBeenCalledTimes(4);
|
||||
expect(githubApi.get.calls.argsFor(0)[0]).toBe('/teams/1/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(1)[0]).toBe('/teams/2/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(2)[0]).toBe('/teams/3/memberships/user');
|
||||
expect(githubApi.get.calls.argsFor(3)[0]).toBe('/teams/4/memberships/user');
|
||||
});
|
||||
|
||||
});
|
||||
@ -157,14 +140,13 @@ describe('GithubTeams', () => {
|
||||
beforeEach(() => {
|
||||
teams = new GithubTeams(githubApi, 'foo');
|
||||
|
||||
const mockResponse = Promise.resolve([{id: 1, slug: 'team1'}, {id: 2, slug: 'team2'}]);
|
||||
teamsFetchAllSpy = spyOn(teams, 'fetchAll').and.returnValue(mockResponse);
|
||||
teamsFetchAllSpy = spyOn(teams, 'fetchAll').and.resolveTo([{id: 1, slug: 'team1'}, {id: 2, slug: 'team2'}]);
|
||||
teamsIsMemberByIdSpy = spyOn(teams, 'isMemberById');
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect(teams.isMemberBySlug('user', ['team-slug'])).toEqual(jasmine.any(Promise));
|
||||
expect(teams.isMemberBySlug('user', ['team-slug'])).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -174,55 +156,46 @@ describe('GithubTeams', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with false if \'fetchAll()\' rejects', done => {
|
||||
teamsFetchAllSpy.and.callFake(() => Promise.reject(null));
|
||||
teams.isMemberBySlug('user', ['team-slug']).then(isMember => {
|
||||
expect(isMember).toBe(false);
|
||||
done();
|
||||
});
|
||||
it('should resolve with false if \'fetchAll()\' rejects', async () => {
|
||||
teamsFetchAllSpy.and.rejectWith(null);
|
||||
await expectAsync(teams.isMemberBySlug('user', ['team-slug'])).toBeResolvedTo(false);
|
||||
});
|
||||
|
||||
|
||||
it('should call \'isMemberById()\' with the correct params if no team is found', done => {
|
||||
teams.isMemberBySlug('user', ['no-match']).then(() => {
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', []);
|
||||
done();
|
||||
});
|
||||
it('should call \'isMemberById()\' with the correct params if no team is found', async () => {
|
||||
await teams.isMemberBySlug('user', ['no-match']);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', []);
|
||||
});
|
||||
|
||||
|
||||
it('should call \'isMemberById()\' with the correct params if teams are found', done => {
|
||||
const spy = teamsIsMemberByIdSpy;
|
||||
it('should call \'isMemberById()\' with the correct params if teams are found', async () => {
|
||||
await teams.isMemberBySlug('userA', ['team1']);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userA', [1]);
|
||||
|
||||
Promise.all([
|
||||
teams.isMemberBySlug('user', ['team1']).then(() => expect(spy).toHaveBeenCalledWith('user', [1])),
|
||||
teams.isMemberBySlug('user', ['team2']).then(() => expect(spy).toHaveBeenCalledWith('user', [2])),
|
||||
teams.isMemberBySlug('user', ['team1', 'team2']).then(() => expect(spy).toHaveBeenCalledWith('user', [1, 2])),
|
||||
]).then(done);
|
||||
await teams.isMemberBySlug('userB', ['team2']);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userB', [2]);
|
||||
|
||||
await teams.isMemberBySlug('userC', ['team1', 'team2']);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userC', [1, 2]);
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with false if \'isMemberById()\' rejects', done => {
|
||||
teamsIsMemberByIdSpy.and.callFake(() => Promise.reject(null));
|
||||
teams.isMemberBySlug('user', ['team1']).then(isMember => {
|
||||
expect(isMember).toBe(false);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
it('should resolve with false if \'isMemberById()\' rejects', async () => {
|
||||
teamsIsMemberByIdSpy.and.rejectWith(null);
|
||||
|
||||
await expectAsync(teams.isMemberBySlug('user', ['team1'])).toBeResolvedTo(false);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with the value \'isMemberById()\' resolves with', async () => {
|
||||
teamsIsMemberByIdSpy.and.resolveTo(true);
|
||||
await expectAsync(teams.isMemberBySlug('userA', ['team1'])).toBeResolvedTo(true);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userA', [1]);
|
||||
|
||||
teamsIsMemberByIdSpy.and.callFake(() => Promise.resolve(true));
|
||||
const isMember1 = await teams.isMemberBySlug('user', ['team1']);
|
||||
expect(isMember1).toBe(true);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', [1]);
|
||||
|
||||
teamsIsMemberByIdSpy.and.callFake(() => Promise.resolve(false));
|
||||
const isMember2 = await teams.isMemberBySlug('user', ['team1']);
|
||||
expect(isMember2).toBe(false);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('user', [1]);
|
||||
teamsIsMemberByIdSpy.and.resolveTo(false);
|
||||
await expectAsync(teams.isMemberBySlug('userB', ['team1'])).toBeResolvedTo(false);
|
||||
expect(teamsIsMemberByIdSpy).toHaveBeenCalledWith('userB', [1]);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -9,7 +9,8 @@ import {Logger} from '../../lib/common/utils';
|
||||
import {BuildCreator} from '../../lib/preview-server/build-creator';
|
||||
import {ChangedPrVisibilityEvent, CreatedBuildEvent} from '../../lib/preview-server/build-events';
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
import {expectToBePreviewServerError} from './helpers';
|
||||
import {customAsyncMatchers} from './jasmine-custom-async-matchers';
|
||||
|
||||
|
||||
// Tests
|
||||
describe('BuildCreator', () => {
|
||||
@ -24,6 +25,7 @@ describe('BuildCreator', () => {
|
||||
const publicShaDir = path.join(publicPrDir, shortSha);
|
||||
let bc: BuildCreator;
|
||||
|
||||
beforeEach(() => jasmine.addAsyncMatchers(customAsyncMatchers));
|
||||
beforeEach(() => bc = new BuildCreator(buildsDir));
|
||||
|
||||
|
||||
@ -35,8 +37,8 @@ describe('BuildCreator', () => {
|
||||
|
||||
|
||||
it('should extend EventEmitter', () => {
|
||||
expect(bc).toEqual(jasmine.any(BuildCreator));
|
||||
expect(bc).toEqual(jasmine.any(EventEmitter));
|
||||
expect(bc).toBeInstanceOf(BuildCreator);
|
||||
expect(bc).toBeInstanceOf(EventEmitter);
|
||||
|
||||
expect(Object.getPrototypeOf(bc)).toBe(BuildCreator.prototype);
|
||||
});
|
||||
@ -67,47 +69,43 @@ describe('BuildCreator', () => {
|
||||
const shaDir = isPublic ? publicShaDir : hiddenShaDir;
|
||||
|
||||
|
||||
it('should return a promise', done => {
|
||||
it('should return a promise', async () => {
|
||||
const promise = bc.create(pr, sha, archive, isPublic);
|
||||
promise.then(done); // Do not complete the test (and release the spies) synchronously
|
||||
// to avoid running the actual `extractArchive()`.
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
// Do not complete the test (and release the spies) synchronously to avoid running the actual
|
||||
// `extractArchive()`.
|
||||
await promise;
|
||||
});
|
||||
|
||||
|
||||
it('should update the PR\'s visibility first if necessary', done => {
|
||||
bcUpdatePrVisibilitySpy.and.callFake(() => expect(shellMkdirSpy).not.toHaveBeenCalled());
|
||||
it('should update the PR\'s visibility first if necessary', async () => {
|
||||
await bc.create(pr, sha, archive, isPublic);
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).
|
||||
then(() => {
|
||||
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(pr, isPublic);
|
||||
expect(shellMkdirSpy).toHaveBeenCalled();
|
||||
}).
|
||||
then(done);
|
||||
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledBefore(shellMkdirSpy);
|
||||
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(pr, isPublic);
|
||||
expect(shellMkdirSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should create the build directory (and any parent directories)', done => {
|
||||
bc.create(pr, sha, archive, isPublic).
|
||||
then(() => expect(shellMkdirSpy).toHaveBeenCalledWith('-p', shaDir)).
|
||||
then(done);
|
||||
it('should create the build directory (and any parent directories)', async () => {
|
||||
await bc.create(pr, sha, archive, isPublic);
|
||||
expect(shellMkdirSpy).toHaveBeenCalledWith('-p', shaDir);
|
||||
});
|
||||
|
||||
|
||||
it('should extract the archive contents into the build directory', done => {
|
||||
bc.create(pr, sha, archive, isPublic).
|
||||
then(() => expect(bcExtractArchiveSpy).toHaveBeenCalledWith(archive, shaDir)).
|
||||
then(done);
|
||||
it('should extract the archive contents into the build directory', async () => {
|
||||
await bc.create(pr, sha, archive, isPublic);
|
||||
expect(bcExtractArchiveSpy).toHaveBeenCalledWith(archive, shaDir);
|
||||
});
|
||||
|
||||
|
||||
it('should emit a CreatedBuildEvent on success', done => {
|
||||
it('should emit a CreatedBuildEvent on success', async () => {
|
||||
let emitted = false;
|
||||
|
||||
bcEmitSpy.and.callFake((type: string, evt: CreatedBuildEvent) => {
|
||||
expect(type).toBe(CreatedBuildEvent.type);
|
||||
expect(evt).toEqual(jasmine.any(CreatedBuildEvent));
|
||||
expect(evt).toBeInstanceOf(CreatedBuildEvent);
|
||||
expect(evt.pr).toBe(+pr);
|
||||
expect(evt.sha).toBe(shortSha);
|
||||
expect(evt.isPublic).toBe(isPublic);
|
||||
@ -115,130 +113,108 @@ describe('BuildCreator', () => {
|
||||
emitted = true;
|
||||
});
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).
|
||||
then(() => expect(emitted).toBe(true)).
|
||||
then(done);
|
||||
await bc.create(pr, sha, archive, isPublic);
|
||||
expect(emitted).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
describe('on error', () => {
|
||||
let existsValues: {[dir: string]: boolean};
|
||||
|
||||
beforeEach(() => {
|
||||
existsValues = {
|
||||
[prDir]: false,
|
||||
[shaDir]: false,
|
||||
};
|
||||
|
||||
bcExistsSpy.and.callFake((dir: string) => existsValues[dir]);
|
||||
bcExistsSpy.and.returnValue(false);
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if changing the PR\'s visibility fails', done => {
|
||||
it('should abort and skip further operations if changing the PR\'s visibility fails', async () => {
|
||||
const mockError = new PreviewServerError(543, 'Test');
|
||||
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject(mockError));
|
||||
bcUpdatePrVisibilitySpy.and.rejectWith(mockError);
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
expect(err).toBe(mockError);
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWith(mockError);
|
||||
|
||||
expect(bcExistsSpy).not.toHaveBeenCalled();
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
|
||||
done();
|
||||
});
|
||||
expect(bcExistsSpy).not.toHaveBeenCalled();
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if the build does already exist', done => {
|
||||
existsValues[shaDir] = true;
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
||||
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
it('should abort and skip further operations if the build does already exist', async () => {
|
||||
bcExistsSpy.withArgs(shaDir).and.returnValue(true);
|
||||
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
|
||||
409, `Request to overwrite existing ${isPublic ? '' : 'non-'}public directory: ${shaDir}`);
|
||||
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should detect existing build directory after visibility change', done => {
|
||||
bcUpdatePrVisibilitySpy.and.callFake(() => existsValues[prDir] = existsValues[shaDir] = true);
|
||||
it('should detect existing build directory after visibility change', async () => {
|
||||
bcUpdatePrVisibilitySpy.and.callFake(() => bcExistsSpy.and.returnValue(true));
|
||||
|
||||
expect(bcExistsSpy(prDir)).toBe(false);
|
||||
expect(bcExistsSpy(shaDir)).toBe(false);
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
||||
expectToBePreviewServerError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
|
||||
409, `Request to overwrite existing ${isPublic ? '' : 'non-'}public directory: ${shaDir}`);
|
||||
|
||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if it fails to create the directories', done => {
|
||||
it('should abort and skip further operations if it fails to create the directories', async () => {
|
||||
shellMkdirSpy.and.throwError('');
|
||||
bc.create(pr, sha, archive, isPublic).catch(() => {
|
||||
expect(shellMkdirSpy).toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
|
||||
|
||||
expect(shellMkdirSpy).toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if it fails to extract the archive', done => {
|
||||
bcExtractArchiveSpy.and.throwError('');
|
||||
bc.create(pr, sha, archive, isPublic).catch(() => {
|
||||
expect(shellMkdirSpy).toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should delete the PR directory (for new PR)', done => {
|
||||
bcExtractArchiveSpy.and.throwError('');
|
||||
bc.create(pr, sha, archive, isPublic).catch(() => {
|
||||
expect(shellRmSpy).toHaveBeenCalledWith('-rf', prDir);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should delete the SHA directory (for existing PR)', done => {
|
||||
existsValues[prDir] = true;
|
||||
it('should abort and skip further operations if it fails to extract the archive', async () => {
|
||||
bcExtractArchiveSpy.and.throwError('');
|
||||
|
||||
bc.create(pr, sha, archive, isPublic).catch(() => {
|
||||
expect(shellRmSpy).toHaveBeenCalledWith('-rf', shaDir);
|
||||
done();
|
||||
});
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
|
||||
|
||||
expect(shellMkdirSpy).toHaveBeenCalled();
|
||||
expect(bcExtractArchiveSpy).toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should reject with an PreviewServerError', done => {
|
||||
it('should delete the PR directory (for new PR)', async () => {
|
||||
bcExtractArchiveSpy.and.throwError('');
|
||||
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
|
||||
expect(shellRmSpy).toHaveBeenCalledWith('-rf', prDir);
|
||||
});
|
||||
|
||||
|
||||
it('should delete the SHA directory (for existing PR)', async () => {
|
||||
bcExistsSpy.withArgs(prDir).and.returnValue(true);
|
||||
bcExtractArchiveSpy.and.throwError('');
|
||||
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejected();
|
||||
expect(shellRmSpy).toHaveBeenCalledWith('-rf', shaDir);
|
||||
});
|
||||
|
||||
|
||||
it('should reject with an PreviewServerError', async () => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
shellMkdirSpy.and.callFake(() => { throw 'Test'; });
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
expectToBePreviewServerError(err, 500, `Error while creating preview at: ${shaDir}\nTest`);
|
||||
done();
|
||||
});
|
||||
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(
|
||||
500, `Error while creating preview at: ${shaDir}\nTest`);
|
||||
});
|
||||
|
||||
|
||||
it('should pass PreviewServerError instances unmodified', done => {
|
||||
it('should pass PreviewServerError instances unmodified', async () => {
|
||||
shellMkdirSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
|
||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||
expectToBePreviewServerError(err, 543, 'Test');
|
||||
done();
|
||||
});
|
||||
await expectAsync(bc.create(pr, sha, archive, isPublic)).toBeRejectedWithPreviewServerError(543, 'Test');
|
||||
});
|
||||
|
||||
});
|
||||
@ -265,12 +241,12 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', done => {
|
||||
it('should return a promise', async () => {
|
||||
const promise = bc.updatePrVisibility(pr, true);
|
||||
promise.then(done); // Do not complete the test (and release the spies) synchronously
|
||||
// to avoid running the actual `extractArchive()`.
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
// Do not complete the test (and release the spies) synchronously to avoid running the actual `extractArchive()`.
|
||||
await promise;
|
||||
});
|
||||
|
||||
|
||||
@ -279,58 +255,53 @@ describe('BuildCreator', () => {
|
||||
const newPrDir = makePublic ? publicPrDir : hiddenPrDir;
|
||||
|
||||
|
||||
it('should rename the directory', done => {
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(() => expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir)).
|
||||
then(done);
|
||||
it('should rename the directory', async () => {
|
||||
await bc.updatePrVisibility(pr, makePublic);
|
||||
expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir);
|
||||
});
|
||||
|
||||
|
||||
describe('when the visibility is updated', () => {
|
||||
|
||||
it('should resolve to true', done => {
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(result => expect(result).toBe(true)).
|
||||
then(done);
|
||||
it('should resolve to true', async () => {
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(true);
|
||||
});
|
||||
|
||||
|
||||
it('should rename the directory', done => {
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(() => expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir)).
|
||||
then(done);
|
||||
it('should rename the directory', async () => {
|
||||
await bc.updatePrVisibility(pr, makePublic);
|
||||
expect(shellMvSpy).toHaveBeenCalledWith(oldPrDir, newPrDir);
|
||||
});
|
||||
|
||||
|
||||
it('should emit a ChangedPrVisibilityEvent on success', done => {
|
||||
it('should emit a ChangedPrVisibilityEvent on success', async () => {
|
||||
let emitted = false;
|
||||
|
||||
bcEmitSpy.and.callFake((type: string, evt: ChangedPrVisibilityEvent) => {
|
||||
expect(type).toBe(ChangedPrVisibilityEvent.type);
|
||||
expect(evt).toEqual(jasmine.any(ChangedPrVisibilityEvent));
|
||||
expect(evt).toBeInstanceOf(ChangedPrVisibilityEvent);
|
||||
expect(evt.pr).toBe(+pr);
|
||||
expect(evt.shas).toEqual(jasmine.any(Array));
|
||||
expect(evt.shas).toBeInstanceOf(Array);
|
||||
expect(evt.isPublic).toBe(makePublic);
|
||||
|
||||
emitted = true;
|
||||
});
|
||||
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(() => expect(emitted).toBe(true)).
|
||||
then(done);
|
||||
await bc.updatePrVisibility(pr, makePublic);
|
||||
expect(emitted).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it('should include all shas in the emitted event', done => {
|
||||
it('should include all shas in the emitted event', async () => {
|
||||
const shas = ['foo', 'bar', 'baz'];
|
||||
let emitted = false;
|
||||
|
||||
bcListShasByDate.and.callFake(() => Promise.resolve(shas));
|
||||
bcListShasByDate.and.resolveTo(shas);
|
||||
bcEmitSpy.and.callFake((type: string, evt: ChangedPrVisibilityEvent) => {
|
||||
expect(bcListShasByDate).toHaveBeenCalledWith(newPrDir);
|
||||
|
||||
expect(type).toBe(ChangedPrVisibilityEvent.type);
|
||||
expect(evt).toEqual(jasmine.any(ChangedPrVisibilityEvent));
|
||||
expect(evt).toBeInstanceOf(ChangedPrVisibilityEvent);
|
||||
expect(evt.pr).toBe(+pr);
|
||||
expect(evt.shas).toBe(shas);
|
||||
expect(evt.isPublic).toBe(makePublic);
|
||||
@ -338,94 +309,82 @@ describe('BuildCreator', () => {
|
||||
emitted = true;
|
||||
});
|
||||
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(() => expect(emitted).toBe(true)).
|
||||
then(done);
|
||||
await bc.updatePrVisibility(pr, makePublic);
|
||||
expect(emitted).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should do nothing if the visibility is already up-to-date', done => {
|
||||
it('should do nothing if the visibility is already up-to-date', async () => {
|
||||
bcExistsSpy.and.callFake((dir: string) => dir === newPrDir);
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(result => {
|
||||
expect(result).toBe(false);
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
}).
|
||||
then(done);
|
||||
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(false);
|
||||
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should do nothing if the PR directory does not exist', done => {
|
||||
it('should do nothing if the PR directory does not exist', async () => {
|
||||
bcExistsSpy.and.returnValue(false);
|
||||
bc.updatePrVisibility(pr, makePublic).
|
||||
then(result => {
|
||||
expect(result).toBe(false);
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
}).
|
||||
then(done);
|
||||
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeResolvedTo(false);
|
||||
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
describe('on error', () => {
|
||||
|
||||
it('should abort and skip further operations if both directories exist', done => {
|
||||
it('should abort and skip further operations if both directories exist', async () => {
|
||||
bcExistsSpy.and.returnValue(true);
|
||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||
expectToBePreviewServerError(err, 409,
|
||||
`Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(
|
||||
409, `Request to move '${oldPrDir}' to existing directory '${newPrDir}'.`);
|
||||
|
||||
expect(shellMvSpy).not.toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if it fails to rename the directory', done => {
|
||||
it('should abort and skip further operations if it fails to rename the directory', async () => {
|
||||
shellMvSpy.and.throwError('');
|
||||
bc.updatePrVisibility(pr, makePublic).catch(() => {
|
||||
expect(shellMvSpy).toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejected();
|
||||
|
||||
expect(shellMvSpy).toHaveBeenCalled();
|
||||
expect(bcListShasByDate).not.toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if it fails to list the SHAs', done => {
|
||||
it('should abort and skip further operations if it fails to list the SHAs', async () => {
|
||||
bcListShasByDate.and.throwError('');
|
||||
bc.updatePrVisibility(pr, makePublic).catch(() => {
|
||||
expect(shellMvSpy).toHaveBeenCalled();
|
||||
expect(bcListShasByDate).toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejected();
|
||||
|
||||
expect(shellMvSpy).toHaveBeenCalled();
|
||||
expect(bcListShasByDate).toHaveBeenCalled();
|
||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should reject with an PreviewServerError', done => {
|
||||
it('should reject with an PreviewServerError', async () => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
shellMvSpy.and.callFake(() => { throw 'Test'; });
|
||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||
expectToBePreviewServerError(err, 500,
|
||||
`Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
|
||||
done();
|
||||
});
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(
|
||||
500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
|
||||
});
|
||||
|
||||
|
||||
it('should pass PreviewServerError instances unmodified', done => {
|
||||
it('should pass PreviewServerError instances unmodified', async () => {
|
||||
shellMvSpy.and.callFake(() => { throw new PreviewServerError(543, 'Test'); });
|
||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||
expectToBePreviewServerError(err, 543, 'Test');
|
||||
done();
|
||||
});
|
||||
await expectAsync(bc.updatePrVisibility(pr, makePublic)).toBeRejectedWithPreviewServerError(543, 'Test');
|
||||
});
|
||||
|
||||
});
|
||||
@ -443,12 +402,14 @@ describe('BuildCreator', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
fsAccessCbs = [];
|
||||
fsAccessSpy = spyOn(fs, 'access').and.callFake((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb));
|
||||
fsAccessSpy = spyOn(fs, 'access').and.callFake(
|
||||
((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb)) as unknown as typeof fs.access,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect((bc as any).exists('foo')).toEqual(jasmine.any(Promise));
|
||||
expect((bc as any).exists('foo')).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -458,25 +419,29 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with \'true\' if \'fs.access()\' succeeds', done => {
|
||||
Promise.
|
||||
all([(bc as any).exists('foo'), (bc as any).exists('bar')]).
|
||||
then(results => expect(results).toEqual([true, true])).
|
||||
then(done);
|
||||
it('should resolve with \'true\' if \'fs.access()\' succeeds', async () => {
|
||||
const existsPromises = [
|
||||
(bc as any).exists('foo'),
|
||||
(bc as any).exists('bar'),
|
||||
];
|
||||
|
||||
fsAccessCbs[0]();
|
||||
fsAccessCbs[1](null);
|
||||
|
||||
await expectAsync(Promise.all(existsPromises)).toBeResolvedTo([true, true]);
|
||||
});
|
||||
|
||||
|
||||
it('should resolve with \'false\' if \'fs.access()\' errors', done => {
|
||||
Promise.
|
||||
all([(bc as any).exists('foo'), (bc as any).exists('bar')]).
|
||||
then(results => expect(results).toEqual([false, false])).
|
||||
then(done);
|
||||
it('should resolve with \'false\' if \'fs.access()\' errors', async () => {
|
||||
const existsPromises = [
|
||||
(bc as any).exists('foo'),
|
||||
(bc as any).exists('bar'),
|
||||
];
|
||||
|
||||
fsAccessCbs[0]('Error');
|
||||
fsAccessCbs[1](new Error());
|
||||
|
||||
await expectAsync(Promise.all(existsPromises)).toBeResolvedTo([false, false]);
|
||||
});
|
||||
|
||||
});
|
||||
@ -495,12 +460,15 @@ describe('BuildCreator', () => {
|
||||
consoleWarnSpy = spyOn(Logger.prototype, 'warn');
|
||||
shellChmodSpy = spyOn(shell, 'chmod');
|
||||
shellRmSpy = spyOn(shell, 'rm');
|
||||
cpExecSpy = spyOn(cp, 'exec').and.callFake((_: string, cb: (...args: any[]) => void) => cpExecCbs.push(cb));
|
||||
cpExecSpy = spyOn(cp, 'exec').and.callFake(
|
||||
((_: string, cb: (...args: any[]) => void) =>
|
||||
cpExecCbs.push(cb)) as unknown as typeof cp.exec,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', () => {
|
||||
expect((bc as any).extractArchive('foo', 'bar')).toEqual(jasmine.any(Promise));
|
||||
expect((bc as any).extractArchive('foo', 'bar')).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
|
||||
@ -512,78 +480,68 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
|
||||
it('should log (as a warning) any stderr output if extracting succeeded', done => {
|
||||
(bc as any).extractArchive('foo', 'bar').
|
||||
then(() => expect(consoleWarnSpy).toHaveBeenCalledWith('This is stderr')).
|
||||
then(done);
|
||||
|
||||
it('should log (as a warning) any stderr output if extracting succeeded', async () => {
|
||||
const extractPromise = (bc as any).extractArchive('foo', 'bar');
|
||||
cpExecCbs[0](null, 'This is stdout', 'This is stderr');
|
||||
|
||||
await expectAsync(extractPromise).toBeResolved();
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith('This is stderr');
|
||||
});
|
||||
|
||||
|
||||
it('should make the build directory non-writable', done => {
|
||||
(bc as any).extractArchive('foo', 'bar').
|
||||
then(() => expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a-w', 'bar')).
|
||||
then(done);
|
||||
|
||||
it('should make the build directory non-writable', async () => {
|
||||
const extractPromise = (bc as any).extractArchive('foo', 'bar');
|
||||
cpExecCbs[0]();
|
||||
|
||||
await expectAsync(extractPromise).toBeResolved();
|
||||
expect(shellChmodSpy).toHaveBeenCalledWith('-R', 'a-w', 'bar');
|
||||
});
|
||||
|
||||
|
||||
it('should delete the build artifact file on success', done => {
|
||||
(bc as any).extractArchive('input/file', 'output/dir').
|
||||
then(() => expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file')).
|
||||
then(done);
|
||||
|
||||
it('should delete the build artifact file on success', async () => {
|
||||
const extractPromise = (bc as any).extractArchive('input/file', 'output/dir');
|
||||
cpExecCbs[0]();
|
||||
|
||||
await expectAsync(extractPromise).toBeResolved();
|
||||
expect(shellRmSpy).toHaveBeenCalledWith('-f', 'input/file');
|
||||
});
|
||||
|
||||
|
||||
describe('on error', () => {
|
||||
|
||||
it('should abort and skip further operations if it fails to extract the archive', done => {
|
||||
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
|
||||
expect(shellChmodSpy).not.toHaveBeenCalled();
|
||||
expect(shellRmSpy).not.toHaveBeenCalled();
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should abort and skip further operations if it fails to extract the archive', async () => {
|
||||
const extractPromise = (bc as any).extractArchive('foo', 'bar');
|
||||
cpExecCbs[0]('Test');
|
||||
|
||||
await expectAsync(extractPromise).toBeRejectedWith('Test');
|
||||
expect(shellChmodSpy).not.toHaveBeenCalled();
|
||||
expect(shellRmSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and skip further operations if it fails to make non-writable', done => {
|
||||
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
|
||||
expect(shellChmodSpy).toHaveBeenCalled();
|
||||
expect(shellRmSpy).not.toHaveBeenCalled();
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
shellChmodSpy.and.callFake(() => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
throw 'Test';
|
||||
});
|
||||
it('should abort and skip further operations if it fails to make non-writable', async () => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
shellChmodSpy.and.callFake(() => { throw 'Test'; });
|
||||
|
||||
const extractPromise = (bc as any).extractArchive('foo', 'bar');
|
||||
cpExecCbs[0]();
|
||||
|
||||
await expectAsync(extractPromise).toBeRejectedWith('Test');
|
||||
expect(shellChmodSpy).toHaveBeenCalled();
|
||||
expect(shellRmSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should abort and reject if it fails to remove the build artifact file', done => {
|
||||
(bc as any).extractArchive('foo', 'bar').catch((err: any) => {
|
||||
expect(shellChmodSpy).toHaveBeenCalled();
|
||||
expect(shellRmSpy).toHaveBeenCalled();
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
|
||||
shellRmSpy.and.callFake(() => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
throw 'Test';
|
||||
});
|
||||
it('should abort and reject if it fails to remove the build artifact file', async () => {
|
||||
// tslint:disable-next-line: no-string-throw
|
||||
shellRmSpy.and.callFake(() => { throw 'Test'; });
|
||||
|
||||
const extractPromise = (bc as any).extractArchive('foo', 'bar');
|
||||
cpExecCbs[0]();
|
||||
|
||||
await expectAsync(extractPromise).toBeRejectedWith('Test');
|
||||
expect(shellChmodSpy).toHaveBeenCalled();
|
||||
expect(shellRmSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
@ -600,62 +558,54 @@ describe('BuildCreator', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
shellLsSpy = spyOn(shell, 'ls').and.returnValue([]);
|
||||
shellLsSpy = spyOn(shell, 'ls').and.returnValue([] as unknown as shell.ShellArray);
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', done => {
|
||||
it('should return a promise', async () => {
|
||||
const promise = (bc as any).listShasByDate('input/dir');
|
||||
promise.then(done); // Do not complete the test (and release the spies) synchronously
|
||||
// to avoid running the actual `ls()`.
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
// Do not complete the test (and release the spies) synchronously to avoid running the actual `ls()`.
|
||||
await promise;
|
||||
});
|
||||
|
||||
|
||||
it('should `ls()` files with their metadata', done => {
|
||||
(bc as any).listShasByDate('input/dir').
|
||||
then(() => expect(shellLsSpy).toHaveBeenCalledWith('-l', 'input/dir')).
|
||||
then(done);
|
||||
it('should `ls()` files with their metadata', async () => {
|
||||
await (bc as any).listShasByDate('input/dir');
|
||||
expect(shellLsSpy).toHaveBeenCalledWith('-l', 'input/dir');
|
||||
});
|
||||
|
||||
|
||||
it('should reject if listing files fails', done => {
|
||||
shellLsSpy.and.callFake(() => Promise.reject('Test'));
|
||||
(bc as any).listShasByDate('input/dir').catch((err: string) => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
it('should reject if listing files fails', async () => {
|
||||
shellLsSpy.and.rejectWith('Test');
|
||||
await expectAsync((bc as any).listShasByDate('input/dir')).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should return the filenames', done => {
|
||||
shellLsSpy.and.callFake(() => Promise.resolve([
|
||||
it('should return the filenames', async () => {
|
||||
shellLsSpy.and.resolveTo([
|
||||
lsResult('foo', 100),
|
||||
lsResult('bar', 200),
|
||||
lsResult('baz', 300),
|
||||
]));
|
||||
]);
|
||||
|
||||
(bc as any).listShasByDate('input/dir').
|
||||
then((shas: string[]) => expect(shas).toEqual(['foo', 'bar', 'baz'])).
|
||||
then(done);
|
||||
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['foo', 'bar', 'baz']);
|
||||
});
|
||||
|
||||
|
||||
it('should sort by date', done => {
|
||||
shellLsSpy.and.callFake(() => Promise.resolve([
|
||||
it('should sort by date', async () => {
|
||||
shellLsSpy.and.resolveTo([
|
||||
lsResult('foo', 300),
|
||||
lsResult('bar', 100),
|
||||
lsResult('baz', 200),
|
||||
]));
|
||||
]);
|
||||
|
||||
(bc as any).listShasByDate('input/dir').
|
||||
then((shas: string[]) => expect(shas).toEqual(['bar', 'baz', 'foo'])).
|
||||
then(done);
|
||||
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['bar', 'baz', 'foo']);
|
||||
});
|
||||
|
||||
|
||||
it('should not break with ShellJS\' custom `sort()` method', done => {
|
||||
it('should not break with ShellJS\' custom `sort()` method', async () => {
|
||||
const mockArray = [
|
||||
lsResult('foo', 300),
|
||||
lsResult('bar', 100),
|
||||
@ -663,26 +613,21 @@ describe('BuildCreator', () => {
|
||||
];
|
||||
mockArray.sort = jasmine.createSpy('sort');
|
||||
|
||||
shellLsSpy.and.callFake(() => Promise.resolve(mockArray));
|
||||
(bc as any).listShasByDate('input/dir').
|
||||
then((shas: string[]) => {
|
||||
expect(shas).toEqual(['bar', 'baz', 'foo']);
|
||||
expect(mockArray.sort).not.toHaveBeenCalled();
|
||||
}).
|
||||
then(done);
|
||||
shellLsSpy.and.resolveTo(mockArray);
|
||||
|
||||
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['bar', 'baz', 'foo']);
|
||||
expect(mockArray.sort).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should only include directories', done => {
|
||||
shellLsSpy.and.callFake(() => Promise.resolve([
|
||||
it('should only include directories', async () => {
|
||||
shellLsSpy.and.resolveTo([
|
||||
lsResult('foo', 100),
|
||||
lsResult('bar', 200, false),
|
||||
lsResult('baz', 300),
|
||||
]));
|
||||
]);
|
||||
|
||||
(bc as any).listShasByDate('input/dir').
|
||||
then((shas: string[]) => expect(shas).toEqual(['foo', 'baz'])).
|
||||
then(done);
|
||||
await expectAsync((bc as any).listShasByDate('input/dir')).toBeResolvedTo(['foo', 'baz']);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -32,18 +32,18 @@ describe('BuildRetriever', () => {
|
||||
};
|
||||
|
||||
api = new CircleCiApi('ORG', 'REPO', 'TOKEN');
|
||||
spyOn(api, 'getBuildInfo').and.callFake(() => Promise.resolve(BUILD_INFO));
|
||||
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl')
|
||||
.and.callFake(() => Promise.resolve(BASE_URL + ARTIFACT_PATH));
|
||||
spyOn(api, 'getBuildInfo').and.resolveTo(BUILD_INFO);
|
||||
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl').and.resolveTo(BASE_URL + ARTIFACT_PATH);
|
||||
|
||||
WRITEFILE_RESULT = undefined;
|
||||
writeFileSpy = spyOn(fs, 'writeFile').and.callFake(
|
||||
(_path: string, _buffer: Buffer, callback: (err?: any) => {}) => callback(WRITEFILE_RESULT),
|
||||
((_path: string, _buffer: Buffer, callback: fs.NoParamCallback) =>
|
||||
callback(WRITEFILE_RESULT)) as typeof fs.writeFile,
|
||||
);
|
||||
|
||||
EXISTS_RESULT = false;
|
||||
existsSpy = spyOn(fs, 'exists').and.callFake(
|
||||
(_path: string, callback: (exists: boolean) => {}) => callback(EXISTS_RESULT),
|
||||
((_path, callback) => callback(EXISTS_RESULT)) as typeof fs.exists,
|
||||
);
|
||||
});
|
||||
|
||||
@ -56,6 +56,7 @@ describe('BuildRetriever', () => {
|
||||
expect(() => new BuildRetriever(api, -1, DOWNLOAD_DIR))
|
||||
.toThrowError(`Invalid parameter "downloadSizeLimit" should be a number greater than 0.`);
|
||||
});
|
||||
|
||||
it('should fail if the "downloadDir" is missing', () => {
|
||||
expect(() => new BuildRetriever(api, MAX_DOWNLOAD_SIZE, ''))
|
||||
.toThrowError(`Missing or empty required parameter 'downloadDir'!`);
|
||||
@ -72,14 +73,10 @@ describe('BuildRetriever', () => {
|
||||
});
|
||||
|
||||
it('should error if it is not possible to extract the PR number from the branch', async () => {
|
||||
BUILD_INFO.branch = 'master';
|
||||
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
|
||||
try {
|
||||
BUILD_INFO.branch = 'master';
|
||||
await retriever.getGithubInfo(12345);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual('No PR found in branch field: master');
|
||||
}
|
||||
|
||||
await expectAsync(retriever.getGithubInfo(12345)).toBeRejectedWithError('No PR found in branch field: master');
|
||||
});
|
||||
});
|
||||
|
||||
@ -110,12 +107,10 @@ describe('BuildRetriever', () => {
|
||||
it('should fail if the artifact is too large', async () => {
|
||||
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(200, ARTIFACT_CONTENTS);
|
||||
retriever = new BuildRetriever(api, 10, DOWNLOAD_DIR);
|
||||
try {
|
||||
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (error) {
|
||||
expect(error.status).toEqual(413);
|
||||
}
|
||||
|
||||
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
|
||||
toBeRejectedWith(jasmine.objectContaining({status: 413}));
|
||||
|
||||
artifactRequest.done();
|
||||
});
|
||||
|
||||
@ -143,50 +138,40 @@ describe('BuildRetriever', () => {
|
||||
artifactRequest.done();
|
||||
});
|
||||
|
||||
it('should fail if the CircleCI API fails', async () => {
|
||||
try {
|
||||
getBuildArtifactUrlSpy.and.callFake(() => Promise.reject('getBuildArtifactUrl failed'));
|
||||
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual('CircleCI artifact download failed (getBuildArtifactUrl failed)');
|
||||
}
|
||||
it('should fail if the CircleCI API fails', async () => {
|
||||
getBuildArtifactUrlSpy.and.rejectWith('getBuildArtifactUrl failed');
|
||||
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
|
||||
toBeRejectedWithError('CircleCI artifact download failed (getBuildArtifactUrl failed)');
|
||||
});
|
||||
|
||||
it('should fail if the URL fetch errors', async () => {
|
||||
it('should fail if the URL fetch errors', async () => {
|
||||
// create a new handler that errors
|
||||
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).replyWithError('Artifact Request Failed');
|
||||
try {
|
||||
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual('CircleCI artifact download failed ' +
|
||||
|
||||
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).toBeRejectedWithError(
|
||||
'CircleCI artifact download failed ' +
|
||||
'(request to http://test.com/some/path/build.zip failed, reason: Artifact Request Failed)');
|
||||
}
|
||||
|
||||
artifactRequest.done();
|
||||
});
|
||||
|
||||
it('should fail if the URL fetch 404s', async () => {
|
||||
it('should fail if the URL fetch 404s', async () => {
|
||||
// create a new handler that errors
|
||||
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(404, 'No such artifact');
|
||||
try {
|
||||
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual('CircleCI artifact download failed (Error 404 - Not Found)');
|
||||
}
|
||||
|
||||
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
|
||||
toBeRejectedWithError('CircleCI artifact download failed (Error 404 - Not Found)');
|
||||
|
||||
artifactRequest.done();
|
||||
});
|
||||
|
||||
it('should fail if file write fails', async () => {
|
||||
it('should fail if file write fails', async () => {
|
||||
const artifactRequest = nock(BASE_URL).get(ARTIFACT_PATH).reply(200, ARTIFACT_CONTENTS);
|
||||
try {
|
||||
WRITEFILE_RESULT = 'Test Error';
|
||||
await retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH);
|
||||
throw new Error('Exception Expected');
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual('CircleCI artifact download failed (Test Error)');
|
||||
}
|
||||
WRITEFILE_RESULT = 'Test Error';
|
||||
|
||||
await expectAsync(retriever.downloadBuildArtifact(12345, 777, 'COMMIT', ARTIFACT_PATH)).
|
||||
toBeRejectedWithError('CircleCI artifact download failed (Test Error)');
|
||||
|
||||
artifactRequest.done();
|
||||
});
|
||||
});
|
||||
|
@ -51,7 +51,10 @@ describe('BuildVerifier', () => {
|
||||
describe('getSignificantFilesChanged', () => {
|
||||
it('should return false if none of the fetched files match the given pattern', async () => {
|
||||
const fetchFilesSpy = spyOn(prs, 'fetchFiles');
|
||||
fetchFilesSpy.and.callFake(() => Promise.resolve([{filename: 'a/b/c'}, {filename: 'd/e/f'}]));
|
||||
fetchFilesSpy.and.resolveTo([
|
||||
{filename: 'a/b/c', sha: 'a1'},
|
||||
{filename: 'd/e/f', sha: 'b2'},
|
||||
]);
|
||||
expect(await bv.getSignificantFilesChanged(777, /^x/)).toEqual(false);
|
||||
expect(fetchFilesSpy).toHaveBeenCalledWith(777);
|
||||
|
||||
@ -78,37 +81,30 @@ describe('BuildVerifier', () => {
|
||||
user: {login: 'username'},
|
||||
};
|
||||
|
||||
prsFetchSpy = spyOn(GithubPullRequests.prototype, 'fetch').
|
||||
and.callFake(() => Promise.resolve(mockPrInfo));
|
||||
|
||||
teamsIsMemberBySlugSpy = spyOn(GithubTeams.prototype, 'isMemberBySlug').
|
||||
and.callFake(() => Promise.resolve(true));
|
||||
prsFetchSpy = spyOn(GithubPullRequests.prototype, 'fetch').and.resolveTo(mockPrInfo);
|
||||
teamsIsMemberBySlugSpy = spyOn(GithubTeams.prototype, 'isMemberBySlug').and.resolveTo(true);
|
||||
});
|
||||
|
||||
|
||||
it('should return a promise', done => {
|
||||
it('should return a promise', async () => {
|
||||
const promise = bv.getPrIsTrusted(pr);
|
||||
promise.then(done); // Do not complete the test (and release the spies) synchronously
|
||||
// to avoid running the actual `GithubTeams#isMemberBySlug()`.
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
|
||||
expect(promise).toEqual(jasmine.any(Promise));
|
||||
// Do not complete the test (and release the spies) synchronously to avoid running the actual
|
||||
// `GithubTeams#isMemberBySlug()`.
|
||||
await promise;
|
||||
});
|
||||
|
||||
|
||||
it('should fetch the corresponding PR', done => {
|
||||
bv.getPrIsTrusted(pr).then(() => {
|
||||
expect(prsFetchSpy).toHaveBeenCalledWith(pr);
|
||||
done();
|
||||
});
|
||||
it('should fetch the corresponding PR', async () => {
|
||||
await bv.getPrIsTrusted(pr);
|
||||
expect(prsFetchSpy).toHaveBeenCalledWith(pr);
|
||||
});
|
||||
|
||||
|
||||
it('should fail if fetching the PR errors', done => {
|
||||
prsFetchSpy.and.callFake(() => Promise.reject('Test'));
|
||||
bv.getPrIsTrusted(pr).catch(err => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
it('should fail if fetching the PR errors', async () => {
|
||||
prsFetchSpy.and.rejectWith('Test');
|
||||
await expectAsync(bv.getPrIsTrusted(pr)).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
@ -117,19 +113,14 @@ describe('BuildVerifier', () => {
|
||||
beforeEach(() => mockPrInfo.labels.push({name: 'trusted: pr-label'}));
|
||||
|
||||
|
||||
it('should resolve to true', done => {
|
||||
bv.getPrIsTrusted(pr).then(isTrusted => {
|
||||
expect(isTrusted).toBe(true);
|
||||
done();
|
||||
});
|
||||
it('should resolve to true', async () => {
|
||||
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(true);
|
||||
});
|
||||
|
||||
|
||||
it('should not try to verify the author\'s membership status', done => {
|
||||
bv.getPrIsTrusted(pr).then(() => {
|
||||
expect(teamsIsMemberBySlugSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
it('should not try to verify the author\'s membership status', async () => {
|
||||
await expectAsync(bv.getPrIsTrusted(pr));
|
||||
expect(teamsIsMemberBySlugSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
@ -137,40 +128,27 @@ describe('BuildVerifier', () => {
|
||||
|
||||
describe('when the PR does not have the "trusted PR" label', () => {
|
||||
|
||||
it('should verify the PR author\'s membership in the specified teams', done => {
|
||||
bv.getPrIsTrusted(pr).then(() => {
|
||||
expect(teamsIsMemberBySlugSpy).toHaveBeenCalledWith('username', ['team1', 'team2']);
|
||||
done();
|
||||
});
|
||||
it('should verify the PR author\'s membership in the specified teams', async () => {
|
||||
await bv.getPrIsTrusted(pr);
|
||||
expect(teamsIsMemberBySlugSpy).toHaveBeenCalledWith('username', ['team1', 'team2']);
|
||||
});
|
||||
|
||||
|
||||
it('should fail if verifying membership errors', done => {
|
||||
teamsIsMemberBySlugSpy.and.callFake(() => Promise.reject('Test'));
|
||||
bv.getPrIsTrusted(pr).catch(err => {
|
||||
expect(err).toBe('Test');
|
||||
done();
|
||||
});
|
||||
it('should fail if verifying membership errors', async () => {
|
||||
teamsIsMemberBySlugSpy.and.rejectWith('Test');
|
||||
await expectAsync(bv.getPrIsTrusted(pr)).toBeRejectedWith('Test');
|
||||
});
|
||||
|
||||
|
||||
it('should resolve to true if the PR\'s author is a member', done => {
|
||||
teamsIsMemberBySlugSpy.and.callFake(() => Promise.resolve(true));
|
||||
|
||||
bv.getPrIsTrusted(pr).then(isTrusted => {
|
||||
expect(isTrusted).toBe(true);
|
||||
done();
|
||||
});
|
||||
it('should resolve to true if the PR\'s author is a member', async () => {
|
||||
teamsIsMemberBySlugSpy.and.resolveTo(true);
|
||||
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(true);
|
||||
});
|
||||
|
||||
|
||||
it('should resolve to false if the PR\'s author is not a member', done => {
|
||||
teamsIsMemberBySlugSpy.and.callFake(() => Promise.resolve(false));
|
||||
|
||||
bv.getPrIsTrusted(pr).then(isTrusted => {
|
||||
expect(isTrusted).toBe(false);
|
||||
done();
|
||||
});
|
||||
it('should resolve to false if the PR\'s author is not a member', async () => {
|
||||
teamsIsMemberBySlugSpy.and.resolveTo(false);
|
||||
await expectAsync(bv.getPrIsTrusted(pr)).toBeResolvedTo(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,11 +0,0 @@
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
|
||||
export const expectToBePreviewServerError = (actual: PreviewServerError, status?: number, message?: string) => {
|
||||
expect(actual).toEqual(jasmine.any(PreviewServerError));
|
||||
if (status != null) {
|
||||
expect(actual.status).toBe(status);
|
||||
}
|
||||
if (message != null) {
|
||||
expect(actual.message).toBe(message);
|
||||
}
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
declare module jasmine {
|
||||
interface AsyncMatchers {
|
||||
toBeRejectedWithPreviewServerError(status: number, message?: string | RegExp): Promise<void>;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
import {PreviewServerError} from '../../lib/preview-server/preview-error';
|
||||
|
||||
|
||||
// Matchers
|
||||
const toBeRejectedWithPreviewServerError: jasmine.CustomAsyncMatcherFactory = () => {
|
||||
return {
|
||||
async compare(actualPromise: Promise<never>, expectedStatus: number, expectedMessage?: string | RegExp) {
|
||||
if (!(actualPromise instanceof Promise)) {
|
||||
throw new Error(`Expected '${toBeRejectedWithPreviewServerError.name}()' to be called on a promise.`);
|
||||
}
|
||||
|
||||
try {
|
||||
await actualPromise;
|
||||
|
||||
return {
|
||||
pass: false,
|
||||
message: `Expected a promise to be rejected with a '${PreviewServerError.name}', but it was resolved.`,
|
||||
};
|
||||
} catch (actualError) {
|
||||
const actualPrintValue = stringify(actualError);
|
||||
const expectedPrintValue =
|
||||
stringify(new PreviewServerError(expectedStatus, expectedMessage && `${expectedMessage}`));
|
||||
|
||||
const pass = errorMatches(actualError, expectedStatus, expectedMessage);
|
||||
const message =
|
||||
`Expected a promise ${pass ? 'not ' : ''}to be rejected with ${expectedPrintValue}, but is was` +
|
||||
`${pass ? '' : ` rejected with ${actualPrintValue}`}.`;
|
||||
|
||||
return {pass, message};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Helpers
|
||||
function errorMatches(actualErr: unknown, expectedStatus: number, expectedMsg?: string | RegExp): boolean {
|
||||
if (!(actualErr instanceof PreviewServerError)) return false;
|
||||
if (actualErr.status !== expectedStatus) return false;
|
||||
return messageMatches(actualErr.message, expectedMsg);
|
||||
}
|
||||
|
||||
function messageMatches(actualMsg: string, expectedMsg?: string | RegExp): boolean {
|
||||
if (typeof expectedMsg === 'undefined') return true;
|
||||
if (typeof expectedMsg === 'string') return actualMsg === expectedMsg;
|
||||
return expectedMsg.test(actualMsg);
|
||||
}
|
||||
|
||||
function stringify(value: unknown): string {
|
||||
if (value instanceof PreviewServerError) {
|
||||
return `${PreviewServerError.name}(${value.status}${value.message ? `, ${value.message}` : ''})`;
|
||||
}
|
||||
|
||||
return jasmine.pp(value);
|
||||
}
|
||||
};
|
||||
|
||||
// Exports
|
||||
export const customAsyncMatchers: jasmine.CustomAsyncMatcherFactories = {
|
||||
toBeRejectedWithPreviewServerError,
|
||||
};
|
@ -9,8 +9,8 @@ describe('PreviewServerError', () => {
|
||||
|
||||
|
||||
it('should extend Error', () => {
|
||||
expect(err).toEqual(jasmine.any(PreviewServerError));
|
||||
expect(err).toEqual(jasmine.any(Error));
|
||||
expect(err).toBeInstanceOf(PreviewServerError);
|
||||
expect(err).toBeInstanceOf(Error);
|
||||
|
||||
expect(Object.getPrototypeOf(err)).toBe(PreviewServerError.prototype);
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
// Imports
|
||||
import * as express from 'express';
|
||||
import * as http from 'http';
|
||||
import * as supertest from 'supertest';
|
||||
import {CircleCiApi} from '../../lib/common/circle-ci-api';
|
||||
@ -134,7 +133,7 @@ describe('PreviewServerFactory', () => {
|
||||
const buildCreator = jasmine.any(BuildCreator);
|
||||
expect(usfCreateMiddlewareSpy).toHaveBeenCalledWith(buildRetriever, buildVerifier, buildCreator, defaultConfig);
|
||||
|
||||
const middleware: express.Express = usfCreateMiddlewareSpy.calls.mostRecent().returnValue;
|
||||
const middleware = usfCreateMiddlewareSpy.calls.mostRecent().returnValue;
|
||||
expect(httpCreateServerSpy).toHaveBeenCalledWith(middleware);
|
||||
});
|
||||
|
||||
@ -230,7 +229,7 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
expect(prsAddCommentSpy).toHaveBeenCalledTimes(2);
|
||||
expect(prs).toBe(allCalls[1].object);
|
||||
expect(prs).toEqual(jasmine.any(GithubPullRequests));
|
||||
expect(prs).toBeInstanceOf(GithubPullRequests);
|
||||
expect(prs.repoSlug).toBe('organisation/repo');
|
||||
});
|
||||
|
||||
@ -302,9 +301,8 @@ describe('PreviewServerFactory', () => {
|
||||
let bvGetSignificantFilesChangedSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
bvGetPrIsTrustedSpy = spyOn(buildVerifier, 'getPrIsTrusted').and.returnValue(Promise.resolve(true));
|
||||
bvGetSignificantFilesChangedSpy = spyOn(buildVerifier, 'getSignificantFilesChanged').
|
||||
and.returnValue(Promise.resolve(true));
|
||||
bvGetPrIsTrustedSpy = spyOn(buildVerifier, 'getPrIsTrusted').and.resolveTo(true);
|
||||
bvGetSignificantFilesChangedSpy = spyOn(buildVerifier, 'getSignificantFilesChanged').and.resolveTo(true);
|
||||
});
|
||||
|
||||
|
||||
@ -331,7 +329,7 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should respond appropriately if the PR did not touch any significant files', async () => {
|
||||
bvGetSignificantFilesChangedSpy.and.returnValue(Promise.resolve(false));
|
||||
bvGetSignificantFilesChangedSpy.and.resolveTo(false);
|
||||
|
||||
const expectedResponse = {canHavePublicPreview: false, reason: 'No significant files touched.'};
|
||||
const expectedLog = `PR:${pr} - Cannot have a public preview, because it did not touch any significant files.`;
|
||||
@ -345,7 +343,7 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should respond appropriately if the PR is not automatically verifiable as "trusted"', async () => {
|
||||
bvGetPrIsTrustedSpy.and.returnValue(Promise.resolve(false));
|
||||
bvGetPrIsTrustedSpy.and.resolveTo(false);
|
||||
|
||||
const expectedResponse = {canHavePublicPreview: false, reason: 'Not automatically verifiable as "trusted".'};
|
||||
const expectedLog =
|
||||
@ -372,7 +370,7 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should respond with error if `getSignificantFilesChanged()` fails', async () => {
|
||||
bvGetSignificantFilesChangedSpy.and.callFake(() => Promise.reject('getSignificantFilesChanged error'));
|
||||
bvGetSignificantFilesChangedSpy.and.rejectWith('getSignificantFilesChanged error');
|
||||
|
||||
await agent.get(url).expect(500, 'getSignificantFilesChanged error');
|
||||
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', 'getSignificantFilesChanged error');
|
||||
@ -380,11 +378,10 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should respond with error if `getPrIsTrusted()` fails', async () => {
|
||||
const error = new Error('getPrIsTrusted error');
|
||||
bvGetPrIsTrustedSpy.and.callFake(() => { throw error; });
|
||||
bvGetPrIsTrustedSpy.and.throwError('getPrIsTrusted error');
|
||||
|
||||
await agent.get(url).expect(500, 'getPrIsTrusted error');
|
||||
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', error);
|
||||
expect(loggerErrorSpy).toHaveBeenCalledWith('Previewability check error', new Error('getPrIsTrusted error'));
|
||||
});
|
||||
|
||||
});
|
||||
@ -497,7 +494,7 @@ describe('PreviewServerFactory', () => {
|
||||
// Note it is important to put the `reject` into `and.callFake`;
|
||||
// If you just `and.returnValue` the rejected promise
|
||||
// then you get an "unhandled rejection" message in the console.
|
||||
getGithubInfoSpy.and.callFake(() => Promise.reject('Test Error'));
|
||||
getGithubInfoSpy.and.rejectWith('Test Error');
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
|
||||
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
|
||||
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
|
||||
@ -518,7 +515,7 @@ describe('PreviewServerFactory', () => {
|
||||
});
|
||||
|
||||
it('should fail if the artifact fetch request fails', async () => {
|
||||
downloadBuildArtifactSpy.and.callFake(() => Promise.reject('Test Error'));
|
||||
downloadBuildArtifactSpy.and.rejectWith('Test Error');
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
|
||||
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
|
||||
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
|
||||
@ -527,7 +524,7 @@ describe('PreviewServerFactory', () => {
|
||||
});
|
||||
|
||||
it('should fail if verifying the PR fails', async () => {
|
||||
getPrIsTrustedSpy.and.callFake(() => Promise.reject('Test Error'));
|
||||
getPrIsTrustedSpy.and.rejectWith('Test Error');
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
|
||||
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
|
||||
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
|
||||
@ -536,7 +533,7 @@ describe('PreviewServerFactory', () => {
|
||||
});
|
||||
|
||||
it('should fail if creating the preview build fails', async () => {
|
||||
createBuildSpy.and.callFake(() => Promise.reject('Test Error'));
|
||||
createBuildSpy.and.rejectWith('Test Error');
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(500, 'Test Error');
|
||||
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
|
||||
expect(downloadBuildArtifactSpy).toHaveBeenCalled();
|
||||
@ -605,7 +602,7 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should propagate errors from BuildVerifier', async () => {
|
||||
bvGetPrIsTrustedSpy.and.callFake(() => Promise.reject('Test'));
|
||||
bvGetPrIsTrustedSpy.and.rejectWith('Test');
|
||||
|
||||
await createRequest(+pr).expect(500, 'Test');
|
||||
|
||||
@ -615,7 +612,9 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should call \'BuildCreator#updatePrVisibility()\' with the correct arguments', async () => {
|
||||
bvGetPrIsTrustedSpy.and.callFake((pr2: number) => Promise.resolve(pr2 === 42));
|
||||
bvGetPrIsTrustedSpy.
|
||||
withArgs(24).and.resolveTo(false).
|
||||
withArgs(42).and.resolveTo(true);
|
||||
|
||||
await createRequest(24);
|
||||
expect(bcUpdatePrVisibilitySpy).toHaveBeenCalledWith(24, false);
|
||||
@ -626,7 +625,7 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should propagate errors from BuildCreator', async () => {
|
||||
bcUpdatePrVisibilitySpy.and.callFake(() => Promise.reject('Test'));
|
||||
bcUpdatePrVisibilitySpy.and.rejectWith('Test');
|
||||
await createRequest(+pr).expect(500, 'Test');
|
||||
});
|
||||
|
||||
@ -634,7 +633,9 @@ describe('PreviewServerFactory', () => {
|
||||
describe('on success', () => {
|
||||
|
||||
it('should respond with 200 (action: undefined)', async () => {
|
||||
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
|
||||
bvGetPrIsTrustedSpy.
|
||||
withArgs(2).and.resolveTo(false).
|
||||
withArgs(4).and.resolveTo(true);
|
||||
|
||||
const reqs = [4, 2].map(num => createRequest(num).expect(200, http.STATUS_CODES[200]));
|
||||
await Promise.all(reqs);
|
||||
@ -642,7 +643,9 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should respond with 200 (action: labeled)', async () => {
|
||||
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
|
||||
bvGetPrIsTrustedSpy.
|
||||
withArgs(2).and.resolveTo(false).
|
||||
withArgs(4).and.resolveTo(true);
|
||||
|
||||
const reqs = [4, 2].map(num => createRequest(num, 'labeled').expect(200, http.STATUS_CODES[200]));
|
||||
await Promise.all(reqs);
|
||||
@ -650,7 +653,9 @@ describe('PreviewServerFactory', () => {
|
||||
|
||||
|
||||
it('should respond with 200 (action: unlabeled)', async () => {
|
||||
bvGetPrIsTrustedSpy.and.returnValues(Promise.resolve(true), Promise.resolve(false));
|
||||
bvGetPrIsTrustedSpy.
|
||||
withArgs(2).and.resolveTo(false).
|
||||
withArgs(4).and.resolveTo(true);
|
||||
|
||||
const reqs = [4, 2].map(num => createRequest(num, 'unlabeled').expect(200, http.STATUS_CODES[200]));
|
||||
await Promise.all(reqs);
|
||||
|
@ -39,7 +39,7 @@ describe('preview-server/utils', () => {
|
||||
throwRequestError(505, 'ERROR MESSAGE', request);
|
||||
} catch (error) {
|
||||
caught = true;
|
||||
expect(error).toEqual(jasmine.any(PreviewServerError));
|
||||
expect(error).toBeInstanceOf(PreviewServerError);
|
||||
expect(error.status).toEqual(505);
|
||||
expect(error.message).toEqual(`ERROR MESSAGE in request: POST some.domain.com/path "The request body"`);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,10 +8,32 @@ exitCode=0
|
||||
|
||||
|
||||
# Helpers
|
||||
function checkCert {
|
||||
local certPath=$1
|
||||
|
||||
if [[ ! -f "$certPath" ]]; then
|
||||
echo "Certificate '$certPath' does not exist. Skipping expiration check..."
|
||||
return
|
||||
fi
|
||||
|
||||
openssl x509 -checkend 0 -in "$certPath" -noout > /dev/null
|
||||
reportStatus "Certificate '$certPath'"
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo " [WARN]"
|
||||
echo " If you did not provide the certificate explicitly, try running the"
|
||||
echo " 'docker build' command again with the '--no-cache' option to generate"
|
||||
echo " a new self-signed certificate."
|
||||
fi
|
||||
}
|
||||
|
||||
function reportStatus {
|
||||
local lastExitCode=$?
|
||||
|
||||
echo "$1: $([[ $lastExitCode -eq 0 ]] && echo OK || echo NOT OK)"
|
||||
[[ $lastExitCode -eq 0 ]] || exitCode=1
|
||||
|
||||
return $lastExitCode
|
||||
}
|
||||
|
||||
|
||||
@ -28,6 +50,16 @@ for s in ${services[@]}; do
|
||||
done
|
||||
|
||||
|
||||
# Check SSL/TLS certificates expiration
|
||||
certs=(
|
||||
"$AIO_LOCALCERTS_DIR/$AIO_DOMAIN_NAME.crt"
|
||||
"$TEST_AIO_LOCALCERTS_DIR/$TEST_AIO_DOMAIN_NAME.crt"
|
||||
)
|
||||
for c in ${certs[@]}; do
|
||||
checkCert $c
|
||||
done
|
||||
|
||||
|
||||
# Check servers
|
||||
origins=(
|
||||
http://$AIO_PREVIEW_SERVER_HOSTNAME:$AIO_PREVIEW_SERVER_PORT
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
TODO (gkalpak): Add docs. Mention:
|
||||
- Testing on CI.
|
||||
Relevant files: `scripts/ci/test-aio.sh`, `aio/aio-builds-setup/scripts/test.sh`
|
||||
Relevant files: `aio/aio-builds-setup/scripts/test.sh`
|
||||
- Deploying from CI.
|
||||
Relevant files: `.circleci/config.yml`, `scripts/ci/deploy.sh`, `aio/scripts/build-artifacts.sh`,
|
||||
`aio/scripts/deploy-to-firebase.sh`
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
## Create `aio-builds` persistent disk (if not already exists)
|
||||
- Follow instructions [here](https://cloud.google.com/compute/docs/disks/add-persistent-disk#create_disk).
|
||||
- `sudo mkfs.ext4 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-aio-builds`
|
||||
- `sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-aio-builds`
|
||||
|
||||
|
||||
## Mount disk
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
## Mount disk on boot
|
||||
- Run:
|
||||
```
|
||||
```sh
|
||||
echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-aio-builds` \
|
||||
/mnt/disks/aio-builds ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab
|
||||
/mnt/disks/aio-builds ext4 defaults,discard,nofail 0 2 | sudo tee -a /etc/fstab
|
||||
```
|
||||
|
@ -1,10 +1,11 @@
|
||||
# VM setup - Create docker image
|
||||
|
||||
|
||||
## Install node and yarn
|
||||
- Install [nvm](https://github.com/creationix/nvm#installation).
|
||||
- Install node.js: `nvm install 8`
|
||||
- Install yarn: `npm -g install yarn`
|
||||
## Install git, Node.js and yarn
|
||||
- `sudo apt-get update`
|
||||
- `sudo apt-get install -y git`
|
||||
- Install the latest stable version of [Node.js](https://nodejs.org/en/download).
|
||||
- Install the latest stable version of [yarn](https://classic.yarnpkg.com/en/docs/install).
|
||||
|
||||
|
||||
## Checkout repository
|
||||
@ -16,7 +17,11 @@
|
||||
- You can overwrite the default environment variables inside the image, by passing new values using
|
||||
`--build-arg`.
|
||||
|
||||
**Note:** The script has to execute docker commands with `sudo`.
|
||||
**Note 1:** The script has to execute docker commands with `sudo`.
|
||||
|
||||
**Note 2:**
|
||||
The script has to execute `yarn` commands, so make sure `yarn` is on the `PATH` when invoking the
|
||||
script.
|
||||
|
||||
|
||||
## Example
|
||||
@ -26,7 +31,7 @@ The following commands would create a docker image from GitHub repo `foo/bar` to
|
||||
|
||||
- `git clone https://github.com/foo/bar.git foobar`
|
||||
- Run:
|
||||
```
|
||||
```sh
|
||||
./foobar/aio-builds-setup/scripts/create-image.sh foobar-builds \
|
||||
--build-arg AIO_REPO_SLUG=foo/bar \
|
||||
--build-arg AIO_DOMAIN_NAME=foobar-builds.io \
|
||||
|
@ -3,24 +3,17 @@
|
||||
|
||||
## Install docker
|
||||
|
||||
_Debian (jessie):_
|
||||
- `sudo apt-get update`
|
||||
- `sudo apt-get install -y apt-transport-https ca-certificates curl git software-properties-common`
|
||||
- `curl -fsSL https://apt.dockerproject.org/gpg | sudo apt-key add -`
|
||||
- `apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D`
|
||||
- `sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ debian-$(lsb_release -cs) main"`
|
||||
- `sudo apt-get update`
|
||||
- `sudo apt-get -y install docker-engine`
|
||||
Official installation instructions: https://docs.docker.com/engine/install
|
||||
Example:
|
||||
|
||||
_Ubuntu (16.04):_
|
||||
_Debian (buster):_
|
||||
- `sudo apt-get update`
|
||||
- `sudo apt-get install -y curl git linux-image-extra-$(uname -r) linux-image-extra-virtual`
|
||||
- `sudo apt-get install -y apt-transport-https ca-certificates`
|
||||
- `curl -fsSL https://yum.dockerproject.org/gpg | sudo apt-key add -`
|
||||
- `apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D`
|
||||
- `sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ ubuntu-$(lsb_release -cs) main"`
|
||||
- `sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common`
|
||||
- `curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -`
|
||||
- `sudo apt-key fingerprint 0EBFCD88`
|
||||
- `sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"`
|
||||
- `sudo apt-get update`
|
||||
- `sudo apt-get -y install docker-engine`
|
||||
- `sudo apt-get -y install docker-ce docker-ce-cli containerd.io`
|
||||
|
||||
|
||||
## Start the docker
|
||||
|
@ -8,16 +8,16 @@ VM host to update the preview server based on changes in the source code.
|
||||
|
||||
The script will pull the latest changes from the origin's master branch and examine if there have
|
||||
been any changes in files inside the preview server source code directory (see below). If there are,
|
||||
it will create a new image and verify that is works as expected. Finally, it will stop and remove
|
||||
it will create a new image and verify that it works as expected. Finally, it will stop and remove
|
||||
the old docker container and image, create a new container based on the new image and start it.
|
||||
|
||||
The script assumes that the preview server source code is in the repository's
|
||||
`aio/aio-builds-setup/` directory and expects the following inputs:
|
||||
|
||||
- **$1**: `HOST_REPO_DIR`
|
||||
- **$2**: `HOST_LOCALCERTS_DIR`
|
||||
- **$3**: `HOST_SECRETS_DIR`
|
||||
- **$4**: `HOST_BUILDS_DIR`
|
||||
- **$2**: `HOST_SECRETS_DIR`
|
||||
- **$3**: `HOST_BUILDS_DIR`
|
||||
- **$4**: `HOST_LOCALCERTS_DIR`
|
||||
- **$5**: `HOST_LOGS_DIR`
|
||||
|
||||
See [here](vm-setup--create-host-dirs-and-files.md) for more info on what each input directory is
|
||||
@ -25,28 +25,38 @@ used for.
|
||||
|
||||
**Note 1:** The script has to execute docker commands with `sudo`.
|
||||
|
||||
**Note 2:** Make sure the user that executes the script has access to update the repository
|
||||
**Note 2:**
|
||||
The script has to execute `yarn` commands, so make sure `yarn` is on the `PATH` when invoking the
|
||||
script.
|
||||
|
||||
**Note 3:** Make sure the user that executes the script has access to update the repository.
|
||||
|
||||
|
||||
## Run the script manually
|
||||
You may choose to manually run the script, when necessary. Example:
|
||||
|
||||
```
|
||||
```sh
|
||||
update-preview-server.sh \
|
||||
/path/to/repo \
|
||||
/path/to/localcerts \
|
||||
/path/to/secrets \
|
||||
/path/to/builds \
|
||||
/path/to/localcerts \
|
||||
/path/to/logs
|
||||
```
|
||||
|
||||
|
||||
## Run the script automatically
|
||||
You may choose to automatically trigger the script, e.g. using a cronjob. For example, the following
|
||||
cronjob entry would run the script every hour and update the preview server (assuming the user has
|
||||
the necessary permissions):
|
||||
cronjob entry would run the script every 30 minutes, update the preview server (if necessary) and
|
||||
log its output to `update-preview-server.log` (assuming the user has the necessary permissions):
|
||||
|
||||
```
|
||||
# Periodically check for changes and update the preview server (if necessary)
|
||||
*/30 * * * * /path/to/update-preview-server.sh /path/to/repo /path/to/localcerts /path/to/secrets /path/to/builds /path/to/logs
|
||||
*/30 * * * * /path/to/update-preview-server.sh /path/to/repo /path/to/secrets /path/to/builds /path/to/localcerts /path/to/logs >> /path/to/update-preview-server.log 2>&1
|
||||
```
|
||||
|
||||
**Note:**
|
||||
Keep in mind that cron jobs run in non-interactive, non-login shells. This means that the execution
|
||||
context might be different compared to when running the same commands from an interactive, login
|
||||
shell. For example, `.bashrc` files are normally _not_ sourced automatically in cron jobs. See
|
||||
[here](http://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html) for more info.
|
||||
|
@ -7,13 +7,14 @@ echo -e "\n\n[`date`] - Updating the preview server..."
|
||||
|
||||
# Input
|
||||
readonly HOST_REPO_DIR=$1
|
||||
readonly HOST_LOCALCERTS_DIR=$2
|
||||
readonly HOST_SECRETS_DIR=$3
|
||||
readonly HOST_BUILDS_DIR=$4
|
||||
readonly HOST_SECRETS_DIR=$2
|
||||
readonly HOST_BUILDS_DIR=$3
|
||||
readonly HOST_LOCALCERTS_DIR=$4
|
||||
readonly HOST_LOGS_DIR=$5
|
||||
|
||||
# Constants
|
||||
readonly PROVISIONAL_IMAGE_NAME=aio-builds:provisional
|
||||
readonly PROVISIONAL_TAG=provisional
|
||||
readonly PROVISIONAL_IMAGE_NAME=aio-builds:$PROVISIONAL_TAG
|
||||
readonly LATEST_IMAGE_NAME=aio-builds:latest
|
||||
readonly CONTAINER_NAME=aio
|
||||
|
||||
@ -30,7 +31,7 @@ readonly CONTAINER_NAME=aio
|
||||
# Do not update the server unless files inside `aio-builds-setup/` have changed
|
||||
# or the last attempt failed (identified by the provisional image still being around).
|
||||
readonly relevantChangedFilesCount=$(git diff --name-only $lastDeployedCommit...HEAD | grep -P "^aio/aio-builds-setup/" | wc -l)
|
||||
readonly lastAttemptFailed=$(sudo docker rmi "$PROVISIONAL_IMAGE_NAME" >> /dev/fd/3 && echo "true" || echo "false")
|
||||
readonly lastAttemptFailed=$(sudo docker image ls | grep "$PROVISIONAL_TAG" >> /dev/fd/3 && echo "true" || echo "false")
|
||||
if [[ $relevantChangedFilesCount -eq 0 ]] && [[ "$lastAttemptFailed" != "true" ]]; then
|
||||
echo "Skipping update because no relevant files have been touched."
|
||||
exit 0
|
||||
@ -60,9 +61,9 @@ readonly CONTAINER_NAME=aio
|
||||
--publish 80:80 \
|
||||
--publish 443:443 \
|
||||
--restart unless-stopped \
|
||||
--volume $HOST_LOCALCERTS_DIR:/etc/ssl/localcerts:ro \
|
||||
--volume $HOST_SECRETS_DIR:/aio-secrets:ro \
|
||||
--volume $HOST_BUILDS_DIR:/var/www/aio-builds \
|
||||
--volume $HOST_LOCALCERTS_DIR:/etc/ssl/localcerts:ro \
|
||||
--volume $HOST_LOGS_DIR:/var/log/aio \
|
||||
"$LATEST_IMAGE_NAME"
|
||||
|
||||
|
110
aio/angular.json
110
aio/angular.json
@ -1,8 +1,12 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"cli": {
|
||||
"packageManager": "yarn"
|
||||
"packageManager": "yarn",
|
||||
"warnings": {
|
||||
"typescriptMismatch": false
|
||||
},
|
||||
"analytics": false
|
||||
},
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
@ -10,6 +14,13 @@
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"prefix": "aio",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"inlineStyle": true,
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
@ -17,7 +28,9 @@
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"webWorkerTsConfig": "tsconfig.worker.json",
|
||||
"aot": true,
|
||||
"optimization": true,
|
||||
"buildOptimizer": true,
|
||||
@ -28,11 +41,9 @@
|
||||
"extractLicenses": true,
|
||||
"namedChunks": true,
|
||||
"vendorChunk": false,
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"assets": [
|
||||
"src/assets",
|
||||
"src/generated",
|
||||
"src/app/search/search-worker.js",
|
||||
"src/pwa-manifest.json",
|
||||
"src/google385281288605d160.html",
|
||||
{
|
||||
@ -49,7 +60,13 @@
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
"scripts": [],
|
||||
"budgets": [
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"fast": {
|
||||
@ -58,8 +75,8 @@
|
||||
"next": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"src": "src/environments/environment.ts",
|
||||
"replaceWith": "src/environments/environment.next.ts"
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.next.ts"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
@ -67,8 +84,8 @@
|
||||
"stable": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"src": "src/environments/environment.ts",
|
||||
"replaceWith": "src/environments/environment.stable.ts"
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.stable.ts"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
@ -76,11 +93,14 @@
|
||||
"archive": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"src": "src/environments/environment.ts",
|
||||
"replaceWith": "src/environments/environment.archive.ts"
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.archive.ts"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
},
|
||||
"ci": {
|
||||
"progress": false
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -101,6 +121,9 @@
|
||||
},
|
||||
"archive": {
|
||||
"browserTarget": "site:build:archive"
|
||||
},
|
||||
"ci": {
|
||||
"browserTarget": "site:build:ci"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -114,17 +137,13 @@
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"scripts": [],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"webWorkerTsConfig": "tsconfig.worker.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/assets",
|
||||
"src/generated",
|
||||
"src/app/search/search-worker.js",
|
||||
"src/pwa-manifest.json",
|
||||
"src/google385281288605d160.html",
|
||||
{
|
||||
@ -137,54 +156,41 @@
|
||||
"input": "node_modules/@webcomponents/custom-elements/src",
|
||||
"output": "/assets/js"
|
||||
}
|
||||
]
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"src/tsconfig.app.json",
|
||||
"src/tsconfig.spec.json"
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"tsconfig.worker.json",
|
||||
"tests/e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": []
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"site-e2e": {
|
||||
"root": "",
|
||||
"projectType": "application",
|
||||
"cli": {},
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "tests/e2e/protractor.conf.js",
|
||||
"devServerTarget": "site:serve"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tests/e2e/tsconfig.e2e.json"
|
||||
],
|
||||
"exclude": []
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"devServerTarget": "site:serve:ci"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"inlineStyle": true,
|
||||
"prefix": "aio",
|
||||
"styleext": "scss"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"prefix": "aio"
|
||||
}
|
||||
}
|
||||
}
|
||||
"defaultProject": "site"
|
||||
}
|
@ -1,83 +1,111 @@
|
||||
<h1 class="no-toc">CLI Command Reference</h1>
|
||||
# CLI Overview and Command Reference
|
||||
|
||||
The Angular CLI is a command-line tool that you use to initialize, develop, scaffold, and maintain Angular applications.
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications. You can use the tool directly in a command shell, or indirectly through an interactive UI such as [Angular Console](https://angularconsole.com).
|
||||
|
||||
## Getting Started
|
||||
## Installing Angular CLI
|
||||
|
||||
### Installing Angular CLI
|
||||
Major versions of Angular CLI follow the supported major version of Angular, but minor versions can be released separately.
|
||||
|
||||
The current version of Angular CLI is 6.x.
|
||||
Install the CLI using the `npm` package manager:
|
||||
<code-example language="bash">
|
||||
npm install -g @angular/cli
|
||||
</code-example>
|
||||
|
||||
* Both the CLI and the projects that you generate with the tool have dependencies that require Node 8.9 or higher, together with NPM 5.5.1 or higher.
|
||||
* Install the CLI using npm:
|
||||
`npm install -g @angular/cli`
|
||||
* The CLI is an open-source tool:
|
||||
https://github.com/angular/angular-cli/tree/master/packages/angular/cli
|
||||
For details about changes between versions, and information about updating from previous releases,
|
||||
see the Releases tab on GitHub: https://github.com/angular/angular-cli/releases
|
||||
|
||||
For details about changes between versions, and information about updating from previous releases, see the Releases tab on GitHub.
|
||||
## Basic workflow
|
||||
|
||||
### Basic workflow
|
||||
Invoke the tool on the command line through the `ng` executable.
|
||||
Online help is available on the command line.
|
||||
Enter the following to list commands or options for a given command (such as [generate](cli/generate)) with a short description.
|
||||
|
||||
Invoke the tool on the command line through the ng executable. Online help is available on the command line:
|
||||
<code-example language="bash">
|
||||
ng help
|
||||
ng generate --help
|
||||
</code-example>
|
||||
|
||||
```
|
||||
> ng help Lists commands with short descriptions
|
||||
> ng <command> --help Lists options for a command.
|
||||
```
|
||||
To create, build, and serve a new, basic Angular project on a development server, go to the parent directory of your new workspace use the following commands:
|
||||
|
||||
To create, build, and serve a new, basic Angular project on a development server, use the following commands:
|
||||
|
||||
```
|
||||
cd <parent of new workspace>
|
||||
ng new my-project
|
||||
cd my-project
|
||||
<code-example language="bash">
|
||||
ng new my-first-project
|
||||
cd my-first-project
|
||||
ng serve
|
||||
```
|
||||
</code-example>
|
||||
|
||||
In your browser, open http://localhost:4200/ to see the new app run.
|
||||
When you use the [ng serve](cli/serve) command to build an app and serve it locally, the server automatically rebuilds the app and reloads the page when you change any of the source files.
|
||||
|
||||
### Workspaces and project files
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Angular 6 introduced the workspace directory structure for Angular apps. A workspace defines a project. A project can contain multiple apps, as well as libraries that can be used in any of the apps.
|
||||
When you run `ng new my-first-project` a new folder, named `my-first-project`, will be created in the current working directory. Since you want to be able to create files inside that folder, make sure you have sufficient rights in the current working directory before running the command.
|
||||
|
||||
Some commands (such as build) must be executed from within a workspace folder, and others (such as new) must be executed from outside any workspace. This requirement is called out in the description of each command where it applies.The `new` command creates a [workspace](guide/glossary#workspace) to contain [projects](guide/glossary#project). A project can be an app or a library, and a workspace can contain multiple apps and libraries.
|
||||
If the current working directory is not the right place for your project, you can change to a more appropriate directory by running `cd <path-to-other-directory>` first.
|
||||
|
||||
A newly generated app project contains the source files for a root module, with a root component and template, which you can edit directly, or add to and modify using CLI commands. Use the generate command to add new files for additional components and services, and code for new pipes, directives, and so on.
|
||||
</div>
|
||||
|
||||
* Commands such as `add` and `generate`, that create or operate on apps and libraries, must be executed from within a workspace folder.
|
||||
* Apps in a workspace can use libraries in the same workspace.
|
||||
* Each project has a `src` folder that contains the logic, data, and assets.
|
||||
See an example of the [file structure](guide/quickstart#project-file-review) in [Getting Started](guide/quickstart).
|
||||
## Workspaces and project files
|
||||
|
||||
When you use the `serve` command to build an app, the server automatically rebuilds the app and reloads the page when you change any of the source files.
|
||||
The [ng new](cli/new) command creates an *Angular workspace* folder and generates a new app skeleton.
|
||||
A workspace can contain multiple apps and libraries.
|
||||
The initial app created by the [ng new](cli/new) command is at the top level of the workspace.
|
||||
When you generate an additional app or library in a workspace, it goes into a `projects/` subfolder.
|
||||
|
||||
### Configuring the CLI
|
||||
A newly generated app contains the source files for a root module, with a root component and template.
|
||||
Each app has a `src` folder that contains the logic, data, and assets.
|
||||
|
||||
Configuration files let you customize your project. The CLI configuration file, angular.json, is created at the top level of the project folder. This is where you can set CLI defaults for your project, and specify which files to include when the CLI builds the project.
|
||||
You can edit the generated files directly, or add to and modify them using CLI commands.
|
||||
Use the [ng generate](cli/generate) command to add new files for additional components and services, and code for new pipes, directives, and so on.
|
||||
Commands such as [add](cli/add) and [generate](cli/generate), which create or operate on apps and libraries, must be executed from within a workspace or project folder.
|
||||
|
||||
The CLI config command lets you set and retrieve configuration values from the command line, or you can edit the angular.json file directly.
|
||||
* See more about the [Workspace file structure](guide/file-structure).
|
||||
|
||||
* See the complete schema for angular.json.
|
||||
* Learn more about configuration options for Angular (link to new guide?)
|
||||
### Workspace and project configuration
|
||||
|
||||
### Command options and arguments
|
||||
A single workspace configuration file, `angular.json`, is created at the top level of the workspace.
|
||||
This is where you can set per-project defaults for CLI command options, and specify configurations to use when the CLI builds a project for different targets.
|
||||
|
||||
All commands and some options have aliases, as listed in the descriptions. Option names are prefixed with a double dash (--), but arguments and option aliases are not.
|
||||
The [ng config](cli/config) command lets you set and retrieve configuration values from the command line, or you can edit the `angular.json` file directly.
|
||||
Note that option names in the configuration file must use [camelCase](guide/glossary#case-types), while option names supplied to commands can use either camelCase or dash-case.
|
||||
|
||||
Typically, the name of a generated artifact can be given as an argument to the command or specified with the --name option. Most commands have additional options.
|
||||
* See more about [Workspace Configuration](guide/workspace-config).
|
||||
* See the [complete schema](https://github.com/angular/angular-cli/wiki/angular-workspace) for `angular.json`.
|
||||
|
||||
## CLI command-language syntax
|
||||
|
||||
Command syntax is shown as follows:
|
||||
|
||||
```
|
||||
ng commandNameOrAlias <arg> [options]
|
||||
```
|
||||
`ng` *commandNameOrAlias* *requiredArg* [*optionalArg*] `[options]`
|
||||
|
||||
Options take either string or Boolean arguments. Defaults are shown in bold for Boolean or enumerated values, and are given with the description. For example:
|
||||
* Most commands, and some options, have aliases. Aliases are shown in the syntax statement for each command.
|
||||
|
||||
```
|
||||
--optionNameOrAlias=<filename>
|
||||
--optionNameOrAlias=true|false
|
||||
--optionNameOrAlias=allowedValue1|allowedValue2|allowedValue3
|
||||
```
|
||||
* Option names are prefixed with a double dash (--).
|
||||
Option aliases are prefixed with a single dash (-).
|
||||
Arguments are not prefixed.
|
||||
For example:
|
||||
<code-example language="bash">
|
||||
ng build my-app -c production
|
||||
</code-example>
|
||||
|
||||
Boolean options can also be expressed with a prefix `no-` to indicate a value of false. For example, `--no-prod` is equivalent to `--prod=false`.
|
||||
* Typically, the name of a generated artifact can be given as an argument to the command or specified with the --name option.
|
||||
|
||||
* Argument and option names can be given in either
|
||||
[camelCase or dash-case](guide/glossary#case-types).
|
||||
`--myOptionName` is equivalent to `--my-option-name`.
|
||||
|
||||
### Boolean and enumerated options
|
||||
|
||||
Boolean options have two forms: `--thisOption` sets the flag, `--noThisOption` clears it.
|
||||
If neither option is supplied, the flag remains in its default state, as listed in the reference documentation.
|
||||
|
||||
Allowed values are given with each enumerated option description, with the default value in **bold**.
|
||||
|
||||
### Relative paths
|
||||
|
||||
Options that specify files can be given as absolute paths, or as paths relative to the current working directory, which is generally either the workspace or project root.
|
||||
|
||||
### Schematics
|
||||
|
||||
The [ng generate](cli/generate) and [ng add](cli/add) commands take as an argument the artifact or library to be generated or added to the current project.
|
||||
In addition to any general options, each artifact or library defines its own options in a *schematic*.
|
||||
Schematic options are supplied to the command in the same format as immediate command options.
|
||||
|
48
aio/content/cli/usage-analytics-gathering.md
Normal file
48
aio/content/cli/usage-analytics-gathering.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Gathering and Viewing Usage Analytics
|
||||
|
||||
Users can opt in to share their Angular CLI usage data with [Google Analytics](https://support.google.com/analytics/answer/1008015?hl=en), using the [`ng analytics` CLI command](analytics).
|
||||
The data is also shared with the Angular team, and used to improve the CLI.
|
||||
|
||||
The gathering of CLI analytics data is disabled by default, and must be enabled at the project level by individual users.
|
||||
It cannot be enabled at the project level for all users.
|
||||
|
||||
Data gathered in this way can be viewed on the Google Analytics site, but is not automatically visible on your own organization's Analytics site.
|
||||
As an administrator for an Angular development group, you can configure your instance of Angular CLI to be able to see analytics data for your own team's usage of the Angular CLI.
|
||||
This configuration option is separate from and in addition to other usage analytics that your users may be sharing with Google.
|
||||
|
||||
## Enable access to CLI usage data
|
||||
|
||||
To configure access to your own users' CLI usage data, use the `ng config` command to add a key to your global [`angular.json` workspace configuration file](guide/workspace-config).
|
||||
The key goes under `cli.analyticsSharing` at the top level of the file, outside the `projects` sections.
|
||||
The value of the key is your organization's tracking ID, as assigned by Google Analytics.
|
||||
This ID is a string that looks like `UA-123456-12`.
|
||||
|
||||
You can choose to use a descriptive string as the key value, or be assigned a random key when you run the CLI command.
|
||||
For example, the following command adds a configuration key named "tracking".
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng config --global cli.analyticsSharing.tracking UA-123456-12
|
||||
</code-example>
|
||||
|
||||
To turn off this feature, run the following command:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng config --global --remove cli.analyticsSharing
|
||||
</code-example>
|
||||
|
||||
|
||||
## Per user tracking
|
||||
|
||||
You can add a custom user ID to the global configuration, in order to identify unique usage of commands and flags.
|
||||
If that user enables CLI analytics for their own project, your analytics display tracks and labels their individual usage.
|
||||
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng config --global cli.analyticsSharing.user SOME_USER_NAME
|
||||
</code-example>
|
||||
|
||||
To generate a new random user ID, run the following command:
|
||||
|
||||
<code-example language="sh" class="code-shell">
|
||||
ng config --global cli.analyticsSharing.user ""
|
||||
</code-example>
|
15
aio/content/examples/.gitignore
vendored
15
aio/content/examples/.gitignore
vendored
@ -23,6 +23,9 @@
|
||||
**/bs-config.e2e.json
|
||||
**/bs-config.json
|
||||
**/package.json
|
||||
**/tsconfig.json
|
||||
**/tsconfig.app.json
|
||||
**/tsconfig.spec.json
|
||||
**/tslint.json
|
||||
**/karma-test-shim.js
|
||||
**/browser-test-shim.js
|
||||
@ -57,7 +60,9 @@ dist/
|
||||
|
||||
# aot
|
||||
**/*.ngsummary.json
|
||||
upgrade-module/tsconfig-aot.json
|
||||
!rollup-config.js
|
||||
upgrade-module/rollup-config.js
|
||||
aot-compiler/**/*.d.ts
|
||||
aot-compiler/**/*.factory.d.ts
|
||||
upgrade-phonecat-2-hybrid/aot/**/*
|
||||
@ -77,12 +82,16 @@ upgrade-phonecat-2-hybrid/aot/**/*
|
||||
# styleguide
|
||||
!styleguide/src/systemjs.custom.js
|
||||
|
||||
# universal
|
||||
!universal/webpack.server.config.js
|
||||
|
||||
# stackblitz
|
||||
*stackblitz.no-link.html
|
||||
|
||||
# ngUpgrade testing
|
||||
upgrade-phonecat-1-typescript/tsconfig-aot.json
|
||||
upgrade-phonecat-1-typescript/rollup-config.js
|
||||
upgrade-phonecat-3-final/tsconfig-aot.json
|
||||
upgrade-phonecat-3-final/rollup-config.js
|
||||
!upgrade-phonecat-*/**/karma.conf.js
|
||||
!upgrade-phonecat-*/**/karma-test-shim.js
|
||||
|
||||
# schematics
|
||||
!schematics-for-libraries/projects/my-lib/package.json
|
||||
|
21
aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts
Normal file
21
aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict'; // necessary for es6 output in node
|
||||
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Accessibility example e2e tests', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it('should display Accessibility Example', function () {
|
||||
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
|
||||
});
|
||||
|
||||
it('should take a number and change progressbar width', function () {
|
||||
element(by.css('input')).sendKeys('16');
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
|
||||
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
||||
});
|
||||
|
||||
});
|
13
aio/content/examples/accessibility/src/app/app.component.html
Executable file
13
aio/content/examples/accessibility/src/app/app.component.html
Executable file
@ -0,0 +1,13 @@
|
||||
<h1>Accessibility Example</h1>
|
||||
<!-- #docregion template -->
|
||||
<label>
|
||||
Enter an example progress value
|
||||
<input type="number" min="0" max="100"
|
||||
[value]="progress" (input)="progress = $event.target.value">
|
||||
</label>
|
||||
|
||||
<!-- The user of the progressbar sets an aria-label to communicate what the progress means. -->
|
||||
<app-example-progressbar [value]="progress" aria-label="Example of a progress bar">
|
||||
</app-example-progressbar>
|
||||
<!-- #enddocregion template -->
|
||||
|
10
aio/content/examples/accessibility/src/app/app.component.ts
Executable file
10
aio/content/examples/accessibility/src/app/app.component.ts
Executable file
@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: [ './app.component.css' ]
|
||||
})
|
||||
export class AppComponent {
|
||||
progress = 0;
|
||||
}
|
12
aio/content/examples/accessibility/src/app/app.module.ts
Executable file
12
aio/content/examples/accessibility/src/app/app.module.ts
Executable file
@ -0,0 +1,12 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { ExampleProgressbarComponent } from './progress-bar.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule ],
|
||||
declarations: [ AppComponent, ExampleProgressbarComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
12
aio/content/examples/accessibility/src/app/progress-bar.component.css
Executable file
12
aio/content/examples/accessibility/src/app/progress-bar.component.css
Executable file
@ -0,0 +1,12 @@
|
||||
:host {
|
||||
display: block;
|
||||
width: 300px;
|
||||
height: 25px;
|
||||
border: 1px solid black;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.bar {
|
||||
background: blue;
|
||||
height: 100%;
|
||||
}
|
28
aio/content/examples/accessibility/src/app/progress-bar.component.ts
Executable file
28
aio/content/examples/accessibility/src/app/progress-bar.component.ts
Executable file
@ -0,0 +1,28 @@
|
||||
// #docregion progressbar-component
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Example progressbar component.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-example-progressbar',
|
||||
template: `<div class="bar" [style.width.%]="value"></div>`,
|
||||
styleUrls: ['./progress-bar.component.css'],
|
||||
host: {
|
||||
// Sets the role for this component to "progressbar"
|
||||
role: 'progressbar',
|
||||
|
||||
// Sets the minimum and maximum values for the progressbar role.
|
||||
'aria-valuemin': '0',
|
||||
'aria-valuemax': '100',
|
||||
|
||||
// Binding that updates the current value of the progressbar.
|
||||
'[attr.aria-valuenow]': 'value',
|
||||
}
|
||||
})
|
||||
export class ExampleProgressbarComponent {
|
||||
/** Current value of the progressbar. */
|
||||
@Input() value = 0;
|
||||
}
|
||||
|
||||
// #enddocregion progressbar-component
|
13
aio/content/examples/accessibility/src/index.html
Normal file
13
aio/content/examples/accessibility/src/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Accessibility Example</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root>Loading...</app-root>
|
||||
</body>
|
||||
</html>
|
9
aio/content/examples/accessibility/stackblitz.json
Normal file
9
aio/content/examples/accessibility/stackblitz.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Accessibility",
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1,2].*"
|
||||
],
|
||||
"tags": ["Accessibility"]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user