Compare commits
6373 Commits
ci/github-
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
80073944a1 | ||
![]() |
a2aa45d3c7 | ||
![]() |
0731c7f634 | ||
![]() |
cf2d40e359 | ||
![]() |
0c47b7184c | ||
![]() |
752100487b | ||
![]() |
7a183c9920 | ||
![]() |
eac35a64e1 | ||
![]() |
0348f47f62 | ||
![]() |
79da3e8cd2 | ||
![]() |
67b431603a | ||
![]() |
604bd6e1cb | ||
![]() |
fdf572b3c5 | ||
![]() |
f6936406ca | ||
![]() |
a4909d6aa0 | ||
![]() |
600af0a5f6 | ||
![]() |
a0fcc0b839 | ||
![]() |
cf6efd91ae | ||
![]() |
ee02855bd5 | ||
![]() |
53fd049d12 | ||
![]() |
a025e98ede | ||
![]() |
768f81627e | ||
![]() |
c2924a10e7 | ||
![]() |
5af3281103 | ||
![]() |
0496e59a10 | ||
![]() |
6f07ef5236 | ||
![]() |
0f9ed1d7d6 | ||
![]() |
3aa0ca984c | ||
![]() |
77832458c9 | ||
![]() |
e10a578603 | ||
![]() |
b142d33bbe | ||
![]() |
bcabf710d0 | ||
![]() |
a725fe261a | ||
![]() |
ebee38994f | ||
![]() |
6ebb0246ab | ||
![]() |
c7a054fa31 | ||
![]() |
6ff6acbb21 | ||
![]() |
8a09cb9794 | ||
![]() |
eeb59b4f4d | ||
![]() |
7afbc3a1c1 | ||
![]() |
3da8ebf27e | ||
![]() |
7e33d531ae | ||
![]() |
32577820f4 | ||
![]() |
3686c640d6 | ||
![]() |
cbe53247fa | ||
![]() |
bbbae1065a | ||
![]() |
b5c3bb998d | ||
![]() |
4ff7aeadbb | ||
![]() |
86eaf57d53 | ||
![]() |
ff7b7a9c2f | ||
![]() |
dea267e5c8 | ||
![]() |
07200be358 | ||
![]() |
45e6bb4a74 | ||
![]() |
b44f7b1a5c | ||
![]() |
3c9c40c4b7 | ||
![]() |
15bb08eea6 | ||
![]() |
10953bddcb | ||
![]() |
7b87a797ed | ||
![]() |
4ea5a19a10 | ||
![]() |
ee263f3b97 | ||
![]() |
f73846cd6b | ||
![]() |
b2fd28d2b0 | ||
![]() |
05535d985b | ||
![]() |
4dc8aa2a27 | ||
![]() |
3d084ac910 | ||
![]() |
f8678d7513 | ||
![]() |
c50136e2cb | ||
![]() |
c3b4e0f37e | ||
![]() |
4d33c41e92 | ||
![]() |
eff4e3e3c2 | ||
![]() |
e6c7536d62 | ||
![]() |
5f4a06039e | ||
![]() |
05b9bb71b1 | ||
![]() |
c7cae616e0 | ||
![]() |
14daffecc5 | ||
![]() |
f6ae7d4f49 | ||
![]() |
316d9d5c34 | ||
![]() |
ba99c7792a | ||
![]() |
66a2af0c77 | ||
![]() |
ab87527e1d | ||
![]() |
a0486577a8 | ||
![]() |
6f4c65c029 | ||
![]() |
295f3796c6 | ||
![]() |
6362ec46d5 | ||
![]() |
de2b1c4bb4 | ||
![]() |
6aad16e11f | ||
![]() |
78b657e8f3 | ||
![]() |
ee9e65ecb1 | ||
![]() |
5341121fde | ||
![]() |
265581e525 | ||
![]() |
06da025393 | ||
![]() |
317bbd8f46 | ||
![]() |
9cb99bbaa8 | ||
![]() |
8a70ac0950 | ||
![]() |
9956446ad7 | ||
![]() |
f0865de125 | ||
![]() |
5cb6779305 | ||
![]() |
1e2e9201b2 | ||
![]() |
6062e658db | ||
![]() |
eca92ea193 | ||
![]() |
3177ce1f35 | ||
![]() |
faa17f8959 | ||
![]() |
d42a09e9b6 | ||
![]() |
408d38b223 | ||
![]() |
333a1266cc | ||
![]() |
a4912ff297 | ||
![]() |
a9920d6776 | ||
![]() |
71b1f1ad88 | ||
![]() |
a198e2984c | ||
![]() |
e160d8466c | ||
![]() |
575479a6a1 | ||
![]() |
8b97de61f5 | ||
![]() |
d870e5c309 | ||
![]() |
2da56a70a2 | ||
![]() |
0b2f134680 | ||
![]() |
5d32a199a9 | ||
![]() |
f677c22fba | ||
![]() |
97ae2d3b9b | ||
![]() |
a3fe2de883 | ||
![]() |
7f6c3b3fc1 | ||
![]() |
ab4ab682e5 | ||
![]() |
a69cb738a8 | ||
![]() |
e9eeee5608 | ||
![]() |
d89ab70036 | ||
![]() |
fa82a82a07 | ||
![]() |
39f92d985b | ||
![]() |
da0129b83e | ||
![]() |
c980caecac | ||
![]() |
b88abd81c8 | ||
![]() |
201c38e407 | ||
![]() |
31c53670e7 | ||
![]() |
e169f00193 | ||
![]() |
e1ee231993 | ||
![]() |
7d4aebd603 | ||
![]() |
2cde8da71c | ||
![]() |
6f54c28c87 | ||
![]() |
17841959f5 | ||
![]() |
cfe5fadb3a | ||
![]() |
3cd4a5ded5 | ||
![]() |
36156244a1 | ||
![]() |
a66a804082 | ||
![]() |
d2524eef7f | ||
![]() |
f6d2af17fc | ||
![]() |
a86754b4c4 | ||
![]() |
2968435f81 | ||
![]() |
4096bbfeee | ||
![]() |
0314fd4b6e | ||
![]() |
3f2257f209 | ||
![]() |
271e0f9896 | ||
![]() |
79b5e1891d | ||
![]() |
b4b453d6de | ||
![]() |
06f085560c | ||
![]() |
38fb735551 | ||
![]() |
b0ecee8155 | ||
![]() |
ba46a0c05b | ||
![]() |
0112164c34 | ||
![]() |
f60fafbb2e | ||
![]() |
004079b07a | ||
![]() |
523a1a71d7 | ||
![]() |
d3999d904a | ||
![]() |
63894062d4 | ||
![]() |
5c60a65eaf | ||
![]() |
c387933d3c | ||
![]() |
882336e0e6 | ||
![]() |
e91aa6db32 | ||
![]() |
325b3fd0db | ||
![]() |
84348299b3 | ||
![]() |
e934864a90 | ||
![]() |
920205bc61 | ||
![]() |
0dcc34837e | ||
![]() |
57d8d7fcd4 | ||
![]() |
f26f014ffc | ||
![]() |
134aa72467 | ||
![]() |
a7a8938291 | ||
![]() |
9338556872 | ||
![]() |
28ef4bc441 | ||
![]() |
686f9ae4b2 | ||
![]() |
a57119761b | ||
![]() |
6881149540 | ||
![]() |
4f842e23df | ||
![]() |
47873a339a | ||
![]() |
03e02185d9 | ||
![]() |
e565d97bc8 | ||
![]() |
6bf8d2b356 | ||
![]() |
2981656ebe | ||
![]() |
5ec0ba72cd | ||
![]() |
f020941629 | ||
![]() |
f1a92872a4 | ||
![]() |
9e7ce2c916 | ||
![]() |
788532dc99 | ||
![]() |
54679ea9cc | ||
![]() |
cb0aeaf708 | ||
![]() |
8de04115ec | ||
![]() |
e65e5ea9d0 | ||
![]() |
19b577bf66 | ||
![]() |
ccb0b42ffb | ||
![]() |
1d46ef38d2 | ||
![]() |
06356d806a | ||
![]() |
45847c62ce | ||
![]() |
9cb6bb8535 | ||
![]() |
e9b25a1e98 | ||
![]() |
ad51b996a2 | ||
![]() |
8a05f311b9 | ||
![]() |
e72267bc00 | ||
![]() |
2e0973a814 | ||
![]() |
27092a822a | ||
![]() |
0cd8e48c36 | ||
![]() |
2b95289ee2 | ||
![]() |
5df5ce6463 | ||
![]() |
04ad0077f4 | ||
![]() |
1bf2f118c7 | ||
![]() |
2119abf954 | ||
![]() |
fc728d0cfb | ||
![]() |
dd01edd168 | ||
![]() |
7c3edad3d4 | ||
![]() |
445ac15a78 | ||
![]() |
856db56cca | ||
![]() |
354e66efad | ||
![]() |
702958e968 | ||
![]() |
df7f3b04b5 | ||
![]() |
7525f3afc1 | ||
![]() |
570d156ce4 | ||
![]() |
26be5b4994 | ||
![]() |
3821dc5f6c | ||
![]() |
18cd1a9937 | ||
![]() |
0551fbdf88 | ||
![]() |
dca4443a8e | ||
![]() |
2a745c8df8 | ||
![]() |
a18f82b458 | ||
![]() |
696a9b01ef | ||
![]() |
d7c043ba35 | ||
![]() |
0c2490368e | ||
![]() |
bb88c9fa3d | ||
![]() |
8227b56f9e | ||
![]() |
1609815743 | ||
![]() |
c4d76a65da | ||
![]() |
763023472b | ||
![]() |
ba175be41f | ||
![]() |
f0766a4474 | ||
![]() |
6f0f0d3ea2 | ||
![]() |
576e329f33 | ||
![]() |
585ef2bdd7 | ||
![]() |
2fcabe1557 | ||
![]() |
192ef42304 | ||
![]() |
8fbf40bf40 | ||
![]() |
8f074296c2 | ||
![]() |
e49b053dac | ||
![]() |
87baa06cc6 | ||
![]() |
db394e2b81 | ||
![]() |
ff9f4de4f1 | ||
![]() |
3a46c2da7c | ||
![]() |
bfd13c06e1 | ||
![]() |
5303773daf | ||
![]() |
ba11f7b90b | ||
![]() |
1db4f508e6 | ||
![]() |
6334749d2c | ||
![]() |
3c7359f026 | ||
![]() |
8aa29438ac | ||
![]() |
fc709423f2 | ||
![]() |
3012a8e71c | ||
![]() |
77f38d3be1 | ||
![]() |
7c0f11789b | ||
![]() |
0a791e4a50 | ||
![]() |
d89200ad24 | ||
![]() |
00b7186cb2 | ||
![]() |
e8896b9de3 | ||
![]() |
6f6102d8ad | ||
![]() |
4c7f233fa8 | ||
![]() |
fd51e01335 | ||
![]() |
3a525d196b | ||
![]() |
92c7145139 | ||
![]() |
1eebb7f189 | ||
![]() |
8effc83b92 | ||
![]() |
7f8c2225f2 | ||
![]() |
887c350f9d | ||
![]() |
103a95c182 | ||
![]() |
1b17722091 | ||
![]() |
b280d54470 | ||
![]() |
d96824acdb | ||
![]() |
9ebd461a22 | ||
![]() |
d8c07b83c3 | ||
![]() |
8f73169979 | ||
![]() |
3c0424e7e0 | ||
![]() |
de14b2c670 | ||
![]() |
c573d91285 | ||
![]() |
16c7441c2f | ||
![]() |
736f6337b2 | ||
![]() |
9c8bc4a239 | ||
![]() |
cf4da82ac3 | ||
![]() |
d133525502 | ||
![]() |
cd1817bf6d | ||
![]() |
0d1491b1a6 | ||
![]() |
f67774d84b | ||
![]() |
37668d159e | ||
![]() |
38554288f5 | ||
![]() |
04dcc3bceb | ||
![]() |
0910a2fc0d | ||
![]() |
3325cb2f86 | ||
![]() |
a1e8443bfb | ||
![]() |
599d34b41e | ||
![]() |
7fd1733882 | ||
![]() |
2e42123870 | ||
![]() |
4cbb90daf7 | ||
![]() |
57575e379f | ||
![]() |
28c3e2d15d | ||
![]() |
2a45b932e2 | ||
![]() |
5a12ab4a13 | ||
![]() |
8a543d8b50 | ||
![]() |
9893576ef0 | ||
![]() |
af80bdb470 | ||
![]() |
b4449e35bf | ||
![]() |
3d0be5213e | ||
![]() |
be3e7050d5 | ||
![]() |
cf98db28d5 | ||
![]() |
5621452ff0 | ||
![]() |
b0676e8fab | ||
![]() |
b142283ba2 | ||
![]() |
e79b6c31f9 | ||
![]() |
65cc0c8bd6 | ||
![]() |
03a6252123 | ||
![]() |
174aac68f7 | ||
![]() |
5d3ba8dec7 | ||
![]() |
fbe1a9cbaa | ||
![]() |
8f7d89436f | ||
![]() |
cf2663b034 | ||
![]() |
96aa14df01 | ||
![]() |
2b6ab57d78 | ||
![]() |
b65b6163f7 | ||
![]() |
f74cfadf64 | ||
![]() |
8e5969bb52 | ||
![]() |
8fdfa7b604 | ||
![]() |
2fdc18b42c | ||
![]() |
1296003445 | ||
![]() |
4dfc3fe6a2 | ||
![]() |
95681b16bd | ||
![]() |
67e3ecc7e3 | ||
![]() |
9821443150 | ||
![]() |
c91cdea0cd | ||
![]() |
6a3e68b606 | ||
![]() |
1822cbcd46 | ||
![]() |
a71f114ba4 | ||
![]() |
253337dc0a | ||
![]() |
6e2db228af | ||
![]() |
cce5583e75 | ||
![]() |
307db74e93 | ||
![]() |
88d4b269b5 | ||
![]() |
ee22aa592e | ||
![]() |
dd09fb5348 | ||
![]() |
d0060dcfdc | ||
![]() |
7b2e2f5d91 | ||
![]() |
b518b30dae | ||
![]() |
51aa4aa1c3 | ||
![]() |
8bb8f98c28 | ||
![]() |
e620827fa8 | ||
![]() |
3c1866b5bb | ||
![]() |
062b8d90af | ||
![]() |
8df888dfb4 | ||
![]() |
778ad3776a | ||
![]() |
5a733629b5 | ||
![]() |
65da87722d | ||
![]() |
937b89c230 | ||
![]() |
b3d81a837b | ||
![]() |
7491b854b3 | ||
![]() |
a1c9f7cdb3 | ||
![]() |
d88711c2fc | ||
![]() |
5e742d29d0 | ||
![]() |
970d10c671 | ||
![]() |
8851ba9c9d | ||
![]() |
7f82a2c1c8 | ||
![]() |
a9910f5991 | ||
![]() |
ad7046b934 | ||
![]() |
d72b1e44c6 | ||
![]() |
eae13e42f3 | ||
![]() |
3373453736 | ||
![]() |
4a6dcd006b | ||
![]() |
7c3c8d6d10 | ||
![]() |
655da32837 | ||
![]() |
5b31a0a294 | ||
![]() |
5d3d8b8330 | ||
![]() |
c8c74153b1 | ||
![]() |
9dc5e8e7e2 | ||
![]() |
1a7a7360b0 | ||
![]() |
8edf5ba29d | ||
![]() |
72f1eec3ad | ||
![]() |
136acdfab6 | ||
![]() |
095cfd961d | ||
![]() |
38a7021d5e | ||
![]() |
b3b03c35b5 | ||
![]() |
fd45f7485d | ||
![]() |
58f6079873 | ||
![]() |
e382632473 | ||
![]() |
cf9a47ba53 | ||
![]() |
56dd3e77ac | ||
![]() |
6c9401c338 | ||
![]() |
019a696a6a | ||
![]() |
8b25a64200 | ||
![]() |
bd71f10234 | ||
![]() |
e0b35bfc18 | ||
![]() |
c1539b16ae | ||
![]() |
737506e79c | ||
![]() |
469aba0140 | ||
![]() |
d8c47b971c | ||
![]() |
24b420527a | ||
![]() |
bf641e1b4b | ||
![]() |
406f801b70 | ||
![]() |
c8e77d8536 | ||
![]() |
6ea2d1e20e | ||
![]() |
09eee5b312 | ||
![]() |
904ebfebf3 | ||
![]() |
545f1dbac9 | ||
![]() |
b00121c9a6 | ||
![]() |
45d79efc3f | ||
![]() |
1d9e56eba0 | ||
![]() |
e7c722574f | ||
![]() |
b358495a6c | ||
![]() |
f4fac406b9 | ||
![]() |
5fd2c8f2d6 | ||
![]() |
421e807f80 | ||
![]() |
df8b387570 | ||
![]() |
f01b0337d2 | ||
![]() |
4ec3026a9a | ||
![]() |
9021d3f5e1 | ||
![]() |
81542b3b72 | ||
![]() |
9185c6e971 | ||
![]() |
69472a1ed0 | ||
![]() |
10aba15154 | ||
![]() |
36dd817913 | ||
![]() |
0eaa084ced | ||
![]() |
62e19c8813 | ||
![]() |
95669df4c3 | ||
![]() |
6b311552f0 | ||
![]() |
66947cf9fa | ||
![]() |
a259a84d3f | ||
![]() |
d1aa4678be | ||
![]() |
04c220bbdf | ||
![]() |
72d6032fa4 | ||
![]() |
53d4859f48 | ||
![]() |
f66f4a1b3f | ||
![]() |
88d68d2d21 | ||
![]() |
4783a071f3 | ||
![]() |
9322b9a060 | ||
![]() |
9bd4b74b06 | ||
![]() |
e6afcf1f94 | ||
![]() |
4b4b74548d | ||
![]() |
1550663b9e | ||
![]() |
c40cbecdd1 | ||
![]() |
209a365511 | ||
![]() |
fb735d625b | ||
![]() |
d19ef6534f | ||
![]() |
667aba7508 | ||
![]() |
d380e93b82 | ||
![]() |
2156beed0c | ||
![]() |
b98314e306 | ||
![]() |
e50c7dcc4c | ||
![]() |
6b731a067a | ||
![]() |
0a3dbc1e8a | ||
![]() |
b24a24ec58 | ||
![]() |
13ef5d6c7d | ||
![]() |
54373cc895 | ||
![]() |
bbe3543c69 | ||
![]() |
bdbbff6a1a | ||
![]() |
f81d3f6199 | ||
![]() |
d0c0f25a48 | ||
![]() |
1f796e9479 | ||
![]() |
1237d9cbea | ||
![]() |
b3969e9654 | ||
![]() |
6eb868b63a | ||
![]() |
82a2207f4a | ||
![]() |
289a96b078 | ||
![]() |
cb2ab26296 | ||
![]() |
79850983e6 | ||
![]() |
fc7e77934f | ||
![]() |
90b93da743 | ||
![]() |
ec32eba02c | ||
![]() |
596fbb3f06 | ||
![]() |
aed6b131bb | ||
![]() |
d148fdccf2 | ||
![]() |
1801d0c650 | ||
![]() |
a5c30733cb | ||
![]() |
d7dd2959c8 | ||
![]() |
a5ffca0576 | ||
![]() |
196bfa8fae | ||
![]() |
1d5ca55aab | ||
![]() |
e0033f1e10 | ||
![]() |
9206a26e1d | ||
![]() |
11dd2bef2d | ||
![]() |
6fc80690ae | ||
![]() |
f6d2705942 | ||
![]() |
79dc14199b | ||
![]() |
71956250dd | ||
![]() |
e84539f809 | ||
![]() |
873330b82c | ||
![]() |
a177b1b7b1 | ||
![]() |
435a28e937 | ||
![]() |
c2b4d92708 | ||
![]() |
a87951a28f | ||
![]() |
6b565ba8f2 | ||
![]() |
c29f830c4b | ||
![]() |
cde4653c62 | ||
![]() |
e07d940b9b | ||
![]() |
ee1526029f | ||
![]() |
eba9dd364e | ||
![]() |
78a44768e0 | ||
![]() |
98c047b763 | ||
![]() |
543b679762 | ||
![]() |
c00f4ab2ae | ||
![]() |
2038568f3e | ||
![]() |
c509243af5 | ||
![]() |
d4544da804 | ||
![]() |
b950d4675f | ||
![]() |
ae5257cda6 | ||
![]() |
8fd8143ab8 | ||
![]() |
acf3cff9ee | ||
![]() |
c5b125b7db | ||
![]() |
fc5c34d1b8 | ||
![]() |
0879d2e85d | ||
![]() |
83fe963a4b | ||
![]() |
e0eeb4afcb | ||
![]() |
c942662d79 | ||
![]() |
6341a837c1 | ||
![]() |
f954ab6f10 | ||
![]() |
3ee666580a | ||
![]() |
dbc2364d16 | ||
![]() |
eee2fd22e0 | ||
![]() |
638dd15f61 | ||
![]() |
9c668e091f | ||
![]() |
b2816a1536 | ||
![]() |
2cbc429291 | ||
![]() |
4c7f32f28c | ||
![]() |
8572e885b4 | ||
![]() |
0e3e9cd382 | ||
![]() |
9118f49a63 | ||
![]() |
d37049a2a2 | ||
![]() |
d12cdb5019 | ||
![]() |
ce879fc416 | ||
![]() |
712f1bd0b7 | ||
![]() |
d2fb552116 | ||
![]() |
5103d908c8 | ||
![]() |
9318e23e64 | ||
![]() |
290bc7334d | ||
![]() |
190561d8a6 | ||
![]() |
ddb0a4e2e5 | ||
![]() |
07a07e34bc | ||
![]() |
dda3f49952 | ||
![]() |
decd95e7f0 | ||
![]() |
6abb8d0d91 | ||
![]() |
2b2146bc58 | ||
![]() |
3a698e2d08 | ||
![]() |
8a74508130 | ||
![]() |
ef1fb6dee4 | ||
![]() |
e36d5b201a | ||
![]() |
77b62a52c0 | ||
![]() |
616543ded0 | ||
![]() |
2170ea270a | ||
![]() |
80d0067048 | ||
![]() |
5218916a7e | ||
![]() |
1c1eb3045c | ||
![]() |
4967997536 | ||
![]() |
666e6d15fa | ||
![]() |
f3ec37ebbf | ||
![]() |
cc3b1ebd96 | ||
![]() |
29490cce30 | ||
![]() |
bedc0451a0 | ||
![]() |
a0595f4b4f | ||
![]() |
8924ec1474 | ||
![]() |
4481bebb38 | ||
![]() |
f5bbfd7b8c | ||
![]() |
41ce5240f2 | ||
![]() |
243824ef74 | ||
![]() |
c95802f26f | ||
![]() |
71c0363bb5 | ||
![]() |
e03adaf9b0 | ||
![]() |
38dfbc775f | ||
![]() |
5229809adb | ||
![]() |
9d88ca07f8 | ||
![]() |
97383488e8 | ||
![]() |
cb566add3c | ||
![]() |
5c40fd65fa | ||
![]() |
2b53b07c70 | ||
![]() |
6de5a12a9d | ||
![]() |
3a418ab63b | ||
![]() |
c8c0063499 | ||
![]() |
34259e90cb | ||
![]() |
d0c69d207c | ||
![]() |
1f0818002c | ||
![]() |
fd65958b88 | ||
![]() |
12f674f404 | ||
![]() |
413a0fb1ae | ||
![]() |
85abfd2171 | ||
![]() |
1601ee6f6a | ||
![]() |
6898eab946 | ||
![]() |
62a85f5e55 | ||
![]() |
a8af8551ec | ||
![]() |
7e0eccc4ef | ||
![]() |
2a970a0af8 | ||
![]() |
bd7f440357 | ||
![]() |
d0437b3be0 | ||
![]() |
1d844b9bd8 | ||
![]() |
53e95233c3 | ||
![]() |
879a674420 | ||
![]() |
71f008f906 | ||
![]() |
1197965e69 | ||
![]() |
8154bbd538 | ||
![]() |
f5e39999d7 | ||
![]() |
ff33ab1379 | ||
![]() |
7521834296 | ||
![]() |
1185aa07a3 | ||
![]() |
ceca5dded5 | ||
![]() |
2a145f2463 | ||
![]() |
e0dfa42d6e | ||
![]() |
cc37af2314 | ||
![]() |
87a679b210 | ||
![]() |
a7359d494a | ||
![]() |
66e6b932d8 | ||
![]() |
cc49a91de7 | ||
![]() |
300c2fec9c | ||
![]() |
a7faa6bb65 | ||
![]() |
bcc0a035cc | ||
![]() |
e99bcbb4d4 | ||
![]() |
adc9d5cdcb | ||
![]() |
d330cd85ac | ||
![]() |
09d6dc50ef | ||
![]() |
7ac166ff08 | ||
![]() |
ae4f81cbab | ||
![]() |
c1fdfd4f14 | ||
![]() |
62e4acc3d1 | ||
![]() |
1091ddbb8e | ||
![]() |
b45acb8d32 | ||
![]() |
104abe04ba | ||
![]() |
1bc807c81a | ||
![]() |
d3b5e5696f | ||
![]() |
34e4098e85 | ||
![]() |
8dcf618411 | ||
![]() |
7cc7955b5d | ||
![]() |
a075260751 | ||
![]() |
aba33de5f5 | ||
![]() |
fe0782afa9 | ||
![]() |
3545520e81 | ||
![]() |
5ea9119322 | ||
![]() |
2e355fd4d3 | ||
![]() |
12f2101d08 | ||
![]() |
d3a817549b | ||
![]() |
c5493c192c | ||
![]() |
d17084bf97 | ||
![]() |
f150a304e8 | ||
![]() |
886e3ebcca | ||
![]() |
bf682d73d4 | ||
![]() |
8f3695e20e | ||
![]() |
829ddf95e5 | ||
![]() |
fb10f62efc | ||
![]() |
8197557fcf | ||
![]() |
e7a0e87c41 | ||
![]() |
ab9bc8a9ec | ||
![]() |
469d2b4640 | ||
![]() |
31796e8e2f | ||
![]() |
284123c6ba | ||
![]() |
7259208893 | ||
![]() |
7e5f6c2dc1 | ||
![]() |
97dc85ba5e | ||
![]() |
a937889c3b | ||
![]() |
aa8f1d569b | ||
![]() |
5dba3bf1fd | ||
![]() |
6651b4171d | ||
![]() |
8c682c52b1 | ||
![]() |
e5b09cc49a | ||
![]() |
b199ef6bfc | ||
![]() |
583a9d38a1 | ||
![]() |
1fce6d6bae | ||
![]() |
39f973430a | ||
![]() |
20346ff192 | ||
![]() |
bd9c1e6cfc | ||
![]() |
d76a872efb | ||
![]() |
a398d6af45 | ||
![]() |
e836eaf448 | ||
![]() |
ae364864f6 | ||
![]() |
cc552dd702 | ||
![]() |
021dd33ed8 | ||
![]() |
684726cdac | ||
![]() |
7b005bb9cf | ||
![]() |
401ef71ae5 | ||
![]() |
0a1d078a74 | ||
![]() |
35502c739c | ||
![]() |
b2ccc34f9c | ||
![]() |
eaa38a5adc | ||
![]() |
cb1373106b | ||
![]() |
f6ee911cbb | ||
![]() |
a3313709ea | ||
![]() |
0eacba5829 | ||
![]() |
bb924b63e6 | ||
![]() |
7301e70ddd | ||
![]() |
7edb026619 | ||
![]() |
0b7845964b | ||
![]() |
55979fe0ae | ||
![]() |
6280cf95b4 | ||
![]() |
8d817daf78 | ||
![]() |
946f1179e9 | ||
![]() |
87fdd23157 | ||
![]() |
713fb3b587 | ||
![]() |
0cb0f66c17 | ||
![]() |
db11a0ddbf | ||
![]() |
779344012a | ||
![]() |
650974e1b3 | ||
![]() |
ed3c549063 | ||
![]() |
3a116179b1 | ||
![]() |
5e64c2b1df | ||
![]() |
d63ecf4c5f | ||
![]() |
77efddcac3 | ||
![]() |
d887ba85ad | ||
![]() |
0c75a06b1e | ||
![]() |
aaa20093b2 | ||
![]() |
5568d824dd | ||
![]() |
17996bf719 | ||
![]() |
2a330a60ed | ||
![]() |
569d1ef583 | ||
![]() |
85b6c94cc6 | ||
![]() |
818d93d7e9 | ||
![]() |
d4c0962c7b | ||
![]() |
e31208beb1 | ||
![]() |
3569fdf451 | ||
![]() |
eb6ba9ac80 | ||
![]() |
4e7a4543b8 | ||
![]() |
753fed285c | ||
![]() |
dffcca73e4 | ||
![]() |
c8f7fc22c7 | ||
![]() |
b2bd38699b | ||
![]() |
c025357fb8 | ||
![]() |
57411c85b9 | ||
![]() |
07a8016118 | ||
![]() |
4d69da57ca | ||
![]() |
7f98b87ca0 | ||
![]() |
c61decf7e5 | ||
![]() |
6e7bd939f6 | ||
![]() |
2021ad12cf | ||
![]() |
c4f4675ebf | ||
![]() |
34827559b9 | ||
![]() |
65c3888d01 | ||
![]() |
e648a0c4ca | ||
![]() |
965a688c97 | ||
![]() |
ab3f4c9fe1 | ||
![]() |
40f3bb5638 | ||
![]() |
a08d18a1fe | ||
![]() |
64d6f35f94 | ||
![]() |
caa4ab3235 | ||
![]() |
06a8ad28a7 | ||
![]() |
382aa50c54 | ||
![]() |
044a19966d | ||
![]() |
17e98198f4 | ||
![]() |
561c0f81a0 | ||
![]() |
4414be77c4 | ||
![]() |
1b55da10b1 | ||
![]() |
78ea2527a1 | ||
![]() |
4456e7e4de | ||
![]() |
92c436dd1a | ||
![]() |
b45f336635 | ||
![]() |
c3651cec0b | ||
![]() |
3b52f7066b | ||
![]() |
8bb741198b | ||
![]() |
26849ca99d | ||
![]() |
4d0e175a65 | ||
![]() |
bd7393fc68 | ||
![]() |
08ff8aa055 | ||
![]() |
f60d159d71 | ||
![]() |
6aa5bfa21a | ||
![]() |
227ba625e6 | ||
![]() |
e64176019a | ||
![]() |
1fc7891add | ||
![]() |
e7930fcc15 | ||
![]() |
4b40740324 | ||
![]() |
a36667d984 | ||
![]() |
9791c9ecaf | ||
![]() |
df082307b9 | ||
![]() |
98d820030c | ||
![]() |
f001aef2dc | ||
![]() |
64fc8b8ee5 | ||
![]() |
a62c1c441c | ||
![]() |
3d154ab795 | ||
![]() |
d1ea1f4c7f | ||
![]() |
5aeb9a4124 | ||
![]() |
ecce99470a | ||
![]() |
540c29cd6b | ||
![]() |
7827501d2a | ||
![]() |
e28f13a102 | ||
![]() |
e0002ef9ba | ||
![]() |
367f6fe12d | ||
![]() |
9b3ca19675 | ||
![]() |
9388e47e1e | ||
![]() |
171d967993 | ||
![]() |
40e357411e | ||
![]() |
52c7aae4df | ||
![]() |
87b1aeac0f | ||
![]() |
93be1f1543 | ||
![]() |
cdb5d07606 | ||
![]() |
3e5fa56956 | ||
![]() |
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 |
93
.bazelignore
93
.bazelignore
@ -1,4 +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
|
||||
|
137
.bazelrc
137
.bazelrc
@ -1,20 +1,3 @@
|
||||
# Load any settings specific to the current user
|
||||
try-import .bazelrc.user
|
||||
################################
|
||||
# Settings for Angular team members only
|
||||
################################
|
||||
# To enable this feature check the "Remote caching" section in docs/BAZEL.md.
|
||||
build:angular-team --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||
|
||||
###############################
|
||||
# Typescript / Angular / Sass #
|
||||
###############################
|
||||
|
||||
# Make compilation fast, by keeping a few copies of the compilers
|
||||
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
||||
build --strategy=TypeScriptCompile=worker
|
||||
build --strategy=AngularTemplateCompile=worker
|
||||
|
||||
# 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
|
||||
|
||||
@ -22,20 +5,39 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
||||
# Filesystem interactions #
|
||||
###############################
|
||||
|
||||
# Don't create symlinks like bazel-out in the project.
|
||||
# These cause VSCode to traverse a massive tree, opening file handles and
|
||||
# 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=/
|
||||
|
||||
# Performance: avoid stat'ing input files
|
||||
build --watchfs
|
||||
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 #
|
||||
@ -43,7 +45,10 @@ test --nolegacy_external_runfiles
|
||||
###############################
|
||||
|
||||
# Releases should always be stamped with version control info
|
||||
build:release --workspace_status_command=./tools/bazel_stamp_vars.sh
|
||||
# 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 #
|
||||
@ -56,46 +61,86 @@ query --output=label_kind
|
||||
# By default, failing tests don't print any output, it goes to the log file
|
||||
test --test_output=errors
|
||||
|
||||
# Show which actions are run under workers,
|
||||
# and print all the actions running in parallel.
|
||||
# Helps to demonstrate that bazel uses all the cores on the machine.
|
||||
build --experimental_ui
|
||||
test --experimental_ui
|
||||
|
||||
################################
|
||||
# Settings for CircleCI #
|
||||
################################
|
||||
|
||||
# Bazel flags for CircleCI are in /.circleci/bazel.rc
|
||||
# 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 or ViewEngine one can use `--define=compile=aot` on
|
||||
# any bazel target. This is a temporary flag until codebase is permanently switched to Ivy.
|
||||
build --define=compile=legacy
|
||||
# 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
|
||||
|
||||
###############################
|
||||
# Remote Build Execution support
|
||||
# Turn on these settings with
|
||||
# --config=remote
|
||||
###############################
|
||||
build:view-engine --define=angular_ivy_enabled=False
|
||||
build:ivy --define=angular_ivy_enabled=True
|
||||
|
||||
# Load default settings for Remote Build Execution
|
||||
import %workspace%/third_party/github.com/bazelbuild/bazel-toolchains/bazelrc/bazel-0.20.0.bazelrc
|
||||
##################################
|
||||
# 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
|
||||
|
||||
# Point to our custom execution platform; see tools/BUILD.bazel
|
||||
# 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.
|
||||
# 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
|
||||
|
||||
# Do not accept remote cache.
|
||||
# We need to understand the security risks of using prior build artifacts.
|
||||
build:remote --remote_accept_cached=false
|
||||
##################################
|
||||
# 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
|
||||
|
||||
####################################################
|
||||
# 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
|
@ -1,42 +0,0 @@
|
||||
# Heavily based on https://github.com/StefanScherer/dockerfiles-windows/ images.
|
||||
# Combines the node windowsservercore image with the Bazel Prerequisites (https://docs.bazel.build/versions/master/install-windows.html).
|
||||
# msys install taken from https://github.com/StefanScherer/dockerfiles-windows/issues/30
|
||||
# VS redist install taken from https://github.com/StefanScherer/dockerfiles-windows/blob/master/apache/Dockerfile
|
||||
# The nanoserver image won't work because MSYS2 does not run in it https://github.com/Alexpux/MSYS2-packages/issues/1493
|
||||
|
||||
# Before building this image, you must locally build node-windows:10.13.0-windowsservercore-1803.
|
||||
# Clone https://github.com/StefanScherer/dockerfiles-windows/commit/4ce7101a766b9b880ac262479dd9126b64d656cf and build using
|
||||
# docker build -t node-windows:10.13.0-windowsservercore-1803 --build-arg core=microsoft/windowsservercore:1803 --build-arg target=microsoft/windowsservercore:1803 .
|
||||
FROM node-windows:10.13.0-windowsservercore-1803
|
||||
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
|
||||
# Install 7zip to extract msys2
|
||||
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe
|
||||
# For some reason the last letter in the destination directory is lost. So '/D=C:\\7zip0' will extract to '/D=C:\\7zip'.
|
||||
RUN Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait
|
||||
|
||||
# Extract msys2
|
||||
RUN Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz
|
||||
RUN Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait
|
||||
RUN Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait
|
||||
RUN Remove-Item msys2.tar.xz
|
||||
RUN Remove-Item msys2.tar
|
||||
RUN Remove-Item 7z.exe
|
||||
RUN Remove-Item -Recurse 7zip
|
||||
|
||||
# Add MSYS2 to PATH, and set BAZEL_SH
|
||||
RUN [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine)
|
||||
RUN [Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine)
|
||||
|
||||
# Install Microsoft Visual C++ Redistributable for Visual Studio 2015
|
||||
RUN Invoke-WebRequest -UseBasicParsing 'https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe' -OutFile vc_redist.x64.exe
|
||||
RUN Start-Process 'c:\\vc_redist.x64.exe' -ArgumentList '/Install', '/Passive', '/NoRestart' -NoNewWindow -Wait
|
||||
RUN Remove-Item vc_redist.x64.exe
|
||||
|
||||
# Add a fix for https://github.com/docker/for-win/issues/2920 as entry point to the container.
|
||||
SHELL ["cmd", "/c"]
|
||||
COPY "fix-msys64.cmd" "C:\\fix-msys64.cmd"
|
||||
ENTRYPOINT cmd /C C:\\fix-msys64.cmd && cmd /c
|
||||
|
||||
CMD ["cmd.exe"]
|
@ -1,96 +0,0 @@
|
||||
# BuildKite configuration
|
||||
|
||||
This folder contains configuration for the [BuildKite](https://buildkite.com) based CI checks for
|
||||
this repository.
|
||||
|
||||
BuildKite is a CI provider that provides build coordination and reports while we provide the
|
||||
infrastructure.
|
||||
|
||||
CI runs are triggered by new PRs and will show up on the GitHub checks interface, along with the
|
||||
other current CI solutions.
|
||||
|
||||
Currently it is only used for tests on Windows platforms.
|
||||
|
||||
|
||||
## The build pipeline
|
||||
|
||||
BuildKite uses a pipeline for each repository. The `pipeline.yml` file defines pipeline
|
||||
[build steps](https://buildkite.com/docs/pipelines/defining-steps) for this repository.
|
||||
|
||||
Run results can be seen in the GitHub checks interface and in the
|
||||
[pipeline dashboard](https://buildkite.com/angular/angular).
|
||||
|
||||
Although most configuration is done via `pipeline.yml`, some options are only available
|
||||
in the online [pipeline settings](https://buildkite.com/angular/angular/settings).
|
||||
|
||||
|
||||
## Infrastructure
|
||||
|
||||
BuildKite does not provide the host machines where the builds runs, providing instead the
|
||||
[BuildKite Agent](https://buildkite.com/docs/agent/v3) that should be run our own infrastructure.
|
||||
|
||||
|
||||
### Agents
|
||||
|
||||
This agent polls the BuildKite API for builds, runs them, and reports back the results.
|
||||
Agents are the unit of concurrency: each agent can run one build at any given time.
|
||||
Adding agents allows more builds to be ran at the same time.
|
||||
|
||||
Individual agents can have tags, and pipeline steps can target only agents with certain tags via the
|
||||
`agents` field in `pipeline.yml`.
|
||||
For example: agents on Windows machines are tagged as `windows`, and the Windows specific build
|
||||
steps list `windows: true` in their `agents` field.
|
||||
|
||||
You can see the current agent pool, along with their tags, in the
|
||||
[agents list](https://buildkite.com/organizations/angular/agents).
|
||||
|
||||
|
||||
### Our host machines
|
||||
|
||||
We use [Google Cloud](https://cloud.google.com/) as our cloud provider, under the
|
||||
[Angular project](https://console.cloud.google.com/home/dashboard?project=internal-200822).
|
||||
To access this project you need need to be logged in with a Google account that's a member of
|
||||
team@angular.io.
|
||||
For googlers this may be your google.com account, for others it is an angular.io account.
|
||||
|
||||
In this project we have a number of Windows VMs running, each of them with several agents.
|
||||
The `provision-windows-buildkite.ps1` file contains instructions on how to create new host VMs that
|
||||
are fully configured to run the BuildKite agents as services.
|
||||
|
||||
Our pipeline uses [docker-buildkite-plugin](https://github.com/buildkite-plugins/docker-buildkite-plugin)
|
||||
to run build steps inside docker containers.
|
||||
This way we achieve isolation and hermeticity.
|
||||
|
||||
The `Dockerfile` file describes a custom Docker image that includes NodeJs, Yarn, and the Bazel
|
||||
pre-requisites on Windows.
|
||||
|
||||
To upload a new version of the docker image, follow any build instructions in `Dockerfile` and then
|
||||
run `docker build -t angular/node-bazel-windows:NEW_VERSION`, followed by
|
||||
`docker push angular/node-bazel-windows:NEW_VERSION`.
|
||||
After being pushed it should be available online, and you can use the new version in `pipeline.yml`.
|
||||
|
||||
|
||||
## Caretaker
|
||||
|
||||
BuildKite status can be found at https://www.buildkitestatus.com/.
|
||||
|
||||
Issues related to the BuildKite setup should be escalated to the Tools Team via the current
|
||||
caretaker, followed by Alex Eagle and Filipe Silva.
|
||||
|
||||
Support requests should be submitted via email to support@buildkite.com and cc Igor, Misko, Alex,
|
||||
Jeremy and Manu
|
||||
|
||||
|
||||
## Rollout strategy
|
||||
|
||||
At the moment our BuildKite CI uses 1 host VM running 4 agents, thus being capable of 4 concurrent
|
||||
builds.
|
||||
The only test running is `bazel test //tools/ts-api-guardian:all`, and the PR check is not
|
||||
mandatory.
|
||||
|
||||
In the future we should add cache support to speed up the initial `yarn` install, and also Bazel
|
||||
remote caching to speed up Bazel builds.
|
||||
|
||||
After the current setup is verified as stable and reliable the GitHub PR check can become mandatory.
|
||||
|
||||
The tests ran should also be expanded to cover most, if not all, of the Bazel tests.
|
@ -1,6 +0,0 @@
|
||||
@echo off
|
||||
REM Fix for https://github.com/docker/for-win/issues/2920
|
||||
REM echo "Fixing msys64 folder..."
|
||||
REM Touch all .dll files inside C:\msys64\
|
||||
forfiles /p C:\msys64\ /s /m *.dll /c "cmd /c Copy /B @path+,, >NUL"
|
||||
REM echo "Fixed msys64 folder."
|
@ -1,10 +0,0 @@
|
||||
steps:
|
||||
- label: windows-test
|
||||
commands:
|
||||
- "yarn install --frozen-lockfile --non-interactive --network-timeout 100000"
|
||||
- "yarn bazel test //tools/ts-api-guardian:all --noshow_progress"
|
||||
plugins:
|
||||
- docker#v2.1.0:
|
||||
image: "filipesilva/node-bazel-windows:0.0.2"
|
||||
agents:
|
||||
windows: true
|
@ -1,92 +0,0 @@
|
||||
# PowerShell script to provision a Windows Server with BuildKite
|
||||
# This script follows https://buildkite.com/docs/agent/v3/windows.
|
||||
|
||||
# Instructions
|
||||
|
||||
# VM creation:
|
||||
# In Google Cloud Platform, create a Compute Engine instance.
|
||||
# We recommend machine type n1-highcpu-16 (16 vCPUs, 14.4 GB memory).
|
||||
# Use a windows boot disk with container support such as
|
||||
# "Windows Server version 1803 Datacenter Core for Containers".
|
||||
# Give it a name, then click "Create".
|
||||
|
||||
# VM setup:
|
||||
# In the Compute Engine menu, select "VM Instances". Click on the VM name you chose before.
|
||||
# Click "Set Windows Password" to choose a username and password.
|
||||
# Click RDP to open a remote desktop via browser, using the username and password.
|
||||
# In the Windows command prompt start an elevated powershell by inputing
|
||||
# "powershell -Command "Start-Process PowerShell -Verb RunAs" followed by Enter.
|
||||
# Download and execute this script from GitHub, passing the token (mandatory), tags (optional)
|
||||
# and number of agents (optional) as args:
|
||||
# ```
|
||||
# Invoke-WebRequest -Uri https://raw.githubusercontent.com/angular/angular/master/.buildkite/provision-windows-buildkite.ps1 -OutFile provision.ps1
|
||||
# .\provision.ps1 -token "MY_TOKEN" -tags "windows=true,another_tag=true" -agents 4
|
||||
# ```
|
||||
# The VM should restart and be fully configured.
|
||||
|
||||
# Creating extra VMs
|
||||
# You can create an image of the current VM by following the instructions below.
|
||||
# https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image
|
||||
# Then create a new VM and choose "Custom images".
|
||||
|
||||
|
||||
# Script proper.
|
||||
|
||||
# Get the token and tags from arguments.
|
||||
param (
|
||||
[Parameter(Mandatory=$true)][string]$token,
|
||||
[string]$tags = ""
|
||||
[Int]$agents = 1
|
||||
)
|
||||
|
||||
# Allow HTTPS
|
||||
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
|
||||
|
||||
# Helper to add to PATH.
|
||||
# Will take current PATH so avoid running it after anything to modifies only the powershell session path.
|
||||
function Add-Path ([string]$newPathItem) {
|
||||
$Env:Path+= ";" + $newPathItem + ";"
|
||||
[Environment]::SetEnvironmentVariable("Path",$env:Path, [System.EnvironmentVariableTarget]::Machine)
|
||||
}
|
||||
|
||||
# Install Git for Windows
|
||||
Write-Host "Installing Git for Windows."
|
||||
Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.19.1.windows.1/Git-2.19.1-64-bit.exe -OutFile git.exe
|
||||
.\git.exe /VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh" /DIR="C:\git"
|
||||
Add-Path "C:\git\bin"
|
||||
Remove-Item git.exe
|
||||
|
||||
# Download NSSM (https://nssm.cc/) to run the BuildKite agent as a service.
|
||||
Write-Host "Downloading NSSM."
|
||||
Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -OutFile nssm.zip
|
||||
Expand-Archive -Path nssm.zip -DestinationPath C:\nssm
|
||||
Add-Path "C:\nssm\nssm-2.24-101-g897c7ad\win64"
|
||||
Remove-Item nssm.zip
|
||||
|
||||
# Run the BuildKite agent install script
|
||||
Write-Host "Installing BuildKite agent."
|
||||
$env:buildkiteAgentToken = $token
|
||||
$env:buildkiteAgentTags = $tags
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/buildkite/agent/master/install.ps1'))
|
||||
|
||||
# Configure the BuildKite agent clone and timestamp behavior
|
||||
Add-Content C:\buildkite-agent\buildkite-agent.cfg "`ngit-clone-flags=--config core.autocrlf=input --config core.eol=lf --config core.longpaths=true --config core.symlinks=true`n"
|
||||
Add-Content C:\buildkite-agent\buildkite-agent.cfg "`ntimestamp-lines=true`n"
|
||||
|
||||
# Register the BuildKite agent service using NSSM, so that it persists through restarts and is
|
||||
# restarted if the process dies.
|
||||
for ($i=1; $i -le $agents; $i++)
|
||||
{
|
||||
$agentName = "buildkite-agent-$i"
|
||||
Write-Host "Registering $agentName as a service."
|
||||
nssm.exe install $agentName "C:\buildkite-agent\bin\buildkite-agent.exe" "start"
|
||||
nssm.exe set $agentName AppStdout "C:\buildkite-agent\$agentName.log"
|
||||
nssm.exe set $agentName AppStderr "C:\buildkite-agent\$agentName.log"
|
||||
nssm.exe status $agentName
|
||||
nssm.exe start $agentName
|
||||
nssm.exe status $agentName
|
||||
}
|
||||
|
||||
# Restart the machine.
|
||||
Restart-Computer
|
@ -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
|
||||
- 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,26 +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 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
@ -7,210 +7,300 @@
|
||||
# To validate changes, use an online parser, eg.
|
||||
# http://yaml-online-parser.appspot.com/
|
||||
|
||||
# Note that the browser docker image comes with Chrome and Firefox preinstalled. This is just
|
||||
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
||||
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
||||
# docker image with browsers pre-installed.
|
||||
# **NOTE**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
var_1: &default_docker_image circleci/node:10.12
|
||||
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
||||
var_3: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-node-10.12
|
||||
# CircleCI configuration version
|
||||
# Version 2.1 allows for extra config reuse features
|
||||
# https://circleci.com/docs/2.0/reusing-config/#getting-started-with-config-reuse
|
||||
version: 2.1
|
||||
|
||||
# Define common ENV vars
|
||||
var_4: &define_env_vars
|
||||
run:
|
||||
name: Define environment variables
|
||||
command: ./.circleci/env.sh
|
||||
# We don't want to include the current branch name in the cache key because that would prevent
|
||||
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
||||
# The cache key should only consist of dynamic values that change whenever something in the
|
||||
# cache changes. For example:
|
||||
# 1) yarn lock file changes --> cached "node_modules" are different.
|
||||
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
||||
# Windows needs its own cache key because binaries in node_modules are different.
|
||||
# **NOTE 1 **: If you change the cache key prefix, also sync the cache_key_fallback to match.
|
||||
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||
var_3: &cache_key v7-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
# We invalidate the cache if the Bazel version changes because otherwise the `bazelisk` cache
|
||||
# folder will contain all previously used versions and ultimately cause the cache restoring to
|
||||
# be slower due to its growing size.
|
||||
var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
|
||||
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
||||
|
||||
var_5: &setup_bazel_remote_execution
|
||||
run:
|
||||
name: "Setup bazel RBE remote execution"
|
||||
command: |
|
||||
openssl aes-256-cbc -d -in .circleci/gcp_token -k "$CI_REPO_NAME" -out /home/circleci/.gcp_credentials
|
||||
echo "export GOOGLE_APPLICATION_CREDENTIALS=/home/circleci/.gcp_credentials" >> $BASH_ENV
|
||||
sudo bash -c "echo 'build --config=remote' >> /etc/bazel.bazelrc"
|
||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||
# `build-ivy-npm-packages`.
|
||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
||||
var_7: &workspace_location ~/
|
||||
|
||||
# Settings common to each job
|
||||
var_6: &job_defaults
|
||||
working_directory: ~/ng
|
||||
docker:
|
||||
- image: *default_docker_image
|
||||
# Filter to run a job on builds for pull requests only.
|
||||
var_8: &only_on_pull_requests
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /pull\/\d+/
|
||||
|
||||
# After checkout, rebase on top of master.
|
||||
# Similar to travis behavior, but not quite the same.
|
||||
# See https://discuss.circleci.com/t/1662
|
||||
var_7: &post_checkout
|
||||
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
|
||||
# Filter to skip a job on builds for pull requests.
|
||||
var_9: &skip_on_pull_requests
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- /pull\/\d+/
|
||||
|
||||
var_8: &yarn_install
|
||||
run:
|
||||
name: Running Yarn install
|
||||
command: yarn install --frozen-lockfile --non-interactive
|
||||
# Filter to run a job on builds for the master branch only.
|
||||
var_10: &only_on_master
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
var_9: &setup_circleci_bazel_config
|
||||
run:
|
||||
name: Setting up CircleCI bazel configuration
|
||||
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
# Executor Definitions
|
||||
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-executors
|
||||
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
|
||||
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
|
||||
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||
executors:
|
||||
default-executor:
|
||||
parameters:
|
||||
resource_class:
|
||||
type: string
|
||||
default: medium
|
||||
docker:
|
||||
- image: circleci/node:12.14.1@sha256:f9de24fc0017059cc42ef7d07db060008af65a98b1f0cdd1ef3339213226bf6d
|
||||
resource_class: << parameters.resource_class >>
|
||||
working_directory: ~/ng
|
||||
|
||||
version: 2
|
||||
windows-executor:
|
||||
working_directory: ~/ng
|
||||
resource_class: windows.medium
|
||||
# CircleCI windows VMs do have the GitBash shell available:
|
||||
# https://github.com/CircleCI-Public/windows-preview-docs#shells
|
||||
# But in this specific case we really should not use it because Bazel must not be ran from
|
||||
# GitBash. These issues discuss why:
|
||||
# https://github.com/bazelbuild/bazel/issues/5751
|
||||
# https://github.com/bazelbuild/bazel/issues/5724#issuecomment-410194038
|
||||
# https://github.com/bazelbuild/bazel/issues/6339#issuecomment-441600879
|
||||
shell: powershell.exe -ExecutionPolicy Bypass
|
||||
machine:
|
||||
# Windows preview image that includes the following:
|
||||
# - Visual Studio 2019 build tools
|
||||
# - Node 12
|
||||
# - yarn 1.17
|
||||
# - Python 3 3.7.4
|
||||
image: windows-server-2019-vs2019:201908-02
|
||||
|
||||
# Command Definitions
|
||||
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-commands
|
||||
commands:
|
||||
custom_attach_workspace:
|
||||
description: Attach workspace at a predefined location
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: *workspace_location
|
||||
|
||||
# Install shared libs used by Chrome that is either provisioned by
|
||||
# rules_webtesting or by puppeteer.
|
||||
install_chrome_libs:
|
||||
description: Install shared Chrome libs
|
||||
steps:
|
||||
- run:
|
||||
name: Install shared Chrome libs
|
||||
command: |
|
||||
sudo apt-get update
|
||||
# Install GTK+ graphical user interface (libgtk-3-0), advanced linux sound architecture (libasound2)
|
||||
# and network security service libraries (libnss3) & X11 Screen Saver extension library (libssx1)
|
||||
# which are dependencies of chrome & needed for karma & protractor headless chrome tests.
|
||||
# This is a very small install which takes around 7s in comparing to using the full
|
||||
# circleci/node:x.x.x-browsers image.
|
||||
sudo apt-get -y install libgtk-3-0 libasound2 libnss3 libxss1
|
||||
|
||||
# Install java runtime which is required by some integration tests such as
|
||||
# //integration:hello_world__closure_test, //integration:i18n_test and
|
||||
# //integration:ng_elements_test to run the closure compiler
|
||||
install_java:
|
||||
description: Install java
|
||||
steps:
|
||||
- run:
|
||||
name: Install java
|
||||
command: |
|
||||
sudo apt-get update
|
||||
# Install java runtime
|
||||
sudo apt-get install default-jre
|
||||
|
||||
# Initializes the CI environment by setting up common environment variables.
|
||||
init_environment:
|
||||
description: Initializing environment (setting up variables)
|
||||
steps:
|
||||
- run:
|
||||
name: Set up environment
|
||||
environment:
|
||||
CIRCLE_GIT_BASE_REVISION: << pipeline.git.base_revision >>
|
||||
CIRCLE_GIT_REVISION: << pipeline.git.revision >>
|
||||
command: ./.circleci/env.sh
|
||||
- run:
|
||||
# Configure git as the CircleCI `checkout` command does.
|
||||
# This is needed because we only checkout on the setup job.
|
||||
# Add GitHub to known hosts
|
||||
name: Configure git
|
||||
command: |
|
||||
mkdir -p ~/.ssh
|
||||
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||
git config --global gc.auto 0 || true
|
||||
|
||||
# Normally this would be an individual job instead of a command.
|
||||
# But startup and setup time for each individual windows job are high enough to discourage
|
||||
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
||||
setup_win:
|
||||
description: Setup windows node environment
|
||||
steps:
|
||||
# Use the Linux workspace directly, as it already has checkout, rebased and node modules.
|
||||
- custom_attach_workspace
|
||||
# Install Bazel pre-requisites that aren't in the preconfigured CircleCI Windows VM.
|
||||
- run: ./.circleci/windows-env.ps1
|
||||
- run: node --version
|
||||
- run: yarn --version
|
||||
- restore_cache:
|
||||
keys:
|
||||
- *cache_key_win
|
||||
- *cache_key_win_fallback
|
||||
# Reinstall to get windows binaries.
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
# Install @bazel/bazelisk globally and use that for the first run.
|
||||
# Workaround for https://github.com/bazelbuild/rules_nodejs/issues/894
|
||||
# NB: the issue was for @bazel/bazel but the same problem applies to @bazel/bazelisk
|
||||
- run: yarn global add @bazel/bazelisk@$env:BAZELISK_VERSION
|
||||
- run: bazelisk info
|
||||
|
||||
notify_webhook_on_fail:
|
||||
description: Notify a webhook about failure
|
||||
parameters:
|
||||
# `webhook_url_env_var` are secret env vars defined in CircleCI project settings.
|
||||
# The URLs come from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||
webhook_url_env_var:
|
||||
type: env_var_name
|
||||
steps:
|
||||
- run:
|
||||
when: on_fail
|
||||
command: |
|
||||
notificationJson="{\"text\":\":x: \`$CIRCLE_JOB\` job for $CIRCLE_BRANCH branch failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}"
|
||||
curl --request POST --header "Content-Type: application/json" --data "$notificationJson" ${<< parameters.webhook_url_env_var >>}
|
||||
|
||||
# Job definitions
|
||||
# Jobs can include parameters that are passed in the workflow job invocation.
|
||||
# https://circleci.com/docs/2.0/reusing-config/#authoring-parameterized-jobs
|
||||
jobs:
|
||||
lint:
|
||||
<<: *job_defaults
|
||||
setup:
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- checkout
|
||||
- init_environment
|
||||
- run:
|
||||
name: Rebase PR on target branch
|
||||
# After checkout, rebase on top of target branch.
|
||||
command: >
|
||||
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
||||
# User is required for rebase.
|
||||
git config user.name "angular-ci"
|
||||
git config user.email "angular-ci"
|
||||
# Rebase PR on top of target branch.
|
||||
node tools/rebase-pr.js
|
||||
else
|
||||
echo "This build is not over a PR, nothing to do."
|
||||
fi
|
||||
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *yarn_install
|
||||
|
||||
- run: 'yarn bazel:format -mode=check ||
|
||||
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
||||
# Run the skylark linter to check our Bazel rules
|
||||
- run: 'yarn bazel:lint ||
|
||||
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
||||
|
||||
- run: ./node_modules/.bin/gulp lint
|
||||
|
||||
test:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
|
||||
# Setup remote execution and run RBE-compatible tests.
|
||||
- *setup_bazel_remote_execution
|
||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-local
|
||||
# Now run RBE incompatible tests locally.
|
||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||
|
||||
- save_cache:
|
||||
key: *cache_key
|
||||
keys:
|
||||
- *cache_key
|
||||
- *cache_key_fallback
|
||||
- run:
|
||||
name: Running Yarn install
|
||||
command: yarn install --frozen-lockfile --non-interactive
|
||||
# Yarn's requests sometimes take more than 10mins to complete.
|
||||
no_output_timeout: 45m
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Make the bazel directories and add a file to them if they don't exist already so that
|
||||
# persist_to_workspace does not fail.
|
||||
- run: |
|
||||
if [ ! -d ~/bazel_repository_cache ]; then
|
||||
mkdir ~/bazel_repository_cache
|
||||
touch ~/bazel_repository_cache/MARKER
|
||||
fi
|
||||
# Persist any changes at this point to be reused by further jobs.
|
||||
# **NOTE**: To add new content to the workspace, always persist on the same root.
|
||||
- persist_to_workspace:
|
||||
root: *workspace_location
|
||||
paths:
|
||||
- "node_modules"
|
||||
- "~/bazel_repository_cache"
|
||||
- ./ng
|
||||
- ./bazel_repository_cache
|
||||
|
||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||
test_ivy_aot:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
lint:
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- *setup_bazel_remote_execution
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
|
||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||
# not be able to easily find the output bin directory when uploading artifacts for size
|
||||
# measurements.
|
||||
- run: yarn test-ivy-aot //... --symlink_prefix=dist/
|
||||
|
||||
# Publish bundle artifacts which will be used to calculate the size change. **Note**: Make
|
||||
# sure that the size plugin from the Angular robot fetches the artifacts from this CircleCI
|
||||
# job (see .github/angular-robot.yml). Additionally any artifacts need to be stored with the
|
||||
# following path format: "{projectName}/{context}/{fileName}". This format is necessary
|
||||
# because otherwise the bot is not able to pick up the artifacts from CircleCI. See:
|
||||
# https://github.com/angular/github-robot/blob/master/functions/src/plugins/size.ts#L392-L394
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
||||
destination: core/hello_world/bundle
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js
|
||||
destination: core/todo/bundle
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js.br
|
||||
destination: core/hello_world/bundle.br
|
||||
- store_artifacts:
|
||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||
destination: core/todo/bundle.br
|
||||
- run: yarn -s tslint
|
||||
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
|
||||
- run: yarn -s ts-circular-deps:check
|
||||
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
||||
|
||||
test_aio:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
# Build aio
|
||||
- run: yarn --cwd aio build --progress=false
|
||||
# Lint the code
|
||||
- run: yarn --cwd aio lint
|
||||
# Run PWA-score tests
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Check the bundle sizes.
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio payload-size
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e
|
||||
# Run unit tests for Firebase redirects
|
||||
- run: yarn --cwd aio redirects-test
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
# Run PWA-score tests
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
# Run accessibility tests
|
||||
- run: yarn --cwd aio test-a11y-score-localhost
|
||||
|
||||
deploy_aio:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
||||
- image: *browsers_docker_image
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
# Deploy angular.io to production (if necessary)
|
||||
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
||||
- run: setPublicVar_CI_STABLE_BRANCH
|
||||
- run: yarn --cwd aio deploy-production
|
||||
|
||||
test_aio_local:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||
- image: *browsers_docker_image
|
||||
parameters:
|
||||
viewengine:
|
||||
type: boolean
|
||||
default: false
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
# Build aio (with local Angular packages)
|
||||
- run: yarn --cwd aio build-local --progress=false
|
||||
# Run PWA-score tests
|
||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
- run: yarn --cwd aio build-local<<# parameters.viewengine >>-with-viewengine<</ parameters.viewengine >>-ci
|
||||
# Run unit tests
|
||||
- run: yarn --cwd aio test --watch=false
|
||||
- run: yarn --cwd aio test --progress=false --watch=false
|
||||
# Run e2e tests
|
||||
- run: yarn --cwd aio e2e
|
||||
- run: yarn --cwd aio e2e --configuration=ci
|
||||
# Run PWA-score tests
|
||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||
|
||||
test_aio_tools:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
# Install
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run: yarn --cwd aio extract-cli-command-docs
|
||||
@ -218,58 +308,14 @@ jobs:
|
||||
- run: yarn --cwd aio tools-test
|
||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||
|
||||
test_docs_examples_0:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
# Install root
|
||||
- *yarn_install
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=0/2
|
||||
|
||||
test_docs_examples_1:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
# Install root
|
||||
- *yarn_install
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=1/2
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
<<: *job_defaults
|
||||
executor: default-executor
|
||||
environment:
|
||||
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *yarn_install
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||
- store_artifacts:
|
||||
path: *aio_preview_artifact_path
|
||||
@ -280,185 +326,81 @@ jobs:
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
test_aio_preview:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
||||
- image: *browsers_docker_image
|
||||
executor: default-executor
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- run: yarn install --cwd aio --frozen-lockfile --non-interactive
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- install_chrome_libs
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
- run:
|
||||
name: Wait for preview and run tests
|
||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||
|
||||
# This job exists only for backwards-compatibility with old scripts and tests
|
||||
# that rely on the pre-Bazel dist/packages-dist layout.
|
||||
# It duplicates some work with the job above: we build the bazel packages
|
||||
# twice. Even though we have a remote cache, these jobs will typically run in
|
||||
# parallel so up-to-date outputs will not be available at the time the build
|
||||
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
||||
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
||||
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
||||
# the bazel packages more than once. Even though we have a remote cache, these jobs will
|
||||
# typically run in parallel so up-to-date outputs will not be available at the time the build
|
||||
# starts.
|
||||
# No new jobs should depend on this one.
|
||||
build-packages-dist:
|
||||
<<: *job_defaults
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- *setup_circleci_bazel_config
|
||||
- *yarn_install
|
||||
- *setup_bazel_remote_execution
|
||||
|
||||
- run: scripts/build-packages-dist.sh
|
||||
# Build the view engine npm packages. No new jobs should depend on this.
|
||||
build-npm-packages:
|
||||
executor:
|
||||
name: default-executor
|
||||
resource_class: medium
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: node scripts/build/build-packages-dist.js
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||
- persist_to_workspace:
|
||||
root: dist
|
||||
root: *workspace_location
|
||||
paths:
|
||||
- packages-dist
|
||||
- packages-dist-ivy-aot
|
||||
- ng/dist/packages-dist
|
||||
- ng/dist/zone.js-dist
|
||||
|
||||
# We run the integration tests outside of Bazel for now.
|
||||
# They are a separate workflow job so that they can be easily re-run.
|
||||
# When the tests are ported to bazel test targets, they should move to the "test"
|
||||
# job above, as part of the bazel test command. That has flaky_test_attempts so the
|
||||
# need to re-run manually should be alleviated.
|
||||
# See comments inside the integration/run_tests.sh script.
|
||||
integration_test:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
||||
- image: *browsers_docker_image
|
||||
# Note: we run Bazel in one of the integration tests, and it can consume >2G
|
||||
# of memory. Together with the system under test, this can exhaust the RAM
|
||||
# on a 4G worker so we use a larger machine here too.
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
# Save dependencies and bazel repository cache to use on subsequent runs.
|
||||
- save_cache:
|
||||
key: *cache_key
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- run: ./integration/run_tests.sh
|
||||
paths:
|
||||
- "node_modules"
|
||||
- "aio/node_modules"
|
||||
- "~/bazel_repository_cache"
|
||||
- "~/.cache/bazelisk"
|
||||
|
||||
# This job updates the content of repos like github.com/angular/core-builds
|
||||
# for every green build on angular/angular.
|
||||
publish_snapshot:
|
||||
<<: *job_defaults
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *define_env_vars
|
||||
# See below - ideally this job should not trigger for non-upstream builds.
|
||||
# But since it does, we have to check this condition.
|
||||
- run:
|
||||
name: Skip this job for Pull Requests and Fork builds
|
||||
# Note, `|| true` on the end makes this step always exit 0
|
||||
command: '[[
|
||||
"$CI_PULL_REQUEST" != "false"
|
||||
|| "$CI_REPO_OWNER" != "angular"
|
||||
|| "$CI_REPO_NAME" != "angular"
|
||||
]] && circleci step halt || true'
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
# CircleCI has a config setting to force SSH for all github connections
|
||||
# This is not compatible with our mechanism of using a Personal Access Token
|
||||
# Clear the global setting
|
||||
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
||||
- run:
|
||||
name: Decrypt github credentials
|
||||
command: 'openssl aes-256-cbc -d -in .circleci/github_token -k "${KEY}" -out ~/.git_credentials'
|
||||
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||
|
||||
aio_monitoring:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# This job needs Chrome to be globally installed because the tests run with Protractor
|
||||
# which does not load the browser through the Bazel webtesting rules.
|
||||
- image: *browsers_docker_image
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: *cache_key
|
||||
- *define_env_vars
|
||||
- run:
|
||||
name: Run tests against the deployed apps
|
||||
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||
- run:
|
||||
name: Notify caretaker about failure
|
||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL'
|
||||
when: on_fail
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
default_workflow:
|
||||
jobs:
|
||||
- lint
|
||||
- test
|
||||
- test_ivy_aot
|
||||
- build-packages-dist
|
||||
- test_aio
|
||||
- setup:
|
||||
filters:
|
||||
branches:
|
||||
ignore: g3
|
||||
- lint:
|
||||
requires:
|
||||
- setup
|
||||
- build-npm-packages:
|
||||
requires:
|
||||
- setup
|
||||
- test_aio:
|
||||
requires:
|
||||
- setup
|
||||
- deploy_aio:
|
||||
requires:
|
||||
- test_aio
|
||||
- test_aio_local:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
- test_aio_tools:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- test_docs_examples_0:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- test_docs_examples_1:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- build-npm-packages
|
||||
- aio_preview:
|
||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||
filters:
|
||||
branches:
|
||||
only: /pull\/\d+/
|
||||
<<: *only_on_pull_requests
|
||||
requires:
|
||||
- setup
|
||||
- test_aio_preview:
|
||||
requires:
|
||||
- aio_preview
|
||||
- integration_test:
|
||||
requires:
|
||||
- build-packages-dist
|
||||
- publish_snapshot:
|
||||
# Note: no filters on this job because we want it to run for all upstream branches
|
||||
# We'd really like to filter out pull requests here, but not yet available:
|
||||
# https://discuss.circleci.com/t/workflows-pull-request-filter/14396/4
|
||||
# Instead, the job just exits immediately at the first step.
|
||||
requires:
|
||||
# Only publish if tests and integration tests pass
|
||||
- test
|
||||
- test_ivy_aot
|
||||
- integration_test
|
||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||
- test_aio_local
|
||||
- test_docs_examples_0
|
||||
- test_docs_examples_1
|
||||
# Get the artifacts to publish from the build-packages-dist job
|
||||
# since the publishing script expects the legacy outputs layout.
|
||||
- build-packages-dist
|
||||
|
||||
aio_monitoring:
|
||||
jobs:
|
||||
- aio_monitoring
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 0 * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
@ -15,7 +15,7 @@
|
||||
#
|
||||
# Usage: `setPublicVar <name> <value>`
|
||||
function setPublicVar() {
|
||||
setSecretVar $1 $2;
|
||||
setSecretVar $1 "$2";
|
||||
echo "$1=$2";
|
||||
}
|
||||
|
||||
@ -36,3 +36,38 @@ function setSecretVar() {
|
||||
# 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;
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
#!/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`).
|
||||
readonly envHelpersPath="`dirname $0`/env-helpers.inc.sh";
|
||||
source $envHelpersPath;
|
||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
|
||||
@ -9,17 +13,32 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||
####################################################################################################
|
||||
# Define PUBLIC environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setPublicVar PROJECT_ROOT "$(pwd)";
|
||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||
# 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 "62";
|
||||
# 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` will only be available when `CIRCLE_COMPARE_URL` is also available,
|
||||
# i.e. on push builds (a.k.a. non-PR builds). That is fine, since we only need it in push builds.
|
||||
setPublicVar CI_COMMIT_RANGE "$(sed -r 's|^.*/([0-9a-f]+\.\.\.[0-9a-f]+)$|\1|i' <<< ${CIRCLE_COMPARE_URL:-})";
|
||||
# `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/')";
|
||||
|
||||
|
||||
####################################################################################################
|
||||
@ -27,9 +46,68 @@ setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||
####################################################################################################
|
||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
# Defined in https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||
setSecretVar CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL "$SLACK_CARETAKER_WEBHOOK_URL";
|
||||
|
||||
|
||||
# Source `$BASH_ENV` to make the variables available immediately.
|
||||
####################################################################################################
|
||||
# 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 "09e68db8ed5b1253f2fe38ff954ef0df019fc25a"
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# 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.
@ -60,14 +60,15 @@ if (require.resolve === module) {
|
||||
|
||||
// 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);
|
||||
});
|
||||
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) {
|
||||
@ -77,15 +78,12 @@ function postJson(url, data) {
|
||||
const statusCode = res.statusCode || -1;
|
||||
let responseText = '';
|
||||
|
||||
res.
|
||||
on('error', reject).
|
||||
on('data', d => responseText += d).
|
||||
on('end', () => resolve({statusCode, 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));
|
||||
request(url, opts, onResponse).on('error', reject).end(JSON.stringify(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",
|
||||
],
|
||||
}
|
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
|
||||
|
758
.github/CODEOWNERS
vendored
758
.github/CODEOWNERS
vendored
@ -1,758 +0,0 @@
|
||||
# ==================================================================================
|
||||
# ==================================================================================
|
||||
# Angular CODEOWNERS
|
||||
# ==================================================================================
|
||||
# ==================================================================================
|
||||
#
|
||||
# Configuration of code ownership and review approvals for the angular/angular repo.
|
||||
#
|
||||
# More info: https://help.github.com/articles/about-codeowners/
|
||||
#
|
||||
|
||||
|
||||
# ================================================
|
||||
# General rules / philosophy
|
||||
# ================================================
|
||||
#
|
||||
# - we trust that people do the right thing and not approve changes they don't feel confident reviewing
|
||||
# - we use github teams so that we funnel code reviews to the most appropriate reviewer, this is why the team structure is fine-grained
|
||||
# - we enforce that only approved PRs get merged to ensure that unreviewed code doesn't get accidentaly merged
|
||||
# - we delegate approval rights as much as possible so that we can scale better
|
||||
# - each group must have at least one person, but several people are preferable to avoid a single point of failure issues
|
||||
# - most file groups have one or two global approvers groups as fallbacks:
|
||||
# - @angular/fw-global-approvers: for approving minor changes, large-scale refactorings, and emergency situations.
|
||||
# - @angular/fw-global-approvers-for-docs-only-changes: for approving minor documentation-only changes that don't require engineering review
|
||||
# - a small number of file groups have very limited number of reviewers because incorrect changes to the files they guard would have serious consequences (e.g. security, public api)
|
||||
#
|
||||
# Configuration nuances:
|
||||
#
|
||||
# - This configuration works in conjunction with the protected branch settings that require all changes to be made via pull requests with at least one approval.
|
||||
# - This approval can come from an appropriate codeowner, or any repo collaborator (person with write access) if the PR is authored by a codeowner.
|
||||
# - Each codeowners team must have write access to the repo, otherwise their reviewes won't count.
|
||||
#
|
||||
# In the case of emergency, the repo administrators which include angular-caretaker can bypass this requirement.
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# GitHub username registry
|
||||
# (just to make this file easier to understand)
|
||||
# ================================================
|
||||
|
||||
# alexeagle - Alex Eagle
|
||||
# alxhub - Alex Rickabaugh
|
||||
# AndrewKushnir - Andrew Kushnir
|
||||
# andrewseguin - Andrew Seguin
|
||||
# benlesh - Ben Lesh
|
||||
# brandonroberts - Brandon Roberts
|
||||
# filipesilva - Filipe Silva
|
||||
# gkalpak - George Kalpakas
|
||||
# hansl - Hans Larsen
|
||||
# IgorMinar - Igor Minar
|
||||
# jasonaden - Jason Aden
|
||||
# jenniferfell - Jennifer Fell
|
||||
# kara - Kara Erickson
|
||||
# kyliau - Keen Yee Liau
|
||||
# matsko - Matias Niemelä
|
||||
# mhevery - Misko Hevery
|
||||
# ocombe - Olivier Combe
|
||||
# petebacondarwin - Pete Bacon Darwin
|
||||
# pkozlowski-opensource - Pawel Kozlowski
|
||||
# robwormald - Rob Wormald
|
||||
# stephenfluin - Stephen Fluin
|
||||
# vikerman - Vikram Subramanian
|
||||
|
||||
|
||||
|
||||
######################################################################################################
|
||||
#
|
||||
# Team structure and memberships
|
||||
# ------------------------------
|
||||
#
|
||||
# This section is here just because the GitHub UI is too hard to navigate and audit.
|
||||
#
|
||||
# Any changes to team structure or memberships must first be made in this file and only then
|
||||
# implemented in the GitHub UI.
|
||||
#######################################################################################################
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/framework-global-approvers
|
||||
# ===========================================================
|
||||
# Used for approving minor changes, large-scale refactorings, and emergency situations.
|
||||
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
||||
#
|
||||
# - IgorMinar
|
||||
# - kara
|
||||
# - mhevery
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/framework-global-approvers-for-docs-only-changes
|
||||
# ===========================================================
|
||||
# Used for approving minor documentation-only changes that don't require engineering review.
|
||||
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
||||
#
|
||||
# - gkalpak
|
||||
# - jenniferfell
|
||||
# - petebacondarwin
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-animations
|
||||
# ===========================================================
|
||||
#
|
||||
# - matsko
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/tools-bazel
|
||||
# ===========================================================
|
||||
#
|
||||
# - alexeagle
|
||||
# - kyliau
|
||||
# - IgorMinar
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/tools-cli
|
||||
# ===========================================================
|
||||
#
|
||||
# - alexeagle
|
||||
# - filipesilva
|
||||
# - hansl
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-compiler
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-ngcc
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
# - gkalpak
|
||||
# - petebacondarwin
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-core
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
# - AndrewKushnir
|
||||
# - kara
|
||||
# - mhevery
|
||||
# - pkozlowski-opensource
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-http
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
# - IgorMinar
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-elements
|
||||
# ===========================================================
|
||||
#
|
||||
# - andrewseguin
|
||||
# - gkalpak
|
||||
# - robwormald
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-forms
|
||||
# ===========================================================
|
||||
#
|
||||
# - kara
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/tools-language-service
|
||||
# ===========================================================
|
||||
#
|
||||
# - kyliau
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-server
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
# - vikerman
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-router
|
||||
# ===========================================================
|
||||
#
|
||||
# - jasonaden
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-service-worker
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
# - gkalpak
|
||||
# - IgorMinar
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-upgrade
|
||||
# ===========================================================
|
||||
#
|
||||
# - gkalpak
|
||||
# - petebacondarwin
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-testing
|
||||
# ===========================================================
|
||||
#
|
||||
# - vikerman
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-i18n
|
||||
# ===========================================================
|
||||
#
|
||||
# - AndrewKushnir
|
||||
# - mhevery
|
||||
# - ocombe
|
||||
# - vikerman
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-security
|
||||
# ===========================================================
|
||||
#
|
||||
# - IgorMinar
|
||||
# - mhevery
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/tools-benchpress
|
||||
# ===========================================================
|
||||
#
|
||||
# - alxhub
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-integration
|
||||
# ===========================================================
|
||||
#
|
||||
# - alexeagle
|
||||
# - IgorMinar
|
||||
# - mhevery
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/docs-infra
|
||||
# ===========================================================
|
||||
#
|
||||
# - gkalpak
|
||||
# - IgorMinar
|
||||
# - petebacondarwin
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-docs-intro
|
||||
# ===========================================================
|
||||
#
|
||||
# - brandonroberts
|
||||
# - IgorMinar
|
||||
# - stephenfluin
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-docs-observables
|
||||
# ===========================================================
|
||||
#
|
||||
# - benlesh
|
||||
# - jasonaden
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-docs-packaging
|
||||
# ===========================================================
|
||||
#
|
||||
# - alexeagle
|
||||
# - IgorMinar
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-docs-marketing
|
||||
# ===========================================================
|
||||
#
|
||||
# - IgorMinar
|
||||
# - stephenfluin
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-public-api
|
||||
# ===========================================================
|
||||
#
|
||||
# - IgorMinar
|
||||
|
||||
|
||||
# ===========================================================
|
||||
# @angular/fw-dev-infra
|
||||
# ===========================================================
|
||||
#
|
||||
# - alexeagle
|
||||
# - IgorMinar
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
######################################################################################################
|
||||
#
|
||||
# CODEOWNERS rules
|
||||
# -----------------
|
||||
#
|
||||
# All the following rules are applied in the order specified in this file.
|
||||
# The last rule that matches wins!
|
||||
#
|
||||
# See https://git-scm.com/docs/gitignore#_pattern_format for pattern syntax docs.
|
||||
#
|
||||
######################################################################################################
|
||||
|
||||
|
||||
# ================================================
|
||||
# Default Owners
|
||||
# (in case no pattern matches a path in a PR - this should be treated as a bug and result in adding the path to CODEOWNERS)
|
||||
# ================================================
|
||||
|
||||
* @IgorMinar @angular/framework-global-approvers
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/animations
|
||||
# ================================================
|
||||
|
||||
/packages/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/platform-browser/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/bazel
|
||||
# ================================================
|
||||
|
||||
/packages/bazel/** @angular/tools-bazel @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/compiler
|
||||
# @angular/compiler-cli
|
||||
# ================================================
|
||||
|
||||
/packages/compiler/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/compiler-cli/** @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/aot-compiler.md @angular/fw-compiler @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# packages/compiler-cli/src/ngcc/
|
||||
# ================================================
|
||||
|
||||
/packages/compiler-cli/src/ngcc/** @angular/fw-ngcc @angular/framework-global-approvers
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/compiler-cli/ngtools
|
||||
#
|
||||
# a rule to control API changes between @angular/compiler-cli and @angular/cli
|
||||
# ================================================
|
||||
|
||||
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/core
|
||||
# @angular/common (except @angular/common/http)
|
||||
# @angular/platform-browser
|
||||
# @angular/platform-browser-dynamic
|
||||
# @angular/platform-webworker
|
||||
# ================================================
|
||||
|
||||
/packages/core/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/platform-browser/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/platform-browser-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/attribute-directives.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/bootstrapping.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/bootstrapping/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/component-interaction.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/component-styles.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/component-styles/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/dependency-injection-in-action.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/dependency-injection-pattern.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/dynamic-component-loader.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/entry-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/feature-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/feature-modules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/feature-modules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/frequent-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/frequent-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/hierarchical-dependency-injection.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/hierarchical-dependency-injection/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/lazy-loading-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/lazy-loading-ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/lifecycle-hooks.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/lifecycle-hooks/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/lifecycle-hooks/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/examples/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/ngmodule/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/ngmodule/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/ngmodule-api.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/ngmodule-faq.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/ngmodule-faq/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/ngmodule-vs-jsmodule.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/module-types.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/template-syntax.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/pipes.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/pipes/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/providers.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/providers/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/singleton-services.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/set-document-title.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/set-document-title/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/set-document-title/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/sharing-ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
/aio/content/guide/structural-directives.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/common/http
|
||||
# ================================================
|
||||
|
||||
/packages/common/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/http.md @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/http/** @angular/fw-http @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/elements
|
||||
# ================================================
|
||||
|
||||
/packages/elements/** @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/elements/** @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/elements/** @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/elements.md @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/forms
|
||||
# ================================================
|
||||
|
||||
/packages/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/forms-overview.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/forms-overview/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/forms-overview/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/form-validation.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/form-validation/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/form-validation/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/dynamic-form.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/dynamic-form/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/dynamic-form/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/reactive-forms.md @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/reactive-forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/reactive-forms/** @angular/fw-forms @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/language-service
|
||||
# ================================================
|
||||
|
||||
/packages/language-service/** @angular/tools-language-service @angular/framework-global-approvers
|
||||
/aio/content/guide/language-service.md @angular/tools-language-service @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/language-service/** @angular/tools-language-service @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/platform-server
|
||||
# ================================================
|
||||
|
||||
/packages/platform-server/** @angular/fw-server @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/universal.md @angular/fw-server @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/universal/** @angular/fw-server @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/router
|
||||
# ================================================
|
||||
|
||||
/packages/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/router.md @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/router/** @angular/fw-router @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/service-worker
|
||||
# ================================================
|
||||
|
||||
/packages/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-getting-started.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/service-worker-getting-started/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-communications.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-config.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-devops.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/service-worker-intro.md @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/service-worker/** @angular/fw-service-worker @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/upgrade
|
||||
# ================================================
|
||||
|
||||
/packages/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/examples/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/upgrade.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-module/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/upgrade/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-phonecat-1-typescript/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-phonecat-2-hybrid/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/upgrade-phonecat-3-final/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/upgrade-performance.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/ajs-quick-reference.md @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/ajs-quick-reference/** @angular/fw-upgrade @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular/**/testing
|
||||
# ================================================
|
||||
|
||||
testing/** @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/testing.md @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/testing/** @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/testing/** @angular/fw-testing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular i18n
|
||||
# ================================================
|
||||
|
||||
/packages/core/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/core/src/render3/i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/core/src/render3/i18n.md @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/core/src/render3/interfaces/i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/locales/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/src/pipes/date_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/src/pipes/i18n_plural_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/src/pipes/i18n_select_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/common/src/pipes/number_pipe.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/compiler/src/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/compiler/src/render3/view/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/packages/compiler-cli/src/extract_i18n.ts @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/i18n.md @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/i18n/** @angular/fw-i18n @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# @angular security
|
||||
# ================================================
|
||||
|
||||
/packages/core/src/sanitization/** @angular/fw-security
|
||||
/packages/core/test/linker/security_integration_spec.ts @angular/fw-security
|
||||
/packages/compiler/src/schema/** @angular/fw-security
|
||||
/packages/platform-browser/src/security/** @angular/fw-security
|
||||
/aio/content/guide/security.md @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# benchpress
|
||||
# ================================================
|
||||
|
||||
/packages/benchpress/** @angular/tools-benchpress @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# /integration/*
|
||||
# ================================================
|
||||
|
||||
/integration/** @angular/fw-integration @angular/framework-global-approvers
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# docs-infra
|
||||
# ================================================
|
||||
|
||||
/aio/* @angular/docs-infra @angular/framework-global-approvers
|
||||
/aio/aio-builds-setup/** @angular/docs-infra @angular/framework-global-approvers
|
||||
/aio/scripts/** @angular/docs-infra @angular/framework-global-approvers
|
||||
/aio/src/** @angular/docs-infra @angular/framework-global-approvers
|
||||
/aio/tests/** @angular/docs-infra @angular/framework-global-approvers
|
||||
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Docs: getting started & tutorial
|
||||
# ================================================
|
||||
|
||||
/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Docs: observables
|
||||
# ================================================
|
||||
|
||||
/aio/content/examples/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/comparing-observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/guide/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/observables-in-angular.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/practical-observable-usage/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/rx-library/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/rx-library.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Docs: packaging, tooling, releasing
|
||||
# ================================================
|
||||
|
||||
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/setup-systemjs-anatomy.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Docs: marketing
|
||||
# ================================================
|
||||
|
||||
/aio/content/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/images/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/navigation.json @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
/aio/content/license.md @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Public API
|
||||
# ================================================
|
||||
|
||||
/tools/public_api_guard/** @angular/fw-public-api
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# Build & CI Owners
|
||||
# ================================================
|
||||
|
||||
/* @angular/fw-dev-infra
|
||||
/.buildkite/** @angular/fw-dev-infra
|
||||
/.circleci/** @angular/fw-dev-infra
|
||||
/.github/** @angular/fw-dev-infra
|
||||
/docs/BAZEL.md @angular/fw-dev-infra
|
||||
/scripts/** @angular/fw-dev-infra
|
||||
/third_party/** @angular/fw-dev-infra
|
||||
/tools/** @angular/fw-dev-infra
|
||||
*.bzl @angular/fw-dev-infra
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# CODEOWNERS Owners owners ...
|
||||
# ================================================
|
||||
|
||||
/.github/CODEOWNERS @IgorMinar @angular/framework-global-approvers
|
67
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
67
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -1,67 +0,0 @@
|
||||
---
|
||||
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-issue-repro2
|
||||
-->
|
||||
<!-- ✍️--> 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. 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
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@ -1,32 +0,0 @@
|
||||
---
|
||||
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
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
@ -1,55 +0,0 @@
|
||||
---
|
||||
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. -->
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
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
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
@ -1,16 +0,0 @@
|
||||
---
|
||||
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
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
@ -1,13 +0,0 @@
|
||||
---
|
||||
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-material.md
vendored
13
.github/ISSUE_TEMPLATE/7-angular-material.md
vendored
@ -1,13 +0,0 @@
|
||||
---
|
||||
name: "\U0001F48EAngular Material"
|
||||
about: Issues and feature requests for Angular Material
|
||||
|
||||
---
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||
|
||||
Please file any Angular Material issues at: https://github.com/angular/material2/issues/new
|
||||
|
||||
For the time being, we keep Angular Material issues in a separate repository.
|
||||
|
||||
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
name: "📚Traducir doc al español"
|
||||
about: Solicitud para traducir ciertos docs al español
|
||||
|
||||
---
|
||||
|
||||
📚Traducir: <!-- ✍️ editar: --> creating-libraries.md
|
||||
|
||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||
|
||||
Traducción de la documentación oficial de Angular a español
|
||||
|
||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||
|
||||
|
||||
## Nombre del archivo:
|
||||
<!-- ✍️ editar: --> creating-libraries.md
|
||||
|
||||
|
||||
## Ruta donde se encuentra el archivo dentro del proyecto de Angular
|
||||
|
||||
<!-- ✍️ editar: --> https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md
|
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,43 +1,35 @@
|
||||
## PR Checklist
|
||||
Please check if your PR fulfills the following requirements:
|
||||
## Lista de Verificación del PR
|
||||
Comprueba si tu PR cumple los siguientes requisitos:
|
||||
|
||||
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||
- [ ] Docs have been added / updated (for bug fixes / features)
|
||||
- [ ] El mensaje de commit esta conforme con [nuestras reglas](https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md#-formato-para-el-mensaje-de-los-commits)
|
||||
- [ ] Probe los cambios que agregué (arreglo de bugs / funcionalidades)
|
||||
- [ ] Revisé previamente las traducciones o cambios de contenido
|
||||
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/blob/master/aio/diccionario-de-términos.md) en español
|
||||
- [ ] He creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
|
||||
- [ ] He enlazado el commit con el issue correspondiente <!-- ejemplo Fixes #X -->
|
||||
|
||||
|
||||
## PR Type
|
||||
What kind of change does this PR introduce?
|
||||
## Tipo de PR
|
||||
¿Qué tipo de cambio introduce este PR?
|
||||
|
||||
<!-- Please check the one that applies to this PR using "x". -->
|
||||
<!-- Marca con una "x" las opciones que aplican. -->
|
||||
|
||||
- [ ] 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:
|
||||
- [ ] Funcionalidad
|
||||
- [ ] Actualización de el estilo del código (formato, variables locales)
|
||||
- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api)
|
||||
- [ ] Cambios relacionados al build
|
||||
- [ ] Cambios relacionados al CI (Integración continua)
|
||||
- [ ] Cambios en el contenido de la documentación
|
||||
- [ ] Cambios en la aplicación / infraestructura de angular.io
|
||||
- [ ] Otro... Por favor describe la:
|
||||
|
||||
## ¿Cuál es el comportamiento actual?
|
||||
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
|
||||
-->
|
||||
|
||||
|
||||
## What is the current behavior?
|
||||
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
||||
|
||||
Issue Number: N/A
|
||||
|
||||
|
||||
## What is the new behavior?
|
||||
|
||||
|
||||
## Does this PR introduce a breaking change?
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
|
||||
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
|
||||
|
||||
|
||||
## Other information
|
||||
## ¿Cuál es el nuevo comportamiento?
|
||||
<!--
|
||||
Ejemplo: Archivo en inglés traducido al español
|
||||
-->
|
||||
|
34
.github/angular-robot.yml
vendored
34
.github/angular-robot.yml
vendored
@ -30,32 +30,36 @@ 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/src/ngcc/**"
|
||||
- "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"
|
||||
@ -63,6 +67,10 @@ merge:
|
||||
- "**/*.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.
|
||||
@ -101,9 +109,14 @@ merge:
|
||||
|
||||
# list of PR statuses that need to be successful
|
||||
requiredStatuses:
|
||||
- "continuous-integration/travis-ci/pr"
|
||||
- "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
|
||||
@ -141,6 +154,12 @@ triage:
|
||||
-
|
||||
- "type: RFC / Discussion / question"
|
||||
- "comp: *"
|
||||
-
|
||||
- "type: confusing"
|
||||
- "comp: *"
|
||||
-
|
||||
- "type: use-case"
|
||||
- "comp: *"
|
||||
|
||||
# options for the triage PR plugin
|
||||
triagePR:
|
||||
@ -161,3 +180,10 @@ triagePR:
|
||||
- "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 }}
|
21
.gitignore
vendored
21
.gitignore
vendored
@ -1,22 +1,28 @@
|
||||
.DS_STORE
|
||||
|
||||
/dist/
|
||||
/bazel-*
|
||||
/bazel-out
|
||||
/integration/bazel/bazel-*
|
||||
e2e_test.*
|
||||
*.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
|
||||
.vscode
|
||||
modules/.vscode
|
||||
.vimrc
|
||||
.nvimrc
|
||||
|
||||
# Don't check in secret files
|
||||
*secret.js
|
||||
@ -34,3 +40,8 @@ yarn-error.log
|
||||
# User specific bazel settings
|
||||
.bazelrc.user
|
||||
|
||||
.notes.md
|
||||
baseline.json
|
||||
|
||||
# Ignore .history for the xyz.local-history VSCode extension
|
||||
.history
|
||||
|
145
.gitmessage
Normal file
145
.gitmessage
Normal file
@ -0,0 +1,145 @@
|
||||
<type>(<scope>): <summary>
|
||||
|
||||
<Describe the motivation behind this change - explain WHY you are making this change. Wrap all lines
|
||||
at 100 characters.>
|
||||
|
||||
Fixes #<issue number>
|
||||
|
||||
# ────────────────────────────────────────── 100 chars ────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# Example Commit Messages
|
||||
# =======================
|
||||
|
||||
|
||||
# ─── Example: Simple refactor ────────────────────────────────────────────────────────────────────┤
|
||||
# refactor(core): rename refreshDynamicEmbeddedViews to refreshEmbeddedViews
|
||||
#
|
||||
# Improve code readability. The original name no longer matches how the function is used.
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: Simple docs change ─────────────────────────────────────────────────────────────────┤
|
||||
# docs: clarify the service limitation in providers.md guide
|
||||
#
|
||||
# Fixes #36332
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: A bug fix ──────────────────────────────────────────────────────────────────────────┤
|
||||
# fix(ngcc): ensure lockfile is removed when `analyzeFn` fails
|
||||
#
|
||||
# Previously an error thrown in the `analyzeFn` would cause the ngcc process to exit immediately
|
||||
# without removing the lockfile, and potentially before the unlocker process had been successfully
|
||||
# spawned resulting in the lockfile being orphaned and left behind.
|
||||
#
|
||||
# Now we catch these errors and remove the lockfile as needed.
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
# ─── Example: Breaking change ────────────────────────────────────────────────────────────────────┤
|
||||
# feat(bazel): simplify ng_package by dropping esm5 and fesm5
|
||||
#
|
||||
# esm5 and fesm5 distributions are no longer needed and have been deprecated in the past.
|
||||
#
|
||||
# https://v9.angular.io/guide/deprecations#esm5-and-fesm5-code-formats-in-angular-npm-packages
|
||||
#
|
||||
# This commit modifies ng_package to no longer distribute these two formats in npm packages built by
|
||||
# ng_package (e.g. @angular/core).
|
||||
#
|
||||
# This commit intentionally doesn't fully clean up the ng_package rule to remove all traces of esm5
|
||||
# and fems5 build artifacts as that is a bigger cleanup and currently we are narrowing down the
|
||||
# scope of this change to the MVP needed for v10, which in this case is 'do not put esm5 and fesm5'
|
||||
# into the npm packages.
|
||||
#
|
||||
# More cleanup to follow: https://angular-team.atlassian.net/browse/FW-2143
|
||||
#
|
||||
# BREAKING CHANGE: esm5 and fesm5 format is no longer distributed in Angular's npm packages e.g.
|
||||
# @angular/core
|
||||
#
|
||||
# Angular CLI will automatically downlevel the code to es5 if differential loading is enabled in the
|
||||
# Angular project, so no action is required from Angular CLI users.
|
||||
#
|
||||
# If you are not using Angular CLI to build your application or library, and you need to be able to
|
||||
# build es5 artifacts, then you will need to downlevel the distributed Angular code to es5 on your
|
||||
# own.
|
||||
#
|
||||
#
|
||||
# Fixes #1234
|
||||
# ─────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
|
||||
|
||||
|
||||
# Angular Commit Message Format
|
||||
# =============================
|
||||
#
|
||||
# The full specification of the Angular Commit Message Format can be found at
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
#
|
||||
# The following is an excerpt of the specification with the most commonly needed info.
|
||||
#
|
||||
# Each commit message consists of a *header*, a *body*, and a *footer*.
|
||||
#
|
||||
# <header>
|
||||
# <BLANK LINE>
|
||||
# <body>
|
||||
# <BLANK LINE>
|
||||
# <footer>
|
||||
#
|
||||
# The header is mandatory.
|
||||
#
|
||||
# The body is mandatory for all commits except for those of scope "docs". When the body is required
|
||||
# it must be at least 20 characters long.
|
||||
#
|
||||
# The footer is optional.
|
||||
#
|
||||
# Any line of the commit message cannot be longer than 100 characters.
|
||||
#
|
||||
#
|
||||
# Commit Message Header
|
||||
# ---------------------
|
||||
#
|
||||
# <type>(<scope>): <short summary>
|
||||
# │ │ │
|
||||
# │ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
# │ │
|
||||
# │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
# │ elements|forms|http|language-service|localize|platform-browser|
|
||||
# │ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
# │ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
# │ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
|
||||
# │
|
||||
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
|
||||
#
|
||||
#
|
||||
# Commit Message Body
|
||||
# ---------------------
|
||||
#
|
||||
# Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
#
|
||||
# Explain the motivation for the change in the commit message body. This commit message should
|
||||
# explain WHY you are making the change. You can include a comparison of the previous behavior with
|
||||
# the new behavior in order to illustrate the impact of the change.
|
||||
#
|
||||
#
|
||||
# Commit Message Footer
|
||||
# ---------------------
|
||||
#
|
||||
# The footer can contain information about breaking changes and is also the place to reference
|
||||
# GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||
#
|
||||
# ```
|
||||
# BREAKING CHANGE: <breaking change summary>
|
||||
# <BLANK LINE>
|
||||
# <breaking change description + migration instructions>
|
||||
# <BLANK LINE>
|
||||
# <BLANK LINE>
|
||||
# Fixes #<issue number>
|
||||
# ```
|
||||
#
|
||||
# Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of
|
||||
# the breaking change, a blank line, and a detailed description of the breaking change that also
|
||||
# includes migration instructions.
|
||||
#
|
53
.ng-dev/commit-message.ts
Normal file
53
.ng-dev/commit-message.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import {CommitMessageConfig} from '../dev-infra/commit-message/config';
|
||||
|
||||
/**
|
||||
* The configuration for `ng-dev commit-message` commands.
|
||||
*/
|
||||
export const commitMessage: CommitMessageConfig = {
|
||||
maxLineLength: 120,
|
||||
minBodyLength: 20,
|
||||
minBodyLengthTypeExcludes: ['docs', 'upstream'],
|
||||
types: [
|
||||
'build',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'release',
|
||||
'style',
|
||||
'test',
|
||||
'upstream',
|
||||
],
|
||||
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',
|
||||
]
|
||||
};
|
11
.ng-dev/config.ts
Normal file
11
.ng-dev/config.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {commitMessage} from './commit-message';
|
||||
import {format} from './format';
|
||||
import {github} from './github';
|
||||
import {merge} from './merge';
|
||||
|
||||
module.exports = {
|
||||
commitMessage,
|
||||
format,
|
||||
github,
|
||||
merge,
|
||||
};
|
22
.ng-dev/format.ts
Normal file
22
.ng-dev/format.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import {FormatConfig} from '../dev-infra/format/config';
|
||||
|
||||
/**
|
||||
* Configuration for the `ng-dev format` command.
|
||||
*/
|
||||
export const format: FormatConfig = {
|
||||
'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
|
||||
};
|
15
.ng-dev/gitconfig
Normal file
15
.ng-dev/gitconfig
Normal file
@ -0,0 +1,15 @@
|
||||
# The file is inert unless it's explicitly included into the local git config via:
|
||||
#
|
||||
# ```
|
||||
# git config --add include.path '../.ng-dev/gitconfig'
|
||||
# ```
|
||||
#
|
||||
# Calling that command will append the following into `.git/config` of the current git workspace
|
||||
# (i.e. $GIT_DIR, typically `angular/.git/config`):
|
||||
#
|
||||
# ```
|
||||
# [include]
|
||||
# path = ../.ng-dev/gitconfig
|
||||
# ```
|
||||
[commit]
|
||||
template = .gitmessage
|
11
.ng-dev/github.ts
Normal file
11
.ng-dev/github.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {GithubConfig} from '../dev-infra/utils/config';
|
||||
|
||||
/**
|
||||
* Github configuration for the `ng-dev` command. This repository is used as
|
||||
* remote for the merge script and other utilities like `ng-dev pr rebase`.
|
||||
*/
|
||||
|
||||
export const github: GithubConfig = {
|
||||
owner: 'angular',
|
||||
name: 'angular'
|
||||
};
|
38
.ng-dev/merge.ts
Normal file
38
.ng-dev/merge.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||
|
||||
/**
|
||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||
* are respected by the merge script (e.g. the target labels).
|
||||
*/
|
||||
export const merge = (): MergeConfig => {
|
||||
// TODO: resume dynamically determining patch branch
|
||||
const patch = '10.0.x';
|
||||
return {
|
||||
githubApiMerge: false,
|
||||
claSignedLabel: 'cla: yes',
|
||||
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||
caretakerNoteLabel: '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'
|
||||
},
|
||||
};
|
||||
};
|
1302
.pullapprove.yml
Normal file
1302
.pullapprove.yml
Normal file
File diff suppressed because it is too large
Load Diff
66
.travis.yml
66
.travis.yml
@ -1,66 +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="
|
||||
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
|
||||
|
||||
# We disable these optional jobs because those acquire tunnel and browser instances which
|
||||
# could lead to rate limit excess while those are failing most of the time and nobody pays
|
||||
# attention anyway.
|
||||
# - CI_MODE=saucelabs_optional
|
||||
# - CI_MODE=browserstack_optional
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- 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
|
||||
- ./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,
|
||||
},
|
||||
]
|
||||
}
|
32
.vscode/recommended-settings.json
vendored
Normal file
32
.vscode/recommended-settings.json
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
// 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,
|
||||
".history": 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"
|
63
BUILD.bazel
63
BUILD.bazel
@ -1,22 +1,33 @@
|
||||
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",
|
||||
])
|
||||
|
||||
alias(
|
||||
name = "tsconfig.json",
|
||||
actual = "//packages:tsconfig-build.json",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "web_test_bootstrap_scripts",
|
||||
# do not sort
|
||||
srcs = [
|
||||
"@ngdeps//node_modules/reflect-metadata:Reflect.js",
|
||||
"@ngdeps//node_modules/zone.js:dist/zone.js",
|
||||
"@ngdeps//node_modules/zone.js:dist/zone-testing.js",
|
||||
"@ngdeps//node_modules/zone.js:dist/task-tracking.js",
|
||||
"@npm//:node_modules/core-js/client/core.js",
|
||||
"//packages/zone.js/bundles:zone.umd.js",
|
||||
"//packages/zone.js/bundles:zone-testing.umd.js",
|
||||
"//packages/zone.js/bundles:task-tracking.umd.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",
|
||||
],
|
||||
)
|
||||
|
||||
@ -25,32 +36,14 @@ filegroup(
|
||||
srcs = [
|
||||
# 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)
|
||||
"@ngdeps//node_modules/angular:angular.js",
|
||||
"@ngdeps//node_modules/angular:angular.min.js",
|
||||
"@ngdeps//node_modules/angular-1.5:angular.js",
|
||||
"@ngdeps//node_modules/angular-1.5:angular.min.js",
|
||||
"@ngdeps//node_modules/angular-1.6:angular.js",
|
||||
"@ngdeps//node_modules/angular-1.6:angular.min.js",
|
||||
"@ngdeps//node_modules/angular-mocks:angular-mocks.js",
|
||||
"@ngdeps//node_modules/angular-mocks-1.5:angular-mocks.js",
|
||||
"@ngdeps//node_modules/angular-mocks-1.6:angular-mocks.js",
|
||||
"@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",
|
||||
],
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||
|
||||
# A nodejs_binary for @angular/bazel/ngc-wrapped to use by default in
|
||||
# ng_module that depends on @npm//@angular/bazel instead of the
|
||||
# output of the //packages/bazel/src/ngc-wrapped ts_library rule. This
|
||||
# default is for downstream users that depend on the @angular/bazel npm
|
||||
# package. The generated @npm//@angular/bazel/ngc-wrapped target
|
||||
# does not work because it does not have the node `--expose-gc` flag
|
||||
# set which is required to support the call to `global.gc()`.
|
||||
nodejs_binary(
|
||||
name = "@angular/bazel/ngc-wrapped",
|
||||
configuration_env_vars = ["compile"],
|
||||
data = ["@npm//@angular/bazel"],
|
||||
entry_point = "@angular/bazel/src/ngc-wrapped/index.js",
|
||||
install_source_map_support = False,
|
||||
templated_args = ["--node_options=--expose-gc"],
|
||||
)
|
||||
|
2867
CHANGELOG.md
2867
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,72 @@
|
||||
# Contributor Code of Conduct
|
||||
## Version 0.3b-angular
|
||||
# Código de Conducta
|
||||
|
||||
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
||||
## 1. Propósito
|
||||
|
||||
Communication through any of Angular's channels (GitHub, Gitter, IRC, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||
“Prometemos brindar cortesía y respeto a cualquier persona involucrada en esta comunidad, sin importar el género con el que se identifique, su orientación sexual, limitación física, edad, raza, etnia, religión o nivel de conocimiento. Esperamos que cualquiera que desee contribuir en este proyecto brinde el mismo comportamiento”
|
||||
|
||||
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
|
||||
Bajo ese principio queremos enfocar esta comunidad, una comunidad de respeto por el otro, donde cualquiera que sienta pasión por Angular y desee involucrarse con cualquier tipo de actividad deberá ayudar a mantener una atmósfera de cortesía por el otro, respetando los pensamientos, acciones, ideales y propuestas del otro.
|
||||
|
||||
If any member of the community violates this code of conduct, the maintainers of the Angular project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
||||
## 2. Comportamiento esperado
|
||||
|
||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [conduct@angular.io](mailto:conduct@angular.io).
|
||||
- Evitar usar expresiones o gestos insultantes, humillantes o intimidatorios para referirnos a otros.
|
||||
- Ejercita la consideración y el respeto en tus comunicaciones y acciones.
|
||||
- Absténte de adoptar una conducta y un lenguaje degradantes, discriminatorios, abusivos o acosadores.
|
||||
- Evitar comportamientos que agredan las expresiones de identidad, género, creencias religiosas, acciones que lastimen o los aíslen a otros.
|
||||
- Evitar comentarios sobre ideas políticas.
|
||||
- No se toleran conductas físicas y actitudes dirigidas al descrédito personal, físico o emocional de cualquier persona.
|
||||
- No se toleran chistes y comentarios excluyentes, sexistas y racistas.
|
||||
- Se rechaza actitudes de hostigamiento.
|
||||
- Se rechaza el acoso: este se entiende como cualquier tipo de comentario verbal que refuerce discriminación por género, identidad y expresión de género, orientación sexual, discapacidad, apariencia física, tamaño corporal, raza, edad o religión en contextos laborales o sociales.
|
||||
- No se tolera el contacto físico y/o la atención sexual no deseada.
|
||||
- Promover la igualdad de oportunidades de formación, educación, intercambio y retroalimentación antes, durante y después de los eventos.
|
||||
- Intenta colaborar en lugar de generar conflicto.
|
||||
- Sé consciente de tu entorno y de tus compañeros participantes. Alerta a líderes de la comunidad si notas una situación peligrosa, alguien en apuros, o violaciones de este Código de Conducta, incluso si parecen intrascendentes.
|
||||
|
||||
## 3. Comportamiento inaceptable
|
||||
Comportamientos inaceptables incluyen: intimidación, acoso, abuso, discriminación, comunicación despectiva o degradante o acciones por cualquier participante en nuestra comunidad ya sea virtual, o en las comunicaciones uno-a-uno que se realizan en el contexto de la comunidad. Por favor ser respetuoso con todos.
|
||||
|
||||
El acoso incluye: comentarios nocivos o perjudiciales, verbales o escritos relacionados con el género, la orientación sexual, raza, religión, discapacidad; uso inadecuado de desnudos y / o imágenes sexuales en espacios públicos (incluyendo la presentación diapositivas); intimidación deliberada, acecho o seguimiento; fotografías o grabaciones acosadoras; interrupción sostenida de charlas y otros eventos; contacto físico inapropiado, y atención sexual no deseada.
|
||||
|
||||
## 4. Consecuencias de comportamiento inaceptable
|
||||
Se espera que personas a quienes se les solicite que detengan su comportamiento inaceptable lo hagan de manera inmediata esto será válido para cualquier miembro de la comunidad.
|
||||
|
||||
En caso de presentarse una violación al código de conducta de manera repetida se tendrá cero tolerancia a este comportamiento por parte de los organizadores.
|
||||
|
||||
Si un miembro de la comunidad participa en una conducta inaceptable, los organizadores pueden tomar cualquier acción que consideren apropiada, hasta e incluyendo una prohibición temporal o expulsión permanente de la comunidad, sin previo aviso.
|
||||
|
||||
Priorizamos la seguridad de las personas marginadas sobre la comodidad de las personas privilegiadas. Nos reservamos el derecho de no actuar sobre las quejas relacionadas con:
|
||||
|
||||
- El "racismo inverso", "sexismo inverso" y "cisfobia".
|
||||
- Comunicación razonable de límites, como "déjame en paz", "vete" o "no estoy discutiendo esto contigo".
|
||||
- Al comunicarse en un "tono", no se encuentra agradable.
|
||||
- Identificando comportamientos o suposiciones racistas, sexistas, cissexistas u opresivas.
|
||||
|
||||
## 5. ¿Qué hacer si se incumple el código de conducta?
|
||||
Si eres víctima o testigo de una conducta inaceptable, o tienes cualquier inquietud, por favor comunícate con el equipo organizador lo antes posible:
|
||||
|
||||
- Mensaje directo: Michael Prentice (@splaktar)
|
||||
- Mensaje directo: Jorge Cano (@jorgeucano)
|
||||
- Mensaje directo: Andrés Villanueva (@villanuevand)
|
||||
- Email: [soporte@angular.lat](mailto:soporte@angular.lat)
|
||||
|
||||
### ¿Qué pasa después?
|
||||
- Una vez haya sido notificada el no cumplimiento de la norma, el equipo de liderazgo se reunirán y analizarán el caso.
|
||||
- Los incidentes presentados se manejarán con discreción.
|
||||
- Los organizadores se comunicarán con la persona que incumplió la norma y tomarán las medidas respectivas.
|
||||
- Se realizará un acompañamiento a la persona agredida y se apoyará.
|
||||
- Si el incidente se hace público, Angular Hispano no se hace responsable de los perjuicios que esto pueda ocasionar en el agresor o el agredido.
|
||||
|
||||
## 6. Alcance
|
||||
Esperamos que todos los participantes de la comunidad (organizadores, voluntarios, contribuyentes pagados o de otro modo; patrocinadores; y otros invitados) se atengan a este Código de Conducta en todos los espacios virtuales y presenciales, así como en todas las comunicaciones de uno-a-uno pertinentes la comunidad.
|
||||
|
||||
### Colaboradores
|
||||
|
||||
- Alejandra Giraldo
|
||||
- Vanessa Marely
|
||||
- Mariano Alvarez
|
||||
- Andrés Villanueva
|
||||
- Michael Prentice
|
||||
- javascript&friends
|
||||
- Angular
|
||||
- She Codes Angular
|
||||
- Colombia dev
|
359
CONTRIBUTING.en.md
Normal file
359
CONTRIBUTING.en.md
Normal file
@ -0,0 +1,359 @@
|
||||
# Contributing to Angular
|
||||
|
||||
We would love for you to contribute to Angular and help make it even better than it is today!
|
||||
As a contributor, here are the guidelines we would like you to follow:
|
||||
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Feature Requests](#feature)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Rules](#rules)
|
||||
- [Commit Message Guidelines](#commit)
|
||||
- [Signing the CLA](#cla)
|
||||
|
||||
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
|
||||
Help us keep Angular open and inclusive.
|
||||
Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
||||
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
||||
|
||||
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
|
||||
- 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.
|
||||
|
||||
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||
|
||||
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
|
||||
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
||||
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
|
||||
## <a name="feature"></a> Missing a Feature?
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
||||
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
||||
This process allows 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.
|
||||
|
||||
**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
|
||||
|
||||
|
||||
### <a name="submit-issue"></a> Submitting an Issue
|
||||
|
||||
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 require that you provide a minimal reproduction.
|
||||
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
||||
|
||||
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.
|
||||
|
||||
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
||||
Often, developers 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.
|
||||
|
||||
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 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)
|
||||
|
||||
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 existing efforts.
|
||||
|
||||
2. 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 upfront helps to ensure that we're ready to accept your work.
|
||||
|
||||
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without a signed CLA.
|
||||
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
||||
|
||||
4. Fork the angular/angular repo.
|
||||
|
||||
5. Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
6. Create your patch, **including appropriate test cases**.
|
||||
|
||||
7. Follow our [Coding Rules](#rules).
|
||||
|
||||
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
||||
|
||||
9. 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.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
10. Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
11. In GitHub, send a pull request to `angular:master`.
|
||||
|
||||
If we ask for changes via code reviews then:
|
||||
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suites to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push -f
|
||||
```
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
|
||||
#### After your pull request is merged
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
```shell
|
||||
git push origin --delete my-fix-branch
|
||||
```
|
||||
|
||||
* Check out the master branch:
|
||||
|
||||
```shell
|
||||
git checkout master -f
|
||||
```
|
||||
|
||||
* Delete the local branch:
|
||||
|
||||
```shell
|
||||
git branch -D my-fix-branch
|
||||
```
|
||||
|
||||
* Update your master with the latest upstream version:
|
||||
|
||||
```shell
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
|
||||
## <a name="rules"></a> Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
* All public API methods **must be documented**.
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||
|
||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
|
||||
## <a name="commit"></a> Commit Message Format
|
||||
|
||||
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||
|
||||
We have very precise rules over how our Git commit messages must be formatted.
|
||||
This format leads to **easier to read commit history**.
|
||||
|
||||
Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||
|
||||
|
||||
```
|
||||
<header>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||
|
||||
The `body` is mandatory for all commits except for those of scope "docs".
|
||||
When the body is required it must be at least 20 characters long.
|
||||
|
||||
The `footer` is optional.
|
||||
|
||||
Any line of the commit message cannot be longer than 100 characters.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>Commit Message Header
|
||||
|
||||
```
|
||||
<type>(<scope>): <short summary>
|
||||
│ │ │
|
||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||
│ │
|
||||
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
│ elements|forms|http|language-service|localize|platform-browser|
|
||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
│
|
||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
```
|
||||
|
||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||
|
||||
|
||||
##### 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: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **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 following is the list of supported scopes:
|
||||
|
||||
* `animations`
|
||||
* `bazel`
|
||||
* `benchpress`
|
||||
* `common`
|
||||
* `compiler`
|
||||
* `compiler-cli`
|
||||
* `core`
|
||||
* `elements`
|
||||
* `forms`
|
||||
* `http`
|
||||
* `language-service`
|
||||
* `localize`
|
||||
* `platform-browser`
|
||||
* `platform-browser-dynamic`
|
||||
* `platform-server`
|
||||
* `platform-webworker`
|
||||
* `platform-webworker-dynamic`
|
||||
* `router`
|
||||
* `service-worker`
|
||||
* `upgrade`
|
||||
* `zone.js`
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
||||
|
||||
* `changelog`: used for updating the release notes in CHANGELOG.md
|
||||
|
||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||
|
||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||
|
||||
* `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`).
|
||||
|
||||
|
||||
##### Summary
|
||||
|
||||
Use the summary field to provide a succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize the first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
|
||||
#### Commit Message Body
|
||||
|
||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||
|
||||
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
||||
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
||||
|
||||
|
||||
#### Commit Message Footer
|
||||
|
||||
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||
|
||||
```
|
||||
BREAKING CHANGE: <breaking change summary>
|
||||
<BLANK LINE>
|
||||
<breaking change description + migration instructions>
|
||||
<BLANK LINE>
|
||||
<BLANK LINE>
|
||||
Fixes #<issue number>
|
||||
```
|
||||
|
||||
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||
|
||||
|
||||
### Revert commits
|
||||
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
||||
|
||||
The content of the commit message body should contain:
|
||||
|
||||
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
||||
- a clear description of the reason for reverting the commit message.
|
||||
|
||||
|
||||
## <a name="cla"></a> Signing the CLA
|
||||
|
||||
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
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
||||
|
||||
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
||||
|
||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||
* https://help.github.com/articles/about-commit-email-addresses/
|
||||
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
||||
|
||||
|
||||
|
||||
|
||||
[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#
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||
[github]: https://github.com/angular/angular
|
||||
[gitter]: https://gitter.im/angular/angular
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||
[jsfiddle]: http://jsfiddle.net
|
||||
[plunker]: http://plnkr.co/edit
|
||||
[runnable]: http://runnable.com
|
||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular
|
440
CONTRIBUTING.md
440
CONTRIBUTING.md
@ -1,280 +1,340 @@
|
||||
# Contributing to Angular
|
||||
# Contribuye a Angular
|
||||
|
||||
We would love for you to contribute to Angular and help make it even better than it is
|
||||
today! As a contributor, here are the guidelines we would like you to follow:
|
||||
¡Nos encantaría que contribuyeras a Angular y que ayudaras a hacerlo aún mejor de lo que es hoy!
|
||||
Como colaborador, estos son los lineamientos que nos gustaría que siguieras:
|
||||
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Feature Requests](#feature)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Rules](#rules)
|
||||
- [Commit Message Guidelines](#commit)
|
||||
- [Signing the CLA](#cla)
|
||||
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
|
||||
|
||||
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
|
||||
- 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.
|
||||
|
||||
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
If you find a bug in the source code, you can help us by
|
||||
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
|
||||
[submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
## <a name="feature"></a> Missing a Feature?
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
|
||||
Repository. If you would like to *implement* a new feature, please submit an issue with
|
||||
a proposal for your work first, to be sure that we can use it.
|
||||
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.
|
||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
### <a name="submit-issue"></a> Submitting an Issue
|
||||
|
||||
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. Having a minimal reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions.
|
||||
|
||||
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.
|
||||
|
||||
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 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.
|
||||
|
||||
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.
|
||||
- [Código de conducta](#coc)
|
||||
- [¿Preguntas o problemas?](#question)
|
||||
- [_Issues_ y _bugs_](#issue)
|
||||
- [Solicitud de funcionalidades](#feature)
|
||||
- [Guía para la creación de issues y PRs](#submit)
|
||||
- [Reglas del código](#rules)
|
||||
- [Convención para el mensaje de los _commits_](#commit)
|
||||
- [Firma del Acuerdo de Licencia de Colaborador (CLA)](#cla)
|
||||
|
||||
|
||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
## <a name="coc"></a> Código de conducta
|
||||
|
||||
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.
|
||||
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.
|
||||
1. Make your changes in a new git branch:
|
||||
Ayúdanos a mantener Angular abierto e inclusivo.
|
||||
Por favor lee y sigue nuestro [Código de conducta][coc].
|
||||
|
||||
|
||||
## <a name="question"></a> ¿Tienes alguna pregunta o problema?
|
||||
|
||||
No abras *issues* para preguntas de soporte general ya que queremos mantener los *issues* de GitHub para reporte de *bugs* y solicitud de funcionalidades.
|
||||
En su lugar, recomendamos utilizar [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) para hacer preguntas relacionadas con soporte. Al crear una nueva pregunta en Stack Overflow, asegúrate de agregar el etiqueta (tag) de `angular`.
|
||||
|
||||
Stack Overflow es mucho mejor para hacer preguntas ya que:
|
||||
|
||||
- Hay miles de personas dispuestas a ayudar en preguntas y respuestas de Stack Overflow
|
||||
que permanecen disponibles para el público, por lo que tu pregunta o respuesta podría ayudar a otra persona.
|
||||
- El sistema de votación de Stack Overflow asegura que las mejores respuestas sobresalgan y sean visibles.
|
||||
|
||||
Para ahorrar tu tiempo y el nuestro, cerraremos sistemáticamente todos los *issues* que sean solicitudes de soporte general y redirigiremos a las personas a Stack Overflow.
|
||||
|
||||
Si deseas chatear sobre alguna pregunta en tiempo real, puedes hacerlo a través de nuestro [canal de Gitter][gitter].
|
||||
|
||||
|
||||
## <a name="issue"></a> ¿Encontraste un Bug?
|
||||
|
||||
Si encontraste un error en el código fuente, puedes ayudarnos [creando un *issue*](#submit-issue) en nuestro [repositorio de GitHub][github].
|
||||
O incluso mejor, puedes [crear un *Pull Request*](#submit-pr) con la solución.
|
||||
|
||||
|
||||
## <a name="feature"></a> ¿Falta alguna funcionalidad?
|
||||
Puedes solicitar una nueva funcionalidad [creando un *issue*](#submit-issue) en nuestro repositorio de GitHub.
|
||||
Si deseas implementar una nueva funcionalidad, por favor considera el tamaño del cambio para determinar los pasos correctos para continuar:
|
||||
|
||||
* Para un **cambio significativo**, primero abre un *issue* y describe tu propuesta para que pueda ser discutida.
|
||||
Este proceso nos permite coordinar mejor nuestros esfuerzos, evitar trabajo duplicado y ayudarte a diseñar el cambio para que sea aceptado con éxito en el proyecto.
|
||||
|
||||
**Nota**: Agregar un nuevo tema a la documentación o reescribir significativamente un tema, también cuenta como *cambio significativo*.
|
||||
|
||||
* **Cambios pequeños** pueden ser elaborados y directamente [creados como un _pull request_](#submit-pr).
|
||||
|
||||
|
||||
## <a name="submit"></a> Guía para la creación de issues y PRs
|
||||
|
||||
|
||||
### <a name="submit-issue"></a> Creación de _issues_
|
||||
|
||||
Antes de crear un *issue*, por favor busca en el el *issue tracker*, quizá un *issue* para tu problema ya existe y la discusión puede informarte sobre soluciones alternativas disponibles.
|
||||
|
||||
Queremos solucionar todos los problemas lo antes posible, pero antes de corregir un bug necesitamos reproducirlo y confirmarlo.
|
||||
Para reproducir errores, requerimos que proporciones una reproducción mínima.
|
||||
Tener un escenario reproducible mínimo nos brinda una gran cantidad de información importante sin tener que ir y venir con preguntas adicionales.
|
||||
|
||||
Una reproducción mínima nos permite confirmar rápidamente un bug (o señalar un problema de código), así también confirmar que estamos solucionando el problema correcto.
|
||||
|
||||
Requerimos una reproducción mínima para ahorrar tiempo a los encargados del mantenimiento y en última instancia, poder corregir más bugs.
|
||||
A menudo los desarrolladores encuentran problemas de código mientras preparan una reproducción mínima.
|
||||
Entendemos que a veces puede ser difícil extraer porciones esenciales de código de un código más grande, pero realmente necesitamos aislar el problema antes de poder solucionarlo.
|
||||
|
||||
Desafortunadamente no podemos investigar/corregir errores sin una reproducción mínima, por lo que si no tenemos tu retroalimentación del bug, vamos a cerrar el *issue* ya que no tiene suficiente información para reproducirse.
|
||||
|
||||
Puedes presentar nuevos *issues* seleccionando nuestra [plantilla de _issues_](https://github.com/angular/angular/issues/new/choose) y complentando la plantilla.
|
||||
|
||||
|
||||
### <a name="submit-pr"></a> Creación de un Pull Requests (PR)
|
||||
|
||||
Antes de crear tu Pull Request (PR) considera los siguientes lineamientos:
|
||||
|
||||
1. Busca en [GitHub](https://github.com/angular/angular/pulls) PRs que estén abiertos o cerrados y que estén relacionados con el que vas a crear.
|
||||
No deseas duplicar los esfuerzos existentes.
|
||||
|
||||
2. Asegúrate de que el PR describa el problema que estás solucionando o que documente el diseño de la funcionalidad que deseas agregar.
|
||||
Discutir el diseño por adelantado ayuda a garantizar que estemos listos para aceptar tu trabajo.
|
||||
|
||||
3. Por favor firma nuestro [Acuerdo de Licencia de Colaborador (CLA)](#cla) antes de crear PRs.
|
||||
No podemos aceptar el código sin el Acuerdo de Licencia de Colaborador (CLA) firmado.
|
||||
Asegúrate de crear todas las contribuciones de Git con la dirección de correo electrónico asociada con tu firma del Acuerdo de Licencia de Colaborador (CLA).
|
||||
|
||||
4. Haz *fork* del repositorio angular/angular.
|
||||
|
||||
5. Haz tus cambios en una nueva rama de Git:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
1. Create your patch, **including appropriate test cases**.
|
||||
1. Follow our [Coding Rules](#rules).
|
||||
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.
|
||||
6. Crea tu correción, **incluyendo casos de prueba apropiados**.
|
||||
|
||||
7. Sigue nuestras [Reglas de código](#rules).
|
||||
|
||||
8. Ejecuta todo el conjunto de pruebas de Angular, tal como está descrito en la [documentación del desarrollador][dev-doc], y asegúrate de que todas las pruebas pasen.
|
||||
|
||||
9. Crea un commit de tus cambios utilizando un mensaje de commit descriptivo que siga nuestra [convención para el mensaje de los commits](#commit).
|
||||
Es necesario cumplir con estas convenciones porque las notas de las versiones se generan automáticamente a partir de estos mensajes.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
Nota: la opción de la línea de comandos de Git `-a` automaticamente hará "add" y "rm" a los archivos editados.
|
||||
|
||||
1. Push your branch to GitHub:
|
||||
10. Haz push de tu rama a GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
1. In GitHub, send a pull request to `angular:master`.
|
||||
* If we suggest changes then:
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suites to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
11. En GitHub, crea un pull request a `angular:master`.
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push -f
|
||||
```
|
||||
Si solicitamos cambios a través de revisiones de código, sigue las siguientes indicaciones:
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
* Haz los cambios requeridos.
|
||||
* Ejecuta nuevamente el conjunto de pruebas de Angular para asegurar que todas las pruebas aún están pasando.
|
||||
* Haz rebase de tu rama a la rama master y haz push con la opción `-f` a tu repositorio de Github (esto actualizará tu Pull Request):
|
||||
|
||||
#### After your pull request is merged
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push -f
|
||||
```
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository:
|
||||
¡Es todo! ¡Muchas gracias por tu contribución!
|
||||
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
#### Después del merge de tu pull request
|
||||
|
||||
Después de que se hizo merge de tu pull request, puedes eliminar de forma segura tu rama y hacer pull de los cambios del repositorio principal (upstream):
|
||||
|
||||
* Elimina la rama remota en GitHub a través de la interfaz de usuario web de GitHub o en tu línea de comandos de la siguiente manera:
|
||||
|
||||
```shell
|
||||
git push origin --delete my-fix-branch
|
||||
```
|
||||
|
||||
* Check out the master branch:
|
||||
* Muévete a la rama master:
|
||||
|
||||
```shell
|
||||
git checkout master -f
|
||||
```
|
||||
|
||||
* Delete the local branch:
|
||||
* Elimina tu rama local:
|
||||
|
||||
```shell
|
||||
git branch -D my-fix-branch
|
||||
```
|
||||
|
||||
* Update your master with the latest upstream version:
|
||||
* Actualiza tu rama master con la última versión del fork (upstream):
|
||||
|
||||
```shell
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
## <a name="rules"></a> Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
* All public API methods **must be documented**. (Details TBC).
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
|
||||
**100 characters**. An automated formatter is available, see
|
||||
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
## <a name="rules"></a> Reglas del código
|
||||
Para garantizar la coherencia en todo el código fuente, ten en cuenta estas reglas mientras trabajas:
|
||||
|
||||
## <a name="commit"></a> Commit Message Guidelines
|
||||
* Todas las funcionalidades o solución de bugs **deben ser probadas** por una o más pruebas (pruebas unitarias).
|
||||
* Todos los métodos públicos del API **deben ser documentados**.
|
||||
* Seguimos la [guía de estilo JavaScript de Google][js-style-guide], pero cada línea no debe exceder **100 caracteres**.
|
||||
|
||||
We have very precise rules over how our git commit messages can be formatted. This leads to **more
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the Angular change log**.
|
||||
Un formateador automatizado está disponible, revisar [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
|
||||
## <a name="commit"></a> Formato para el mensaje de los commits
|
||||
|
||||
*Esta especificación está inspirada y reemplaza el [Formato de mensaje de commits de AngularJS][commit-message-format].*
|
||||
|
||||
Tenemos reglas muy precisas sobre cómo deben formatearse nuestros mensajes de los commits de Git.
|
||||
Este formato permite tener **un historial de commits más facil de leer**.
|
||||
|
||||
Cada mensaje de un commit consta del **header**, el **body**, y el **footer**.
|
||||
|
||||
### Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<header>
|
||||
<LINEA VACIA>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<LINEA VACIA>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
El `header` es obligatorio y debe ajustarse al formato del [mensaje del header del commit](#commit-header).
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
to read on GitHub as well as in various git tools.
|
||||
El `body` es obligatorio para todos los commits excepto los que tenga scope "docs".
|
||||
Cuando el body es requerido debe tener al menos 20 caracteres.
|
||||
|
||||
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||
El `footer` es opcional.
|
||||
|
||||
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
|
||||
Cualquier línea del mensaje del commit no puede tener más de 100 caracteres.
|
||||
|
||||
|
||||
#### <a href="commit-header"></a>Mensaje del header del commit
|
||||
|
||||
```
|
||||
docs(changelog): update changelog to beta.5
|
||||
```
|
||||
```
|
||||
fix(release): need to depend on 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.
|
||||
<tipo>(<alcance>): <resumen>
|
||||
│ │ │
|
||||
│ │ └─⫸ Resumen corto escrito en modo imperativo, tiempo presente. Sin mayúsculas. Sin punto final.
|
||||
│ │
|
||||
│ └─⫸ Alcance del commit: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||
│ elements|forms|http|language-service|localize|platform-browser|
|
||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||
│
|
||||
└─⫸ Tipo de commit: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
```
|
||||
|
||||
### 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.
|
||||
El `<tipo>` y `<resumen>` son obligatorios, el `(<alcance>)` es opcional.
|
||||
|
||||
### 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)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
##### Tipo
|
||||
|
||||
### Scope
|
||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages.
|
||||
El tipo debe ser uno de los siguientes:
|
||||
|
||||
The following is the list of supported scopes:
|
||||
* **build**: cambios que afectan el sistema de compilación o dependencias externas (ejemplos de scopes: gulp, broccoli, npm)
|
||||
* **ci**: cambios en nuestros archivos y scripts de configuración de CI (ejemplos de scopes: Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: cambios en la documentación
|
||||
* **feat**: una nueva funcionalidad
|
||||
* **fix**: una solución de un bug
|
||||
* **perf**: un cambio de código que mejora el rendimiento.
|
||||
* **refactor**: un cambio de código que no corrige ningún error ni agrega ninguna funcionalidad
|
||||
* **style**: cambios que no afectan el significado del código (espacios en blanco, formato, falta de punto y coma, etc.)
|
||||
* **test**: se agregan pruebas faltantes o se corrigen pruebas existentes
|
||||
|
||||
* **animations**
|
||||
* **common**
|
||||
* **compiler**
|
||||
* **compiler-cli**
|
||||
* **core**
|
||||
* **elements**
|
||||
* **forms**
|
||||
* **http**
|
||||
* **language-service**
|
||||
* **platform-browser**
|
||||
* **platform-browser-dynamic**
|
||||
* **platform-server**
|
||||
* **platform-webworker**
|
||||
* **platform-webworker-dynamic**
|
||||
* **router**
|
||||
* **service-worker**
|
||||
* **upgrade**
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
##### Alcance
|
||||
El alcance debe ser el nombre del paquete npm afectado (tal como lo percibe la persona que lee el registro de cambios generado a partir de los mensajes de commit).
|
||||
|
||||
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g.
|
||||
public path changes, package.json changes done to all packages, d.ts file/format changes, changes
|
||||
to bundles, etc.
|
||||
* **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
|
||||
* 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`).
|
||||
La siguiente es la lista de alcances permitidos:
|
||||
|
||||
### Subject
|
||||
The subject contains a succinct description of the change:
|
||||
* `animations`
|
||||
* `bazel`
|
||||
* `benchpress`
|
||||
* `common`
|
||||
* `compiler`
|
||||
* `compiler-cli`
|
||||
* `core`
|
||||
* `elements`
|
||||
* `forms`
|
||||
* `http`
|
||||
* `language-service`
|
||||
* `localize`
|
||||
* `platform-browser`
|
||||
* `platform-browser-dynamic`
|
||||
* `platform-server`
|
||||
* `platform-webworker`
|
||||
* `platform-webworker-dynamic`
|
||||
* `router`
|
||||
* `service-worker`
|
||||
* `upgrade`
|
||||
* `zone.js`
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize the first letter
|
||||
* no dot (.) at the end
|
||||
Actualmente hay algunas excepciones a la regla "usar el nombre de paquete":
|
||||
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
* `packaging`: usado para cambios que cambian el diseño de los paquetes de npm en todos nuestros paquetes. Ejemplos: cambios de la ruta públic, package.json cambios hechos a todos los paquetes, cambios a archivos o formatos d.ts, cambios a bundles, etc.
|
||||
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
* `changelog`: utilizado para actualizar las notas de la versión en CHANGELOG.md
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
* `dev-infra`: utilizado para cambios relacionados con dev-infra dentro de los directorios /scripts, /tools y /dev-infra
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
* `docs-infra`: utilizado para cambios relacionados con la documentación (angular.io) dentro del directorio /aio del repositorio
|
||||
|
||||
## <a name="cla"></a> Signing the CLA
|
||||
* `migrations`: utilizado para los cambios en las migraciones `ng update`.
|
||||
|
||||
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!
|
||||
* `ngcc`: usado para los cambios del [Compilador de compatibilidad de Angular](./packages/compiler-cli/ngcc/README.md)
|
||||
|
||||
* 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].
|
||||
* `ve`: utilizado para cambios específicos de ViewEngine (legacy compiler/renderer).
|
||||
|
||||
<hr>
|
||||
* alcance vacío: útil para cambios de `style`, `test` y `refactor` que se realizan en todos los paquetes (ejemplo: `style: add missing semicolons`) y para cambios de la documentación que no están relacionados a un paquete en específico(ejemplo: `docs: corrige error gramatical en el tutorial`).
|
||||
|
||||
If you have more than one Git identity, you must make sure that you sign the CLA using the primary email address associated with the ID that has been granted access to the Angular repository. Git identities can be associated with more than one email address, and only one is primary. Here are some links to help you sort out multiple Git identities and email addresses:
|
||||
|
||||
##### Resumen
|
||||
|
||||
Usa el campo resumen para proporcionar una descripción breve del cambio:
|
||||
|
||||
* usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios"
|
||||
* no debe de contener ninguna letra mayúscula
|
||||
* no debe de conter punto (.) al final
|
||||
|
||||
|
||||
#### Mensaje del cuerpo del commit
|
||||
|
||||
Tal como en el resumen, usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios".
|
||||
|
||||
Explica la razón del cambio en el el mensaje del cuerpo del commit. Este mensaje de confirmación debe explicar _por qué_ está realizando el cambio.
|
||||
Puedes incluir una comparación del comportamiento anterior con el nuevo comportamiento para ilustrar el impacto del cambio.
|
||||
|
||||
|
||||
#### Mensaje del footer del commit
|
||||
|
||||
El footer puede contener información sobre cambios significativos y también es el lugar para hacer referencia a issues de GitHub, tickets de Jira y otros PRs que están relacionados con el commit.
|
||||
|
||||
```
|
||||
CAMBIO SIGNIFICATIVO: <resumen del cambio significativo>
|
||||
<LINEA VACIA>
|
||||
<descripción del cambio significativo + instrucciones para la migración>
|
||||
<LINEA VACIA>
|
||||
<LINEA VACIA>
|
||||
Fix #<issue número>
|
||||
```
|
||||
|
||||
La sección de cambios significativos debería comenzar con la frase "CAMBIO SIGNIFICATIVO: " seguido de un resumen del cambio significativo, una línea en blanco y una descripción detallada del cambio significativo que también incluya instrucciones de migración.
|
||||
|
||||
|
||||
### Revirtiendo commits
|
||||
|
||||
Si el commit revierte un commit previo, el commit debería comenzar con `revert: `, seguido por el header del commit revertido.
|
||||
|
||||
El contenido del mensaje del commit debería contener:
|
||||
|
||||
- Información sobre el SHA del commit que se revierte en el siguiente formato: `Esto revierte el commit <SHA>`,
|
||||
- Una descripción clara de la razón para revertir el mensaje del _commit_.
|
||||
|
||||
|
||||
## <a name="cla"></a> Firma del Acuerdo de Licencia de Colaborador (CLA)
|
||||
|
||||
Por favor firma nuestro Acuerdo de Licencia de Colaborador (CLA) cuando creas tu primer pull request. Para que cualquier cambio de código sea aceptado, el Acuerdo de Licencia de Colaborador (CLA) debe ser firmado. Es un proceso rápido con nuestro CLA assistant que está integrado con nuestro CI.
|
||||
|
||||
Los siguientes documentos pueden ayudarte a resolver problemas con cuentas de GitHub y múltiples direcciones de correo electrónico:
|
||||
|
||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||
* 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.
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
||||
|
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
|
||||
|
26
README.en.md
Normal file
26
README.en.md
Normal file
@ -0,0 +1,26 @@
|
||||
[](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.
|
||||
|
||||
## Quickstart
|
||||
|
||||
[Get started in 5 minutes][quickstart].
|
||||
|
||||
## 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).
|
||||
|
||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||
[quickstart]: https://angular.io/start
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[ng]: https://angular.io
|
34
README.md
34
README.md
@ -1,29 +1,25 @@
|
||||
[](https://travis-ci.org/angular/angular)
|
||||
[](https://circleci.com/gh/angular/angular/tree/master)
|
||||
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
||||
[](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 en español
|
||||
|
||||
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa
|
||||
TypeScript/JavaScript y otros lenguajes de programación.
|
||||
|
||||
# Angular
|
||||
## ¿Quieres ayudar?
|
||||
|
||||
Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript and other languages.
|
||||
### Documentación en español
|
||||
|
||||
## Quickstart
|
||||
¿Quieres mejorar la documentación? ¡Excelente! Lee nuestras pautas para
|
||||
[colaborar](CONTRIBUTING.md) y luego revisa algunos de nuestras
|
||||
[issues](https://github.com/angular-hispano/angular/issues).
|
||||
|
||||
[Get started in 5 minutes][quickstart].
|
||||
### El framework
|
||||
|
||||
## Changelog
|
||||
La colaboración para corregir errores y agregar funciones en el framework debe realizarse en inglés a través
|
||||
del repositorio [angular/angular](https://github.com/angular/angular) upstream.
|
||||
|
||||
[Learn about the latest improvements][changelog].
|
||||
## Guía rápida
|
||||
|
||||
## Want to help?
|
||||
[Comienza a usarlo en 5 minutos](https://docs.angular.lat/start).
|
||||
|
||||
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).
|
||||
## Registro de cambios (Changelog)
|
||||
|
||||
[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
|
||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||
[ng]: https://angular.io
|
||||
[Últimas mejoras realizadas](CHANGELOG.md).
|
||||
|
164
WORKSPACE
164
WORKSPACE
@ -1,116 +1,108 @@
|
||||
workspace(name = "angular")
|
||||
workspace(
|
||||
name = "angular",
|
||||
managed_directories = {"@npm": ["node_modules"]},
|
||||
)
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load(
|
||||
"//packages/bazel:package.bzl",
|
||||
"rules_angular_dependencies",
|
||||
"rules_angular_dev_dependencies",
|
||||
)
|
||||
|
||||
# Fetch rules_nodejs so we can install our npm dependencies
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "b7a62250a3a73277ade0ce306d22f122365b513f5402222403e507f2f997d421",
|
||||
url = "https://github.com/bazelbuild/rules_go/releases/download/0.16.3/rules_go-0.16.3.tar.gz",
|
||||
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"],
|
||||
)
|
||||
|
||||
# Uncomment for local bazel rules development
|
||||
#local_repository(
|
||||
# name = "build_bazel_rules_nodejs",
|
||||
# path = "../rules_nodejs",
|
||||
#)
|
||||
#local_repository(
|
||||
# name = "build_bazel_rules_typescript",
|
||||
# path = "../rules_typescript",
|
||||
#)
|
||||
# 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")
|
||||
|
||||
# Angular Bazel users will call this function
|
||||
rules_angular_dependencies()
|
||||
check_rules_nodejs_version(minimum_version_string = "1.7.0")
|
||||
|
||||
# Install transitive deps of rules_nodejs
|
||||
load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
|
||||
# Setup the Node.js toolchain
|
||||
node_repositories(
|
||||
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"],
|
||||
)
|
||||
|
||||
rules_nodejs_dependencies()
|
||||
load("//integration:angular_integration_test.bzl", "npm_package_archives")
|
||||
|
||||
yarn_install(
|
||||
name = "npm",
|
||||
manual_build_file_contents = npm_package_archives(),
|
||||
package_json = "//:package.json",
|
||||
yarn_lock = "//:yarn.lock",
|
||||
)
|
||||
|
||||
# Install all bazel dependencies of the @npm npm packages
|
||||
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||
|
||||
install_bazel_dependencies()
|
||||
|
||||
# Load angular dependencies
|
||||
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||
|
||||
# These are the dependencies only for us
|
||||
rules_angular_dev_dependencies()
|
||||
|
||||
# Install transitive deps of rules_typescript
|
||||
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
|
||||
# Load protractor dependencies
|
||||
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||
|
||||
rules_typescript_dependencies()
|
||||
npm_bazel_protractor_dependencies()
|
||||
|
||||
#
|
||||
# Point Bazel to WORKSPACEs that live in subdirectories
|
||||
#
|
||||
http_archive(
|
||||
name = "rxjs",
|
||||
sha256 = "72b0b4e517f43358f554c125e40e39f67688cd2738a8998b4a266981ed32f403",
|
||||
strip_prefix = "package/src",
|
||||
url = "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz",
|
||||
)
|
||||
# Load karma dependencies
|
||||
load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies")
|
||||
|
||||
# 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",
|
||||
)
|
||||
npm_bazel_karma_dependencies()
|
||||
|
||||
#
|
||||
# Load and install our dependencies downloaded above.
|
||||
#
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
|
||||
check_bazel_version("0.20.0", """
|
||||
You no longer need to install Bazel on your machine.
|
||||
Angular has a dependency on the @bazel/bazel package which supplies it.
|
||||
Try running `yarn bazel` instead.
|
||||
(If you did run that, check that you've got a fresh `yarn install`)
|
||||
|
||||
""")
|
||||
|
||||
node_repositories(
|
||||
node_version = "10.9.0",
|
||||
package_json = ["//:package.json"],
|
||||
preserve_symlinks = True,
|
||||
yarn_version = "1.12.1",
|
||||
)
|
||||
|
||||
local_repository(
|
||||
name = "npm",
|
||||
path = "tools/npm_workspace",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains()
|
||||
|
||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
||||
# 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()
|
||||
|
||||
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
|
2
aio/.gitignore
vendored
2
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
|
||||
|
174
aio/README.md
174
aio/README.md
@ -1,135 +1,131 @@
|
||||
# Angular documentation project (https://angular.io)
|
||||
# Proyecto de documentación Angular (https://docs.angular.lat)
|
||||
|
||||
Everything in this folder is part of the documentation project. This includes
|
||||
Todo en esta carpeta es parte del proyecto de documentación. Esto incluye:
|
||||
|
||||
* the web site for displaying the documentation
|
||||
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
|
||||
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
|
||||
* El sitio web para mostrar la documentación
|
||||
* La configuración de dgeni para convertir los archivos de origen a archivos renderizados que se pueden vizualizar en el sitio web.
|
||||
* Las herramientas para establecer ejemplos para el desarrollo; y generar archivos en tiempo real y archivos zip desde los ejemplos.
|
||||
|
||||
## Developer tasks
|
||||
## Tareas de desarrollador
|
||||
|
||||
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
|
||||
You should run all these tasks from the `angular/aio` folder.
|
||||
Here are the most important tasks you might need to use:
|
||||
Nosotros usamos [Yarn](https://yarnpkg.com) para gestionar las dependencias y crear tareas de compilación.
|
||||
Debes ejecutar todas estas tareas desde la carpeta `angular/aio`.
|
||||
Aquí están las tareas más importantes que podrías necesitar usar:
|
||||
|
||||
* `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` - instalar todas las dependencias.
|
||||
* `yarn setup` - instalar todas las dependencias, boilerplate, stackblitz, zips y ejecuta dgeni en los documentos.
|
||||
* `yarn setup-local` - igual que `setup`, pero crea los paquetes de Angular a partir del código y usa estas versiones construidas localmente (en lugar de las recuperadas desde npm) para aio y ejemplos de documentos 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` - crear una compilación de producción de la aplicación (después de instalar dependencias, boilerplate, etc).
|
||||
* `yarn build-local` - igual que `build`, pero usa `setup-local` en lugar de `setup`.
|
||||
* `yarn build-local-with-viewengine` - igual que `build-local`, pero además también enciende el modo `ViewEngine` (pre-Ivy) en aio.
|
||||
(Nota: Encender el modo `ViewEngine` en ejemplos de documentos, ver `yarn boilerplate:add:viewengine` abajo.)
|
||||
|
||||
* `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.
|
||||
* `yarn lint` - check that the doc-viewer code follows our style rules.
|
||||
* `yarn test` - watch all the source files, for the doc-viewer, and run all the unit tests when any change.
|
||||
* `yarn test --watch=false` - run all the unit tests once.
|
||||
* `yarn e2e` - run all the e2e tests for the doc-viewer.
|
||||
* `yarn start` - ejecutar un servidor web de desarrollo que observa los archivos; luego crea el doc-viewer y vuelve a cargar la página, según sea necesario.
|
||||
* `yarn serve-and-sync` - ejecutar ambos, el `docs-watch` y `start` en la misma consola.
|
||||
* `yarn lint` - comprobar que el código del doc-viewer sigue nuestras reglas de estilo.
|
||||
* `yarn test` - observar todos los archivos de origen, para el doc-viewer, y ejecuta todas las pruebas unitarias cuando haya algún cambio.
|
||||
* `yarn test --watch=false` -ejecutar todas las pruebas unitarias una sola vez.
|
||||
* `yarn e2e` - ejecutar todas las pruebas de e2e para el doc-viewer.
|
||||
|
||||
* `yarn docs` - generate all the docs from the source files.
|
||||
* `yarn docs-watch` - watch the Angular source and the docs files and run a short-circuited doc-gen for the docs that changed.
|
||||
* `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 docs` - generar toda la documentación desde los archivos fuente.
|
||||
* `yarn docs-watch` - observar el código Angular, los archivos de documentación y ejecutar un 'doc-gen' en corto circuito para los documentos que fueron cambiados.
|
||||
* `yarn docs-lint` - comprobar que el código del documento generado sigue nuestras reglas de estilo.
|
||||
* `yarn docs-test` - ejecutar las pruebas unitarias para el código de generación de doc.
|
||||
|
||||
* `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: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 boilerplate:add` - generar todo el código boilerplate para los ejemplos, para que puedan ejecutarse localmente.
|
||||
* `yarn boilerplate:add:viewengine` - igual que `boilerplate:add` pero también enciende el modo `ViewEngine` (pre-Ivy).
|
||||
|
||||
* `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 boilerplate:remove` - eliminar todo el código boilerplate que fue añadido a través`yarn boilerplate:add`.
|
||||
* `yarn generate-stackblitz` - generar los archivos stackblitz que están usados por la etiqueta `live-example` en documentos.
|
||||
* `yarn generate-zips` - generar los archivos zip desde los ejemplos. Zip está disponible a través de la etiqueta `live-example` en los documentos.
|
||||
|
||||
## 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.
|
||||
* `yarn example-e2e` - ejecutar todas las pruebas e2e para ejemplos. Opciones disponibles:
|
||||
- `--setup`: generar boilerplate, forzar la actualización del controlador web y otras configuraciones, luego ejecutar las pruebas.
|
||||
- `--local`: ejecutar pruebas e2e con la versión local de Angular contenida en la carpeta "dist".
|
||||
_Requiere `--setup` para que surta efecto._
|
||||
- `--viewengine`: ejecutar pruebas e2e en modo `ViewEngine` (pre-Ivy).
|
||||
- `--filter=foo`: limitar pruebas e2e a las que contienen la palabra "foo".
|
||||
|
||||
> 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!
|
||||
> **Nota para usuarios Windows**
|
||||
>
|
||||
> Configurar los ejemplos implica crear algunos [enlaces simbólicos](https://es.wikipedia.org/wiki/Enlace_simb%C3%B3lico) (ver [Aquí](./tools/examples/README.md#symlinked-node_modules) para más detalles). En Windows, esto requiere tener [Habilitado el Modo de desarrollador ](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (compatible con Windows 10 o más reciente) o ejecutar los comandos de configuración cómo administrador.
|
||||
>
|
||||
> Los comandos afectados son:
|
||||
> - `yarn setup` / `yarn setup-*`
|
||||
> - `yarn build` / `yarn build-*`
|
||||
> - `yarn boilerplate:add`
|
||||
> - `yarn example-e2e --setup`
|
||||
|
||||
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`.
|
||||
## Usando ServiceWorker localmente
|
||||
|
||||
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.
|
||||
|
||||
## Using ServiceWorker locally
|
||||
|
||||
Running `yarn start` (even when explicitly targeting production mode) does not set up the
|
||||
ServiceWorker. If you want to test the ServiceWorker locally, you can use `yarn build` and then
|
||||
serve the files in `dist/` with `yarn http-server dist -p 4200`.
|
||||
Ejecutando `yarn start` (incluso cuando se apunta explícitamente al modo de producción) no configura el
|
||||
ServiceWorker. Si quieres probar el ServiceWorker localmente, puedes usar `yarn build` y luego
|
||||
ejecutar los archivos en `dist/` con `yarn http-server dist -p 4200`.
|
||||
|
||||
|
||||
## Guide to authoring
|
||||
## Guía de autoría
|
||||
Existen dos tipos de contenido en la documentación:
|
||||
|
||||
There are two types of content in the documentation:
|
||||
* **Documentación de API**: descripciones de los módulos, clases, interfaces, decoradores, etc que son parte de la plataforma Angular.
|
||||
La documentacion de API está generada directamente desde el código fuente.
|
||||
El código fuente está contenido en archivos TypeScript , almacenados en la carpeta `angular/packages`.
|
||||
Cada elemento de la API puede tener un comentario anterior, el cual contiene etiquetas y contenido de estilos JSDoc.
|
||||
El contenido está escrito en markdown.
|
||||
|
||||
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
|
||||
API docs are generated directly from the source code.
|
||||
The source code is contained in TypeScript files, located in the `angular/packages` folder.
|
||||
Each API item may have a preceding comment, which contains JSDoc style tags and content.
|
||||
The content is written in markdown.
|
||||
* **Otro contenido**: guias, tutoriales, y otro material de marketing.
|
||||
Todos los demás contenidos se escriben utilizando markdown en archivos de texto, ubicados en la carpeta `angular/aio/content`.
|
||||
Más específicamente, hay subcarpetas que contienen tipos particulares de contenido: guías, tutoriales y marketing.
|
||||
|
||||
* **Other content**: guides, tutorials, and other marketing material.
|
||||
All other content is written using markdown in text files, located in the `angular/aio/content` folder.
|
||||
More specifically, there are sub-folders that contain particular types of content: guides, tutorial and marketing.
|
||||
* **Ejempos de código**: los ejemplos de código deben ser comprobables para garantizar su precisión.
|
||||
Además, nuestros ejemplos tienen un aspecto específico y permiten al usuario copiar el código fuente. Para mayor
|
||||
ejemplos se representan en una interfaz con pestañas (e.g. template, HTML, y TypeScript en pestañas separadas). Adicionalmente, algunos son ejemplos en acción, que proporcionan enlaces donde se puede editar el código, ejecutar, y/o descargar. Para obtener más detalles sobre cómo trabajar con ejemplos de código, lea los [fragmentos de código](https://docs.angular.lat/guide/docs-style-guide#code-snippets), [código fuente de marcado ](https://docs.angular.lat/guide/docs-style-guide#source-code-markup), y [ ejemplos en acción ](https://docs.angular.lat/guide/docs-style-guide#live-examples) paginas de los [ autores de guías de estilo ](https://docs.angular.lat/guide/docs-style-guide).
|
||||
|
||||
* **Code examples**: code examples need to be testable to ensure their accuracy.
|
||||
Also, our examples have a specific look and feel and allow the user to copy the source code. For larger
|
||||
examples they are rendered in a tabbed interface (e.g. template, HTML, and TypeScript on separate
|
||||
tabs). Additionally, some are live examples, which provide links where the code can be edited, executed, and/or downloaded. For details on working with code examples, please read the [Code snippets](https://angular.io/guide/docs-style-guide#code-snippets), [Source code markup](https://angular.io/guide/docs-style-guide#source-code-markup), and [Live examples](https://angular.io/guide/docs-style-guide#live-examples) pages of the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
||||
Usamos la herramienta [dgeni](https://github.com/angular/dgeni) para convertir estos archivos en docs que se pueden ver en el doc-viewer.
|
||||
Las [guías de estilo para Autores](https://docs.angular.lat/guide/docs-style-guide) prescriben pautas para
|
||||
escribir páginas de guía, explica cómo usar la documentación de clases y componentes, y cómo marcar el código fuente para producir fragmentos de código.
|
||||
|
||||
We use the [dgeni](https://github.com/angular/dgeni) tool to convert these files into docs that can be viewed in the doc-viewer.
|
||||
### Generando documentos completos
|
||||
|
||||
The [Authors Style Guide](https://angular.io/guide/docs-style-guide) prescribes guidelines for
|
||||
writing guide pages, explains how to use the documentation classes and components, and how to markup sample source code to produce code snippets.
|
||||
La principal tarea para generar los documentos es `yarn docs`. Esto procesará todos los archivos fuente (API y otros), extrayendo la documentación y generando archivos JSON que pueden ser consumidos por el doc-viewer.
|
||||
|
||||
### Generating the complete docs
|
||||
### Generación parcial de doc para editores
|
||||
|
||||
The main task for generating the docs is `yarn docs`. This will process all the source files (API and other),
|
||||
extracting the documentation and generating JSON files that can be consumed by the doc-viewer.
|
||||
La generación completa de documentos puede llevar hasta un minuto. Eso es demasiado lento para la creación y edición eficiente de documentos.
|
||||
|
||||
### Partial doc generation for editors
|
||||
Puedes ealizar pequeños cambios en un editor inteligente que muestre un markdown con formato:
|
||||
>En VS Code, _Cmd-K, V_ abre la vista previa de markdown en el panel lateral; _Cmd-B_ alterna la barra izquierda
|
||||
|
||||
Full doc generation can take up to one minute. That's too slow for efficient document creation and editing.
|
||||
Puedes también mirar los cambios que se muestran correctamente en el doc-viewer
|
||||
con un tiempo de ciclo rápido de edición / visualización.
|
||||
|
||||
You can make small changes in a smart editor that displays formatted markdown:
|
||||
>In VS Code, _Cmd-K, V_ opens markdown preview in side pane; _Cmd-B_ toggles left sidebar
|
||||
Para este propósito, usa la tarea `yarn docs-watch`, que observa los cambios en los archivos de origen y solo vuelve a procesar los archivos necesarios para generar los documentos relacionados con el archivo que ha cambiado.
|
||||
Dado que esta tarea tiene accesos directos, es mucho más rápido (a menudo menos de 1 segundo) pero no producirá contenido de fidelidad completa. Por ejemplo, los enlaces a otros documentoss y ejemplos de código pueden no mostrarse correctamente. Esto se nota especialmente en los enlaces a otros documentos y en los ejemplos incrustados, que no siempre se representan correctamente.
|
||||
|
||||
You also want to see those changes displayed properly in the doc viewer
|
||||
with a quick, edit/view cycle time.
|
||||
La configuración general es la siguiente:
|
||||
|
||||
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.
|
||||
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
|
||||
correctly.
|
||||
|
||||
The general setup is as follows:
|
||||
|
||||
* Open a terminal, ensure the dependencies are installed; run an initial doc generation; then start the doc-viewer:
|
||||
* Abrir una terminal, estar seguro que las dependencias están instaladas; ejecutar una generación inicial del doc; luego iniciar el doc-viewer:
|
||||
|
||||
```bash
|
||||
yarn setup
|
||||
yarn start
|
||||
```
|
||||
|
||||
* Open a second terminal and start watching the docs
|
||||
* Abrir una segunda terminal e iniciar el observador de documentos.
|
||||
|
||||
```bash
|
||||
yarn docs-watch
|
||||
```
|
||||
|
||||
>Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window
|
||||
>Alternativamente, prueba el comando fusionado `serve-and-sync` que crea, observa y ejecuta en la misma ventana de la terminal
|
||||
```bash
|
||||
yarn serve-and-sync
|
||||
```
|
||||
|
||||
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
|
||||
You can automatically open the browser by using `yarn start -o` in the first terminal.
|
||||
* Abre un navegador con la siguiente dirección https://localhost:4200/ y navega hasta el documento en el que quieras trabajar.
|
||||
Puedes automáticamente abrir el navegador utilizando `yarn start -o` en la primera terminal.
|
||||
|
||||
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
|
||||
be regenerated, the app will rebuild and the page will reload.
|
||||
* Realiza cambios en la página de documentación asociada o en los archivos de ejemplo. Cada vez que un archivo es guardado, la documentación se regenerará, la aplicación se reconstruirá y la página se volverá a cargar.
|
||||
|
||||
* If you get a build error complaining about examples or any other odd behavior, be sure to consult
|
||||
the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
||||
*Si recibes un error de compilación acerca de los ejemplos o cualquier otro error, asegúrate de consultar las
|
||||
[guías de estilo para Autores](https://angular.io/guide/docs-style-guide) para más información.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
"@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": "^3.1.0",
|
||||
"tslint": "^5.11.0",
|
||||
"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 @@
|
||||
|
||||
## 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"
|
||||
|
||||
|
107
aio/angular.json
107
aio/angular.json
@ -1,11 +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",
|
||||
"warnings": {
|
||||
"typescriptMismatch": false
|
||||
}
|
||||
},
|
||||
"analytics": false
|
||||
},
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
@ -13,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",
|
||||
@ -20,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,
|
||||
@ -31,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",
|
||||
{
|
||||
@ -50,9 +58,15 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
"src/styles/main.scss"
|
||||
],
|
||||
"scripts": []
|
||||
"scripts": [],
|
||||
"budgets": [
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"fast": {
|
||||
@ -61,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
|
||||
@ -70,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
|
||||
@ -79,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
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -104,6 +121,9 @@
|
||||
},
|
||||
"archive": {
|
||||
"browserTarget": "site:build:archive"
|
||||
},
|
||||
"ci": {
|
||||
"browserTarget": "site:build:ci"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -117,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",
|
||||
{
|
||||
@ -140,54 +156,41 @@
|
||||
"input": "node_modules/@webcomponents/custom-elements/src",
|
||||
"output": "/assets/js"
|
||||
}
|
||||
]
|
||||
],
|
||||
"styles": [
|
||||
"src/styles/main.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,13 +1,13 @@
|
||||
<h1 class="no-toc">CLI Command Reference</h1>
|
||||
# CLI Overview and Command Reference
|
||||
|
||||
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).
|
||||
The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell.
|
||||
|
||||
## Installing Angular CLI
|
||||
|
||||
Major versions of Angular CLI follow the supported major version of Angular, but minor versions can be released separately.
|
||||
|
||||
Install the CLI using the `npm` package manager:
|
||||
<code-example format="." language="bash">
|
||||
<code-example language="bash">
|
||||
npm install -g @angular/cli
|
||||
</code-example>
|
||||
|
||||
@ -20,14 +20,14 @@ 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.
|
||||
|
||||
<code-example format="." language="bash">
|
||||
<code-example language="bash">
|
||||
ng help
|
||||
ng generate --help
|
||||
</code-example>
|
||||
|
||||
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:
|
||||
|
||||
<code-example format="." language="bash">
|
||||
<code-example language="bash">
|
||||
ng new my-first-project
|
||||
cd my-first-project
|
||||
ng serve
|
||||
@ -36,6 +36,14 @@ ng serve
|
||||
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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
## Workspaces and project files
|
||||
|
||||
The [ng new](cli/new) command creates an *Angular workspace* folder and generates a new app skeleton.
|
||||
@ -74,8 +82,8 @@ Command syntax is shown as follows:
|
||||
* Option names are prefixed with a double dash (--).
|
||||
Option aliases are prefixed with a single dash (-).
|
||||
Arguments are not prefixed.
|
||||
For example:
|
||||
<code-example format="." language="bash">
|
||||
For example:
|
||||
<code-example language="bash">
|
||||
ng build my-app -c production
|
||||
</code-example>
|
||||
|
||||
|
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>
|
16
aio/content/examples/.gitignore
vendored
16
aio/content/examples/.gitignore
vendored
@ -18,11 +18,15 @@
|
||||
**/src/karma.conf.js
|
||||
**/.angular-cli.json
|
||||
**/.editorconfig
|
||||
**/.gitignore
|
||||
**/angular.json
|
||||
**/tsconfig.json
|
||||
**/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 +61,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 +83,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
|
||||
|
19
aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts
Normal file
19
aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Accessibility example e2e tests', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
browser.get('');
|
||||
});
|
||||
|
||||
it('should display Accessibility Example', () => {
|
||||
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
|
||||
});
|
||||
|
||||
it('should take a number and change progressbar width', () => {
|
||||
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');
|
||||
});
|
||||
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user