Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d83974ba4 | ||
|
|
777a1d9e0c | ||
|
|
3f70e6ab44 | ||
|
|
5d1f5bb532 | ||
|
|
8ca528b97b | ||
|
|
a101127646 | ||
|
|
c9320b05a8 | ||
|
|
06eb9e79b1 | ||
|
|
ef550da718 | ||
|
|
282bd4a26b | ||
|
|
23ad3edc0f | ||
|
|
e98829fa80 | ||
|
|
c785a06d0d | ||
|
|
5d021bf39e | ||
|
|
24cb107711 | ||
|
|
e16014b0a6 | ||
|
|
499356744d | ||
|
|
9419a78344 | ||
|
|
e16c53a5f7 | ||
|
|
974e413f72 | ||
|
|
ba9a522e67 | ||
|
|
14b2567b39 | ||
|
|
45d8004ad0 | ||
|
|
9a8f5ca76b | ||
|
|
a39aaa9677 | ||
|
|
e87779801b | ||
|
|
4db0fc4b47 | ||
|
|
ea25355308 | ||
|
|
45b7d6e62e | ||
|
|
8577262450 | ||
|
|
c1b033ae26 | ||
|
|
4899a17ea6 | ||
|
|
5ecba26daa | ||
|
|
0a9c481021 | ||
|
|
1921550a89 | ||
|
|
8793ddf009 | ||
|
|
7cad2203b6 | ||
|
|
fe243e534e | ||
|
|
a3d8535576 | ||
|
|
4e54616efc | ||
|
|
ed6c1246bc | ||
|
|
1e35546fa9 | ||
|
|
84189e159a | ||
|
|
e6fa431c2e | ||
|
|
bfa3169c67 | ||
|
|
15a5c388bf | ||
|
|
15f721b13e | ||
|
|
9998c1dac3 | ||
|
|
4fd803cf05 | ||
|
|
fb08507748 | ||
|
|
3b62532cf0 | ||
|
|
805016abd2 | ||
|
|
9cd06d9ab3 | ||
|
|
da5a607faf | ||
|
|
c658d0cec6 | ||
|
|
3331e29c49 | ||
|
|
a174422e63 | ||
|
|
0ec9b57341 | ||
|
|
39674dcc10 | ||
|
|
ef8bcd893e | ||
|
|
8cbd33e678 | ||
|
|
38f0ce81c4 | ||
|
|
36969d2b09 | ||
|
|
91ad2dcfb0 | ||
|
|
9387595834 | ||
|
|
9f4991b84c | ||
|
|
abc1fe3d46 | ||
|
|
d69e4749c5 | ||
|
|
170ef8a96d | ||
|
|
eba349c31f | ||
|
|
34aaa5c87a | ||
|
|
81a10609f8 | ||
|
|
69b9132541 | ||
|
|
dee9360285 | ||
|
|
91c8a22d27 | ||
|
|
42e05d138c | ||
|
|
01dfebe632 | ||
|
|
717666ea23 | ||
|
|
202f5c4624 | ||
|
|
3520c13545 | ||
|
|
a13db9dea9 | ||
|
|
69b676c887 | ||
|
|
98ef769cc5 | ||
|
|
fb74dd9860 | ||
|
|
4bdbdf7650 | ||
|
|
f829cf09c6 | ||
|
|
1421a5c943 | ||
|
|
ec92f88807 | ||
|
|
d67fd924f6 | ||
|
|
5ae01bf1d1 | ||
|
|
d9e15dda77 | ||
|
|
e37eb1543f | ||
|
|
eee6b2cd9b | ||
|
|
5e56c99f73 | ||
|
|
6c303bfedf | ||
|
|
a36331636c | ||
|
|
9a80568783 | ||
|
|
a8027a9642 | ||
|
|
36ccc01a3b | ||
|
|
054d9dd62c | ||
|
|
6676c15035 | ||
|
|
a08323a205 | ||
|
|
0434bb75c3 | ||
|
|
db9bbb6526 | ||
|
|
1134f188c2 | ||
|
|
ce48b1e1f2 | ||
|
|
6f37d40e27 | ||
|
|
f4e135f41a | ||
|
|
698491c213 | ||
|
|
106ab4fa62 | ||
|
|
31f766b08b | ||
|
|
bfd9435bf1 | ||
|
|
85f1fc4bdf | ||
|
|
8a467183ae | ||
|
|
7f7982dc33 | ||
|
|
13f1c32456 | ||
|
|
712fb800b4 | ||
|
|
5848ce8b31 | ||
|
|
22360f7246 | ||
|
|
6a54d4a442 | ||
|
|
4edad7ab4f | ||
|
|
b96744043a | ||
|
|
3eff625216 | ||
|
|
e8f4885aa5 | ||
|
|
fbc529dcf2 | ||
|
|
ba15176f59 | ||
|
|
80e5590847 | ||
|
|
e6142672bc | ||
|
|
642ec1c620 | ||
|
|
ad961e19a9 | ||
|
|
5a877ca98c | ||
|
|
cfbe192062 | ||
|
|
0f328b85bc | ||
|
|
67d7d57028 | ||
|
|
7700d5da80 | ||
|
|
7f306a9964 | ||
|
|
083ad913ee | ||
|
|
3c6bdc3e25 | ||
|
|
1bd0cd0533 | ||
|
|
b2ecc9f1a0 | ||
|
|
34f5d96e59 | ||
|
|
1a27722c5d | ||
|
|
2c759fde3d | ||
|
|
4db89f3790 | ||
|
|
69848dfed0 | ||
|
|
a80962e4fc | ||
|
|
0cd53ae01b | ||
|
|
5dc51dc568 | ||
|
|
69e7cdc9de | ||
|
|
5bd4f95694 | ||
|
|
766e7017c9 | ||
|
|
86ef1af4c6 | ||
|
|
a1e21e3643 | ||
|
|
d6f7f14f9b | ||
|
|
5771e92265 | ||
|
|
e9fbb2e9ab | ||
|
|
2f389a5043 | ||
|
|
603c841b7a | ||
|
|
b25c554d10 | ||
|
|
53d2831611 | ||
|
|
2e1d103bd4 | ||
|
|
bb55a023b1 | ||
|
|
10da394158 | ||
|
|
f80001d2fe | ||
|
|
7eb5afac80 | ||
|
|
323b18a79c | ||
|
|
8c6506ff68 | ||
|
|
e6cec7fb9b | ||
|
|
030707ccfe | ||
|
|
c598dcfc88 | ||
|
|
29e51fc6d9 | ||
|
|
b89771d7d0 | ||
|
|
e15137016c | ||
|
|
cb8ba1bdce | ||
|
|
5126376e6d | ||
|
|
54b1877258 | ||
|
|
1b3b1bcaf8 | ||
|
|
6671dcb907 | ||
|
|
099e01adfd | ||
|
|
7d641d91f5 | ||
|
|
08ead8b9d1 | ||
|
|
6a150256e6 | ||
|
|
5946d11f38 | ||
|
|
661697fba8 | ||
|
|
800c9f894f | ||
|
|
b9cba1e5a9 | ||
|
|
b8da02b088 | ||
|
|
a38d41a6e5 | ||
|
|
1bb471b5d5 | ||
|
|
4497f32b60 | ||
|
|
08c333fc82 | ||
|
|
c257a3f20c | ||
|
|
c988f0a54d | ||
|
|
1d07c38fb4 | ||
|
|
f6a2b64c2b | ||
|
|
412e5d5a1d | ||
|
|
8cc89f6a45 | ||
|
|
07e3620194 | ||
|
|
00cc8f0364 | ||
|
|
9a2e745008 | ||
|
|
d406d5956e | ||
|
|
95b6b5f077 | ||
|
|
752794fbbb | ||
|
|
82def836a1 | ||
|
|
29328539fe | ||
|
|
59c40734d7 | ||
|
|
042cb42552 | ||
|
|
0f466ecf38 | ||
|
|
7cca3ae109 | ||
|
|
c0eba739fc | ||
|
|
6be623963a | ||
|
|
0aeb5a6c4c | ||
|
|
057ce672b8 | ||
|
|
199512067e | ||
|
|
0991dad745 | ||
|
|
5ea764e165 | ||
|
|
8f8d5e19d7 | ||
|
|
b4c511173f | ||
|
|
6057935361 | ||
|
|
4872507e33 | ||
|
|
d360dc3932 | ||
|
|
d40d837a82 | ||
|
|
d54117736d | ||
|
|
a30f14fdfd | ||
|
|
fc09f7e034 | ||
|
|
158733ebb9 | ||
|
|
b9bb97b841 | ||
|
|
be533ced37 | ||
|
|
ff4659bb01 | ||
|
|
8c2e63ad6f | ||
|
|
21252ad4ff | ||
|
|
ee7ade5eb3 | ||
|
|
7941efa617 | ||
|
|
5b29d45ec5 | ||
|
|
78c2021396 | ||
|
|
1fbea2e6ea | ||
|
|
a3b0b5471e | ||
|
|
c80f9236e3 | ||
|
|
8b5cbcba79 | ||
|
|
927ff10074 | ||
|
|
59d3596c50 | ||
|
|
59cd091d19 | ||
|
|
ff9f722b34 | ||
|
|
7dc7e2edf7 | ||
|
|
01be9e51d2 | ||
|
|
e2d19b9173 | ||
|
|
f06c8767c8 | ||
|
|
aa89e7b15f | ||
|
|
c5c4498b29 | ||
|
|
618b972bb7 | ||
|
|
c77f953faa | ||
|
|
5f94f59f20 | ||
|
|
f345d07a13 | ||
|
|
9fc087b8b7 | ||
|
|
74db9f115f | ||
|
|
376b1edd78 | ||
|
|
05d72c9203 | ||
|
|
15f3ffd14c | ||
|
|
8e3997a686 | ||
|
|
8e9862e64d | ||
|
|
abe7cc1a8c | ||
|
|
d96c63d11f | ||
|
|
6ae72a2f26 | ||
|
|
0f59a7d507 | ||
|
|
2b40b752e5 | ||
|
|
c0b2a785be | ||
|
|
64bb6f6631 | ||
|
|
de67f6d7bd | ||
|
|
0148f683df | ||
|
|
ec4b53e129 | ||
|
|
b6c4999ff3 | ||
|
|
d08624b570 | ||
|
|
1035be332c | ||
|
|
a2d9a677ed | ||
|
|
ed45e1fee6 | ||
|
|
36dad89f50 | ||
|
|
e8878bbea5 | ||
|
|
764e9d7dfa | ||
|
|
08f25bf4b7 | ||
|
|
32df3366ef | ||
|
|
239ca8d6aa | ||
|
|
9770bf226b | ||
|
|
e76035712a | ||
|
|
bc83a8bcbd | ||
|
|
3e4070a7bf | ||
|
|
4aba98cdc5 | ||
|
|
d9877ad2fe | ||
|
|
1e7099fc01 | ||
|
|
9c3fb62e02 | ||
|
|
4355763d8f | ||
|
|
bd26ce04e6 | ||
|
|
919a50362d | ||
|
|
2aa16e65cf | ||
|
|
a115421f71 | ||
|
|
85bfaf2a63 | ||
|
|
4866271348 | ||
|
|
4be525d899 | ||
|
|
e8bf2e79a4 | ||
|
|
06e3ff8eec | ||
|
|
a5b2495071 | ||
|
|
5c43583cd4 | ||
|
|
18457f1bc4 | ||
|
|
dd9d81a87e | ||
|
|
90a8813c5a | ||
|
|
6419deeb63 | ||
|
|
951db810b9 | ||
|
|
39d35a3c6f | ||
|
|
21b20405c5 | ||
|
|
7b7d671d21 | ||
|
|
2bb5a201dd | ||
|
|
c9ab3a5495 | ||
|
|
558b17af7f | ||
|
|
1bb37f7ff8 | ||
|
|
18459fddc0 | ||
|
|
508e5bf64c | ||
|
|
67c646e454 | ||
|
|
ed48513606 | ||
|
|
9958264445 | ||
|
|
fdd1026068 | ||
|
|
74cd55a889 | ||
|
|
221fa8c886 | ||
|
|
35f99634f4 | ||
|
|
98869c8487 | ||
|
|
f9d6747b20 | ||
|
|
3972ac2321 | ||
|
|
669f61020e | ||
|
|
1221da2e05 | ||
|
|
7a4d93de71 | ||
|
|
194e0ee944 | ||
|
|
8dfa4ba837 | ||
|
|
5e99c888a9 | ||
|
|
197e932088 | ||
|
|
121a38315f | ||
|
|
50db0dc478 | ||
|
|
575e24aff5 | ||
|
|
28dcb82bc0 | ||
|
|
1a645f10a6 | ||
|
|
5c8631f304 | ||
|
|
8f5206680f | ||
|
|
129938001c | ||
|
|
a18c2a80ce | ||
|
|
ad40323cb7 | ||
|
|
a7eb5905fe | ||
|
|
2ab1000b5a | ||
|
|
4911e876f9 | ||
|
|
b3cd7f559c | ||
|
|
5f09c02687 | ||
|
|
20fbba7722 | ||
|
|
0cc2fdecb7 | ||
|
|
8a8808d703 | ||
|
|
d21da87902 | ||
|
|
140c80e32b | ||
|
|
ab54778134 | ||
|
|
79c80b9e60 | ||
|
|
7ff49c9635 | ||
|
|
8dbbe9825e | ||
|
|
3d648f35db | ||
|
|
b65df02c72 | ||
|
|
be06468ff9 | ||
|
|
234bc47bf2 | ||
|
|
aa8985de74 | ||
|
|
075882d1d9 | ||
|
|
267523dbc3 | ||
|
|
536148f8bc | ||
|
|
a8d795eb71 | ||
|
|
d2517b0344 | ||
|
|
f212ebe0a9 | ||
|
|
c1ab97f253 | ||
|
|
724d5e1c84 | ||
|
|
c2445e386d | ||
|
|
0e8c62e484 | ||
|
|
2e4d0c65d5 | ||
|
|
d8c1b5d05d | ||
|
|
ffc05bae7e | ||
|
|
95a0d9ddb1 | ||
|
|
d362cd4788 | ||
|
|
b0b78ddc41 | ||
|
|
dc5f181b93 | ||
|
|
bf4f628df3 | ||
|
|
47ef5ceae7 | ||
|
|
6157c01213 | ||
|
|
9b09d96158 | ||
|
|
f32c5479ce | ||
|
|
e0266d2a49 | ||
|
|
c87d539f8d | ||
|
|
1243795ae5 | ||
|
|
a0b5b1dd3c | ||
|
|
e39f1b11b1 | ||
|
|
527b0f1b60 | ||
|
|
c0b4d29143 | ||
|
|
f9055747c7 | ||
|
|
c8560aa15e | ||
|
|
f9b4949b14 | ||
|
|
33c1b94aed | ||
|
|
9bc988034c | ||
|
|
d0c8af0089 | ||
|
|
0f111e426e | ||
|
|
935769e768 | ||
|
|
46cfc080b7 | ||
|
|
3e2a9d58cc | ||
|
|
9f5a9d31af | ||
|
|
cf8f54fe13 | ||
|
|
21c84cda35 | ||
|
|
018e9cd911 | ||
|
|
1714bf76ea | ||
|
|
1f1d484eee | ||
|
|
0737ddf80a | ||
|
|
5b96b360c8 | ||
|
|
a5eea26642 | ||
|
|
eb2f482023 | ||
|
|
04e419ba08 | ||
|
|
54a7de8ab2 | ||
|
|
754c73c98a | ||
|
|
c72a1c09b7 | ||
|
|
254cfc9791 | ||
|
|
db24824250 | ||
|
|
8c5a9f32be | ||
|
|
42dc6f2d6f | ||
|
|
09a94343ce | ||
|
|
cd481922d9 | ||
|
|
77767dfbea | ||
|
|
f388383190 | ||
|
|
b21f6fb183 | ||
|
|
6c01c31447 | ||
|
|
52bc1deecd | ||
|
|
25ea162565 | ||
|
|
6047052fdb | ||
|
|
e5157e5c37 | ||
|
|
e034d05c91 | ||
|
|
f2bbe3000c | ||
|
|
41fe7aec08 | ||
|
|
60fa8d198e | ||
|
|
f3c0090422 | ||
|
|
66084276d4 | ||
|
|
3b123ff799 | ||
|
|
1c76b5e47c | ||
|
|
57e5da1e63 | ||
|
|
7f1f6d3343 | ||
|
|
6ed9574a18 | ||
|
|
7c3740c8f4 | ||
|
|
3e81ba1f1a | ||
|
|
e85a120672 | ||
|
|
b91443b595 | ||
|
|
df2badbe89 | ||
|
|
da9cdd8fd6 | ||
|
|
8226fea5b2 | ||
|
|
fbb57da420 | ||
|
|
75338609e2 | ||
|
|
8f53f8b592 | ||
|
|
aa227aa5ba | ||
|
|
19bdc90e38 | ||
|
|
69d529bbe8 | ||
|
|
070f1c3824 | ||
|
|
849e6b3038 | ||
|
|
a0f859e68d | ||
|
|
2327b8e1f4 | ||
|
|
a0560c9411 | ||
|
|
7377a01af9 | ||
|
|
7eaebb8f6d | ||
|
|
68c92aa2b0 | ||
|
|
43a4e04bf9 | ||
|
|
8e73fd6fb6 | ||
|
|
79b3115e0b | ||
|
|
f05628fb23 | ||
|
|
86c8db25f7 | ||
|
|
99a03ca026 | ||
|
|
290297af00 | ||
|
|
bdcf7098a1 | ||
|
|
de512627ce | ||
|
|
af76c459dc | ||
|
|
2fb8b3527c | ||
|
|
fe13a96567 | ||
|
|
db610914ef | ||
|
|
410d318db2 | ||
|
|
fa25586d32 | ||
|
|
4ba63ec643 | ||
|
|
56dcbe713c | ||
|
|
f2f32ddf35 | ||
|
|
600a20bc1e | ||
|
|
5f61fad5ab | ||
|
|
a67cb0ef2a | ||
|
|
9cf60319c2 | ||
|
|
19505421c6 | ||
|
|
9700a3467f | ||
|
|
314a969aff | ||
|
|
533326fef0 | ||
|
|
3738275280 | ||
|
|
d5e0d4e769 | ||
|
|
818c61d1ef | ||
|
|
1038f37f7f | ||
|
|
70c7083823 | ||
|
|
1b34ed829f | ||
|
|
efc833c58a | ||
|
|
81ed5f7031 | ||
|
|
c6babe939b | ||
|
|
0e3fc6c5cf | ||
|
|
f09bf82384 | ||
|
|
270a90fca3 | ||
|
|
0bdc88694d | ||
|
|
dce7c53e4f | ||
|
|
c2b3d0e311 | ||
|
|
7f97bac978 | ||
|
|
a096054b3c | ||
|
|
3cef56bf0e | ||
|
|
7cf60ccadd | ||
|
|
763510638e | ||
|
|
727efb8aa5 | ||
|
|
8a18dcd9ae | ||
|
|
3a672f5925 | ||
|
|
8ece7b73c1 | ||
|
|
e8f29c5c3b | ||
|
|
540a86c813 | ||
|
|
0117fc9eb0 | ||
|
|
07647ad576 | ||
|
|
2ce7e068a4 | ||
|
|
412227426e | ||
|
|
e09fdb19a4 | ||
|
|
1bce47d3df | ||
|
|
5276eea100 | ||
|
|
88ca2d1d2a | ||
|
|
a03905dcb5 | ||
|
|
c2f4c6d718 | ||
|
|
c77ab3a0dd | ||
|
|
cc3225d2d1 | ||
|
|
1b57c12efe | ||
|
|
6b0009d660 | ||
|
|
2403d9121b | ||
|
|
e1e6413e4d | ||
|
|
8e5b0150f3 | ||
|
|
984bf2a0f7 | ||
|
|
18ac03b505 | ||
|
|
17f789968d | ||
|
|
c994d56efc | ||
|
|
57fb484e03 | ||
|
|
6fb3f14122 | ||
|
|
ff066a1ed5 | ||
|
|
1a21d39d36 | ||
|
|
9a26635bab | ||
|
|
f42a257b7e | ||
|
|
07c2b855d9 | ||
|
|
5640d1aade | ||
|
|
e667b6c082 | ||
|
|
a42b2a7343 | ||
|
|
1e2e37cfc1 | ||
|
|
295f9c82d2 | ||
|
|
d901ee1224 | ||
|
|
9403c5cc71 | ||
|
|
480bebd8f0 | ||
|
|
bd39c2829c | ||
|
|
c7b448a5e8 | ||
|
|
58ffb8c048 | ||
|
|
a2b6e1d728 | ||
|
|
989467ebe0 | ||
|
|
c59a5d2088 | ||
|
|
8de3f6cd92 | ||
|
|
29b402ba07 | ||
|
|
32e6d24741 | ||
|
|
2b9a42adb6 | ||
|
|
facaee251c | ||
|
|
9e7e0e450d | ||
|
|
1d69ceba86 | ||
|
|
0f1cbe73df | ||
|
|
a07116b071 | ||
|
|
8136c7370b | ||
|
|
b2edeb4ce2 | ||
|
|
f207346567 | ||
|
|
f360f34c25 | ||
|
|
1af98a1b94 | ||
|
|
fede6df5b9 | ||
|
|
dc96d7f9cf | ||
|
|
174c54a00c | ||
|
|
0c9dfc5404 | ||
|
|
cafe648d78 | ||
|
|
8c36ca3943 | ||
|
|
aeb968a00e | ||
|
|
e5a3ff56e3 | ||
|
|
14b2fd0fbb | ||
|
|
c674ed0693 | ||
|
|
15c71cddb5 | ||
|
|
4a32aaa0e6 | ||
|
|
90ff6f2bcf | ||
|
|
d1111419fc | ||
|
|
221796c4d3 | ||
|
|
7f9b8fdd02 | ||
|
|
b260a89462 | ||
|
|
743dfecf83 | ||
|
|
d8fd3384a7 | ||
|
|
b95f47243f | ||
|
|
a6bdf3ccc2 | ||
|
|
d9a504621a | ||
|
|
fb6b47f283 | ||
|
|
5843a9036f | ||
|
|
c0c12a4027 | ||
|
|
3171a28f79 | ||
|
|
42bd7a6c82 | ||
|
|
b2848e3a7e | ||
|
|
dee99fd5f6 | ||
|
|
fffdec4e5a | ||
|
|
ef7883fb46 | ||
|
|
43360de49e | ||
|
|
40b5a6cd63 | ||
|
|
17acccf3c8 | ||
|
|
c804549138 | ||
|
|
e94944e32c | ||
|
|
983ec522ac | ||
|
|
8162576082 | ||
|
|
16c06b531e | ||
|
|
1cb9fae778 | ||
|
|
8d5900e552 | ||
|
|
2aa680316d | ||
|
|
2478434376 | ||
|
|
70db4b9094 | ||
|
|
65de31faa2 | ||
|
|
05abadf6e3 | ||
|
|
a972bd07dd | ||
|
|
5c8b8f4a95 | ||
|
|
b7893f42c6 | ||
|
|
89c3be7fdb | ||
|
|
75a6dea48d | ||
|
|
8efa2e2e26 | ||
|
|
c9e2dd3080 | ||
|
|
7a3d6b2ed7 | ||
|
|
2b94bc1e05 | ||
|
|
eb04464a35 | ||
|
|
64e9c5a5a6 | ||
|
|
909e7ba5fe | ||
|
|
453391a521 | ||
|
|
e04b6382bd | ||
|
|
e475d671ca | ||
|
|
ba8df39497 | ||
|
|
06e8b83431 | ||
|
|
07e65f6ee7 | ||
|
|
afcaadcec4 | ||
|
|
7c241a0f9d | ||
|
|
45d760bb8c | ||
|
|
8f4d0ab308 | ||
|
|
5f480caae7 | ||
|
|
5fb0d00f51 | ||
|
|
a6af312ec2 | ||
|
|
96a3eb8e90 | ||
|
|
bec13e0895 | ||
|
|
46edd3ffc6 | ||
|
|
037e29de6b | ||
|
|
6859336b71 | ||
|
|
67904a3be3 | ||
|
|
95e3c1f4a8 | ||
|
|
169cdbd6aa | ||
|
|
b7d2af4a43 | ||
|
|
0a978fc2e9 | ||
|
|
554f32c33b | ||
|
|
39e6914ccd | ||
|
|
3ac93f3796 | ||
|
|
0e3b7c33b0 | ||
|
|
c04f85da55 | ||
|
|
df3cb64265 | ||
|
|
026e6777a1 | ||
|
|
6b0ba23097 | ||
|
|
c070efc3e3 | ||
|
|
770eb3ac60 | ||
|
|
2c756221e6 | ||
|
|
4e42407af3 | ||
|
|
6c4c0f6195 | ||
|
|
0c035c5821 | ||
|
|
12c8d445bc | ||
|
|
54ff4d26f8 | ||
|
|
84f56db1c5 | ||
|
|
9d41b8d61f | ||
|
|
f24a56bea9 | ||
|
|
2bb370a1aa | ||
|
|
a0cbee1457 | ||
|
|
8d1f15eed9 | ||
|
|
db848556e2 | ||
|
|
7d1a326873 | ||
|
|
6efcbdc0d8 | ||
|
|
2f252b8b39 | ||
|
|
fd5adb97be | ||
|
|
bae2c4f72e | ||
|
|
cf2d163098 | ||
|
|
ffa90938d7 | ||
|
|
10ac81350c | ||
|
|
155ed253c6 | ||
|
|
05255d06ea | ||
|
|
e59667b74e | ||
|
|
9e5253da27 | ||
|
|
013672ad27 | ||
|
|
502ad0c46f | ||
|
|
094f9afc7b | ||
|
|
368c0ee148 | ||
|
|
dc79213dfe | ||
|
|
d26ea9adb2 | ||
|
|
a9868cf5c4 | ||
|
|
546eaf7604 | ||
|
|
513a4606cc | ||
|
|
4aabb3574d | ||
|
|
746a8657c3 | ||
|
|
db269af1eb | ||
|
|
d1ee9df661 | ||
|
|
1dbfe2b407 | ||
|
|
eeb73544d2 | ||
|
|
a668a219be | ||
|
|
e7794e4a25 | ||
|
|
91c8b5c2ff | ||
|
|
aa201de7c2 | ||
|
|
2e35fde43d | ||
|
|
848ba3392e | ||
|
|
147e538ba7 | ||
|
|
9932e9cdcd | ||
|
|
17b3df1e7c | ||
|
|
6eeaa0a334 | ||
|
|
55088e08e6 | ||
|
|
afb2860597 | ||
|
|
355c591e59 | ||
|
|
b343bad250 | ||
|
|
67d24c7115 | ||
|
|
d324009381 | ||
|
|
c582b34cbc |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git push:*)",
|
||||
"Bash(pnpm registry:build:*)",
|
||||
"Bash(pnpm build:*)",
|
||||
"Bash(pnpm add:*)",
|
||||
"Bash(pnpm dev)",
|
||||
"Bash(jq:*)",
|
||||
"Bash(curl:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
node_modules/
|
||||
target/
|
||||
.next/
|
||||
build/
|
||||
dist/
|
||||
|
||||
/templates/
|
||||
/fixtures/
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/eslintrc",
|
||||
"root": true,
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"turbo",
|
||||
"prettier",
|
||||
"plugin:tailwindcss/recommended"
|
||||
],
|
||||
"plugins": ["tailwindcss"],
|
||||
"ignorePatterns": ["**/fixtures/**"],
|
||||
"rules": {
|
||||
"@next/next/no-html-link-for-pages": "off",
|
||||
"tailwindcss/no-custom-classname": "off",
|
||||
"tailwindcss/classnames-order": "error"
|
||||
},
|
||||
"settings": {
|
||||
"tailwindcss": {
|
||||
"callees": ["cn", "cva"],
|
||||
"config": "tailwind.config.cjs"
|
||||
},
|
||||
"next": {
|
||||
"rootDir": ["apps/*/"]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"parser": "@typescript-eslint/parser"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
title: "[blocks]: "
|
||||
labels: ["Blocks Request"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Thanks for taking the time to create a block request! Please search open/closed requests before submitting, as the block or a similar one may have already been requested.
|
||||
|
||||
- type: textarea
|
||||
id: block-description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Tell us about your block request
|
||||
placeholder: "A dashboard for an e-commerce website showing sales, orders, and customers..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: block-example-url
|
||||
attributes:
|
||||
label: Example
|
||||
description: Link to an example of the block
|
||||
placeholder: ex. https://example.com
|
||||
validations:
|
||||
required: false
|
||||
@@ -1,3 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [shadcn]
|
||||
@@ -1,85 +0,0 @@
|
||||
name: "Bug report"
|
||||
description: Report an issue
|
||||
title: '[bug]: '
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Thanks for taking the time to create a bug report. Please search open/closed issues before submitting, as the issue may have already been reported/addressed.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
#### If you aren't sure this is a bug or not, please open a discussion instead:
|
||||
- [Discussions](https://github.com/shadcn-ui/ui/discussions/new?category=general)
|
||||
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us how in the description. Thanks!
|
||||
placeholder: Bug description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: components-affected
|
||||
attributes:
|
||||
label: Affected component/components
|
||||
description: Which shadcn/ui components are affected?
|
||||
placeholder: ex. Button, Checkbox...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: How to reproduce
|
||||
description: A step-by-step description of how to reproduce the bug.
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: codesandbox-stackblitz
|
||||
attributes:
|
||||
label: Codesandbox/StackBlitz link
|
||||
description: |
|
||||
A link to a CodeSandbox or StackBlitz that includes a minimal reproduction of the problem. In rare cases when not applicable, you can link to a GitHub repository that we can easily run to recreate the issue. If a report is vague and does not have a reproduction, it will be closed without warning.
|
||||
|
||||
> [!CAUTION]
|
||||
> If you skip this step, this issue might be **labeled** with `please add a reproduction` and **closed**.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: "Please include browser console and server logs around the time this bug occurred. Optional if provided reproduction. Please try not to insert an image but copy paste the log text."
|
||||
render: bash
|
||||
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: System Info
|
||||
description: Information about browsers, system or binaries that's relevant.
|
||||
render: bash
|
||||
placeholder: System, Binaries, Browsers
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Before submitting
|
||||
description: By submitting this issue, you agree to follow our [Contributing Guidelines](https://github.com/shadcn-ui/ui/blob/main/CONTRIBUTING.md).
|
||||
options:
|
||||
- label: I've made research efforts and searched the documentation
|
||||
required: true
|
||||
- label: I've searched for existing issues
|
||||
required: true
|
||||
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Get Help
|
||||
url: https://github.com/shadcn-ui/ui/discussions/new?category=general
|
||||
about: If you can't get something to work the way you expect, open a question in our discussion forums.
|
||||
@@ -1,55 +0,0 @@
|
||||
name: "Feature request"
|
||||
description: Create a feature request for shadcn/ui
|
||||
title: '[feat]: '
|
||||
labels: ['area: request']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Thanks for taking the time to create a feature request! Please search open/closed issues before submitting, as the issue may have already been reported/addressed.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
#### If you aren't sure this is a bug or not, please open a discussion instead:
|
||||
- [Discussions](https://github.com/shadcn-ui/ui/discussions/new?category=general)
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: Tell us about your feature request
|
||||
placeholder: 'I think this feature would be great because...'
|
||||
value: 'Describe your feature request...'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: components-affected
|
||||
attributes:
|
||||
label: Affected component/components
|
||||
description: Is this feature request relevant to any of the already existing components?
|
||||
placeholder: ex. Button, Checkbox...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the feature here.
|
||||
placeholder: ex. screenshots, Stack Overflow links, forum links, etc.
|
||||
value: 'Additional details here...'
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Before submitting
|
||||
description: By submitting this issue, you agree to follow our [Contributing Guidelines](https://github.com/shadcn-ui/ui/blob/main/CONTRIBUTING.md).
|
||||
options:
|
||||
- label: I've made research efforts and searched the documentation
|
||||
required: true
|
||||
- label: I've searched for existing issues and PRs
|
||||
required: true
|
||||
@@ -0,0 +1,12 @@
|
||||
// ORIGINALLY FROM CLOUDFLARE WRANGLER:
|
||||
// https://github.com/cloudflare/wrangler2/blob/main/.github/changeset-version.js
|
||||
|
||||
import { exec } from "child_process"
|
||||
|
||||
// This script is used by the `release.yml` workflow to update the version of the packages being released.
|
||||
// The standard step is only to run `changeset version` but this does not update the package-lock.json file.
|
||||
// So we also run `npm install`, which does this update.
|
||||
// This is a workaround until this is handled automatically by `changeset version`.
|
||||
// See https://github.com/changesets/changesets/issues/421.
|
||||
exec("npx changeset version")
|
||||
exec("npm install")
|
||||
@@ -1,46 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/astro-app"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/astro-monorepo"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/next-app"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/next-monorepo"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/react-router-app"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/react-router-monorepo"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/start-app"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/start-monorepo"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/vite-app"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/templates/vite-monorepo"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -1,9 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="640" viewBox="0 0 1280 640" role="img" aria-label="ui">
|
||||
<rect width="1280" height="640" fill="#0A0A0A"/>
|
||||
<svg x="96" y="215" width="210" height="210" viewBox="0 0 67 67"><path d="M22.21 67V44.6369H0V67H22.21Z" fill="#fff"/><path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z" fill="#fff"/><path d="M22.21 0H0V22.3184H22.21V0Z" fill="#fff"/><path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" fill="#fff"/><path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" fill="#fff"/></svg>
|
||||
<text x="378" y="276" font-family="Inter,system-ui,-apple-system,sans-serif" font-size="78" font-weight="800" letter-spacing="-2" fill="#ffffff">ui</text>
|
||||
<text x="378" y="322" font-family="Inter,system-ui,sans-serif" font-size="30" fill="#ffffff" opacity=".66">React component library for AI applications</text>
|
||||
<rect x="378" y="338" width="806" height="3" rx="1.5" fill="#ffffff" opacity=".9"/>
|
||||
<text x="378" y="390" font-family="Inter,system-ui,sans-serif" font-size="24" font-weight="600" fill="#ffffff" opacity=".5">github.com/hanzoai</text>
|
||||
<text x="1184" y="390" text-anchor="end" font-family="Inter,system-ui,sans-serif" font-size="24" font-weight="600" fill="#ffffff" opacity=".5">hanzo.ai</text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -4,7 +4,7 @@
|
||||
import { exec } from "child_process"
|
||||
import fs from "fs"
|
||||
|
||||
const pkgJsonPath = "pkgs/shadcn/package.json"
|
||||
const pkgJsonPath = "pkg/cli/package.json"
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath))
|
||||
exec("git rev-parse --short HEAD", (err, stdout) => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { exec } from "child_process"
|
||||
import fs from "fs"
|
||||
|
||||
const pkgJsonPath = "pkgs/shadcn/package.json"
|
||||
const pkgJsonPath = "pkg/cli/package.json"
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath))
|
||||
exec("git rev-parse --short HEAD", (err, stdout) => {
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run linting
|
||||
run: pnpm run lint
|
||||
|
||||
typecheck:
|
||||
name: Type Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run type checking
|
||||
run: |
|
||||
cd app && pnpm run typecheck
|
||||
cd ../pkg/ui && pnpm run tc --noEmit
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build UI package
|
||||
run: cd pkg/ui && pnpm run build:full
|
||||
|
||||
- name: Build app
|
||||
run: cd app && pnpm run build
|
||||
env:
|
||||
NEXT_PUBLIC_APP_URL: https://ui.hanzo.ai
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: |
|
||||
app/.next
|
||||
pkg/ui/dist
|
||||
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run pkg/ui tests
|
||||
run: cd pkg/ui && pnpm test -- --run
|
||||
|
||||
- name: Run app tests
|
||||
run: |
|
||||
if [ -f "app/package.json" ] && grep -q '"test"' app/package.json 2>/dev/null; then
|
||||
cd app && pnpm test || echo "No tests configured"
|
||||
else
|
||||
echo "No test script found"
|
||||
fi
|
||||
|
||||
- name: Upload coverage
|
||||
if: always()
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./pkg/ui/coverage/lcov.info
|
||||
flags: unit
|
||||
|
||||
deploy-preview:
|
||||
name: Deploy Preview
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, typecheck, build]
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Install Vercel CLI
|
||||
run: npm install --global vercel@latest
|
||||
|
||||
- name: Pull Vercel Environment Information
|
||||
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
|
||||
env:
|
||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
|
||||
- name: Build Project Artifacts
|
||||
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
|
||||
|
||||
- name: Deploy Project Artifacts to Vercel
|
||||
id: deploy
|
||||
run: |
|
||||
url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
|
||||
echo "preview_url=$url" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Comment PR with preview URL
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '🚀 Preview deployed to: ${{ steps.deploy.outputs.preview_url }}'
|
||||
})
|
||||
|
||||
status:
|
||||
name: CI Status
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint, typecheck, build, test]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check status
|
||||
run: |
|
||||
if [ "${{ needs.lint.result }}" != "success" ] || \
|
||||
[ "${{ needs.typecheck.result }}" != "success" ] || \
|
||||
[ "${{ needs.build.result }}" != "success" ] || \
|
||||
[ "${{ needs.test.result }}" != "success" ]; then
|
||||
echo "CI checks failed"
|
||||
exit 1
|
||||
else
|
||||
echo "All CI checks passed!"
|
||||
fi
|
||||
@@ -1,9 +0,0 @@
|
||||
name: CI/CD
|
||||
on:
|
||||
push: { branches: [main], tags: ["v*"] }
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
cicd:
|
||||
uses: hanzoai/ci/.github/workflows/build.yml@v1
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,116 @@
|
||||
name: Code check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["*"]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: pnpm lint
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
#- run: pnpm lint
|
||||
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
name: pnpm format:check
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- run: pnpm format:check
|
||||
|
||||
tsc:
|
||||
runs-on: ubuntu-latest
|
||||
name: pnpm typecheck
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8.6.1
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- run: pnpm typecheck
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Test Coverage
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
name: Test Coverage
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: cd pkg/ui && pnpm test:coverage
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./pkg/ui/coverage/lcov.info
|
||||
flags: unit
|
||||
name: hanzo-ui-coverage
|
||||
|
||||
- name: Comment PR with coverage
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const coverage = JSON.parse(fs.readFileSync('./pkg/ui/coverage/coverage-summary.json', 'utf8'));
|
||||
const total = coverage.total;
|
||||
const comment = `## Test Coverage Report\n\n` +
|
||||
`Lines: ${total.lines.pct}%\n` +
|
||||
`Statements: ${total.statements.pct}%\n` +
|
||||
`Functions: ${total.functions.pct}%\n` +
|
||||
`Branches: ${total.branches.pct}%`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build documentation
|
||||
working-directory: ./app
|
||||
run: |
|
||||
pnpm build
|
||||
touch out/.nojekyll
|
||||
env:
|
||||
NODE_ENV: production
|
||||
GITHUB_ACTIONS: true
|
||||
NEXT_PUBLIC_APP_URL: https://ui.hanzo.ai
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: ./app/out
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
@@ -0,0 +1,96 @@
|
||||
name: NPM Publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
package:
|
||||
description: 'Package to publish'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- ui
|
||||
- ui-mcp
|
||||
- auth
|
||||
- commerce
|
||||
- all
|
||||
version_bump:
|
||||
description: 'Version bump type'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'pnpm'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build packages
|
||||
run: |
|
||||
if [ "${{ github.event.inputs.package }}" = "all" ] || [ "${{ github.event.inputs.package }}" = "ui" ]; then
|
||||
cd pkg/ui && npm run build || true
|
||||
fi
|
||||
|
||||
- name: Bump version and publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
|
||||
run: |
|
||||
npm config set //registry.npmjs.org/:_authToken $NODE_AUTH_TOKEN
|
||||
|
||||
publish_package() {
|
||||
local pkg_dir=$1
|
||||
cd $pkg_dir
|
||||
npm version ${{ github.event.inputs.version_bump }}
|
||||
npm publish --access public
|
||||
cd -
|
||||
}
|
||||
|
||||
case "${{ github.event.inputs.package }}" in
|
||||
ui)
|
||||
publish_package "pkg/ui"
|
||||
;;
|
||||
ui-mcp)
|
||||
publish_package "pkg/ui-mcp"
|
||||
;;
|
||||
auth)
|
||||
publish_package "pkg/auth"
|
||||
;;
|
||||
commerce)
|
||||
publish_package "pkg/commerce"
|
||||
;;
|
||||
all)
|
||||
publish_package "pkg/ui"
|
||||
publish_package "pkg/ui-mcp"
|
||||
publish_package "pkg/auth"
|
||||
publish_package "pkg/commerce"
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'chore: bump ${{ github.event.inputs.package }} version to ${{ github.event.inputs.version_bump }}'
|
||||
title: 'chore: bump ${{ github.event.inputs.package }} version'
|
||||
body: |
|
||||
Automated version bump for ${{ github.event.inputs.package }} package(s).
|
||||
|
||||
Version bump type: ${{ github.event.inputs.version_bump }}
|
||||
branch: version-bump-${{ github.event.inputs.package }}-${{ github.run_number }}
|
||||
@@ -0,0 +1,65 @@
|
||||
# Adapted from create-t3-app.
|
||||
name: Write Beta Release comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Release - Beta"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: |
|
||||
github.repository_owner == 'hanzoai-ui' &&
|
||||
${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
name: Write comment to the PR
|
||||
steps:
|
||||
- name: "Comment on PR"
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
|
||||
for (const artifact of allArtifacts.data.artifacts) {
|
||||
// Extract the PR number and package version from the artifact name
|
||||
const match = /^npm-package-hanzoai-ui@(.*?)-pr-(\d+)/.exec(artifact.name);
|
||||
|
||||
if (match) {
|
||||
require("fs").appendFileSync(
|
||||
process.env.GITHUB_ENV,
|
||||
`\nBETA_PACKAGE_VERSION=${match[1]}` +
|
||||
`\nWORKFLOW_RUN_PR=${match[2]}` +
|
||||
`\nWORKFLOW_RUN_ID=${context.payload.workflow_run.id}`
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- name: "Comment on PR with Link"
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
number: ${{ env.WORKFLOW_RUN_PR }}
|
||||
message: |
|
||||
A new prerelease is available for testing:
|
||||
|
||||
```sh
|
||||
npx hanzoai-ui@${{ env.BETA_PACKAGE_VERSION }}
|
||||
```
|
||||
|
||||
- name: "Remove the autorelease label once published"
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: '${{ env.WORKFLOW_RUN_PR }}',
|
||||
name: '🚀 autorelease',
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
# Adapted from create-t3-app.
|
||||
|
||||
name: Release - Beta
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
prerelease:
|
||||
if: |
|
||||
github.repository_owner == 'hanzoai' &&
|
||||
contains(github.event.pull_request.labels.*.name, '🚀 autorelease')
|
||||
name: Build & Publish a beta release to NPM
|
||||
runs-on: ubuntu-latest
|
||||
environment: Preview
|
||||
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use PNPM
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: 8.6.1
|
||||
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Modify package.json version
|
||||
run: node .github/version-script-beta.js
|
||||
|
||||
- name: Authenticate to NPM
|
||||
run: echo "//registry.npmjs.org/:_authToken=$NPM_ACCESS_TOKEN" >> pkg/cli/.npmrc
|
||||
env:
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
|
||||
- name: Publish Beta to NPM
|
||||
run: pnpm pub:beta
|
||||
|
||||
- name: get-npm-version
|
||||
id: package-version
|
||||
uses: martinbeentjes/npm-get-version-action@main
|
||||
with:
|
||||
path: pkg/cli
|
||||
|
||||
- name: Upload packaged artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: npm-package-hanzoai-ui@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name
|
||||
path: pkg/cli/dist/index.js
|
||||
@@ -0,0 +1,53 @@
|
||||
# Adapted from create-t3-app.
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: ${{ github.repository_owner == 'hanzoai-ui' }}
|
||||
name: Create a PR for release workflow
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use PNPM
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: 8.6.1
|
||||
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
version: 8.6.1
|
||||
node-version: 18
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: pnpm install
|
||||
|
||||
# - name: Check for errors
|
||||
# run: pnpm check
|
||||
|
||||
- name: Build the package
|
||||
run: pnpm build:cli
|
||||
|
||||
- name: Create Version PR or Publish to NPM
|
||||
id: changesets
|
||||
uses: changesets/action@v1.4.1
|
||||
with:
|
||||
commit: "chore(release): version packages"
|
||||
title: "chore(release): version packages"
|
||||
version: node .github/changeset-version.js
|
||||
publish: npx changeset publish
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
NODE_ENV: "production"
|
||||
@@ -0,0 +1,100 @@
|
||||
name: Sync Forks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
fork:
|
||||
description: 'Fork to sync (luxfi or zoo or all)'
|
||||
required: false
|
||||
default: 'all'
|
||||
|
||||
jobs:
|
||||
sync-luxfi:
|
||||
if: github.event.inputs.fork == 'luxfi' || github.event.inputs.fork == 'all' || github.event_name == 'push'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Hanzo UI
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.name "Hanzo Bot"
|
||||
git config --global user.email "bot@hanzo.ai"
|
||||
|
||||
- name: Clone Luxfi Fork
|
||||
run: |
|
||||
git clone https://github.com/luxfi/ui.git luxfi-ui
|
||||
cd luxfi-ui
|
||||
git remote add upstream https://github.com/hanzoai/ui.git
|
||||
git fetch upstream
|
||||
|
||||
- name: Sync and Rebrand
|
||||
run: |
|
||||
cd luxfi-ui
|
||||
# Merge upstream changes
|
||||
git checkout main
|
||||
git merge upstream/main --no-edit || true
|
||||
|
||||
# Run rebrand script
|
||||
cp ../scripts/rebrand.sh ./
|
||||
chmod +x rebrand.sh
|
||||
./rebrand.sh luxfi
|
||||
|
||||
# Commit changes
|
||||
git add -A
|
||||
git commit -m "sync: Update from hanzoai/ui and rebrand for Luxfi" || true
|
||||
|
||||
- name: Push to Luxfi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FORK_SYNC_TOKEN }}
|
||||
run: |
|
||||
cd luxfi-ui
|
||||
git push https://$GITHUB_TOKEN@github.com/luxfi/ui.git main || true
|
||||
|
||||
sync-zoo:
|
||||
if: github.event.inputs.fork == 'zoo' || github.event.inputs.fork == 'all' || github.event_name == 'push'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Hanzo UI
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.name "Hanzo Bot"
|
||||
git config --global user.email "bot@hanzo.ai"
|
||||
|
||||
- name: Clone Zoo Fork
|
||||
run: |
|
||||
git clone https://github.com/zooai/ui.git zoo-ui
|
||||
cd zoo-ui
|
||||
git remote add upstream https://github.com/hanzoai/ui.git
|
||||
git fetch upstream
|
||||
|
||||
- name: Sync and Rebrand
|
||||
run: |
|
||||
cd zoo-ui
|
||||
# Merge upstream changes
|
||||
git checkout main
|
||||
git merge upstream/main --no-edit || true
|
||||
|
||||
# Run rebrand script
|
||||
cp ../scripts/rebrand.sh ./
|
||||
chmod +x rebrand.sh
|
||||
./rebrand.sh zoo
|
||||
|
||||
# Commit changes
|
||||
git add -A
|
||||
git commit -m "sync: Update from hanzoai/ui and rebrand for Zoo" || true
|
||||
|
||||
- name: Push to Zoo
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.FORK_SYNC_TOKEN }}
|
||||
run: |
|
||||
cd zoo-ui
|
||||
git push https://$GITHUB_TOKEN@github.com/zooai/ui.git main || true
|
||||
@@ -0,0 +1,58 @@
|
||||
name: E2E and Visual Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
schedule:
|
||||
# Run tests daily at 2 AM UTC to catch breaking updates
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 9.0.6
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: pnpm exec playwright install --with-deps
|
||||
|
||||
- name: Build the project
|
||||
run: pnpm build
|
||||
|
||||
- name: Run component health check
|
||||
run: pnpm health-check
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run E2E tests
|
||||
run: pnpm test:e2e
|
||||
|
||||
- name: Run visual regression tests
|
||||
run: pnpm test:visual
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
@@ -47,37 +47,12 @@ package-lock.json
|
||||
# pnpm-lock.yaml - needed for CI/CD, do not ignore
|
||||
yarn.lock
|
||||
|
||||
# AI cruft
|
||||
|
||||
|
||||
|
||||
|
||||
AGENTS.md
|
||||
CLAUDE.md
|
||||
GEMINI.md
|
||||
GROK.md
|
||||
QWEN.md
|
||||
|
||||
.playwright-mcp
|
||||
app/out
|
||||
app/.source
|
||||
|
||||
# test artifacts
|
||||
tests/reports/
|
||||
tests/artifacts/
|
||||
|
||||
# Note: Block screenshots are pre-generated and committed
|
||||
# They cannot be generated in CI (requires display/browser)
|
||||
# app/public/r/styles/*/ -- REMOVED to allow committing screenshots
|
||||
|
||||
|
||||
# Test artifacts
|
||||
test-results/
|
||||
playwright-report/
|
||||
*BADGE_INSPECTION*.md
|
||||
*BADGE_INSPECTION*.txt
|
||||
|
||||
# ide
|
||||
.idea
|
||||
.fleet
|
||||
|
||||
.notes
|
||||
.claude/settings.local.json
|
||||
pkg/ui/dist-test/
|
||||
app/public/api/
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# The whole caller. Every decision this pipeline makes — what to test, what to
|
||||
# build, where to roll it — is read from the root hanzo.yml, so this file only
|
||||
# ever names the triggers and the reusable.
|
||||
#
|
||||
# `.hanzo/workflows`, not `.github/workflows`, and that is not a style choice:
|
||||
# CI for this repo runs on git.hanzo.ai, which resolves ONLY `.hanzo/workflows`.
|
||||
# github.com has zero self-hosted runners registered for the `hanzo-build-*`
|
||||
# labels this pipeline asks for, so the same file under `.github/workflows`
|
||||
# would queue there forever and never report anything at all.
|
||||
name: CI/CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ['v*']
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: cicd-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
cicd:
|
||||
uses: hanzoai/ci/.hanzo/workflows/build.yml@v1
|
||||
secrets: inherit
|
||||
@@ -1,70 +0,0 @@
|
||||
name: deploy
|
||||
|
||||
# RETIRED as an automatic lane. The image is built by hanzo.yml's `images:` block
|
||||
# through hanzoai/ci (.hanzo/workflows/cicd.yml), and this job is kept only as a
|
||||
# manually-dispatched fallback.
|
||||
#
|
||||
# The reason is one capability, not tidiness. ui.hanzo.ai is a static export, so
|
||||
# its ingest key has to be BAKED IN at build; the key lives in KMS as
|
||||
# `deploy/PUBLISHABLE_KEY`, and hanzoai/ci is the only lane that reads it and
|
||||
# passes it as `--build-arg PUBLISHABLE_KEY=…`. The `docker build -t "$image" .`
|
||||
# below cannot — there is no KMS hop in it and nowhere to put the value — so any
|
||||
# image it produced would ship a client with no key at all, and cloud answers
|
||||
# `401 ingest_key_required` for an unattributed write. With the Dockerfile now
|
||||
# failing closed on an empty key, this job fails on every run instead of quietly
|
||||
# publishing an inert site.
|
||||
#
|
||||
# Left in place rather than deleted, and dispatch-only rather than on push:
|
||||
# deleting a repo's only build lane strands the host with no failing run to show
|
||||
# it, and two push-triggered builders for one image means one commit yields two
|
||||
# images under two tag schemes. Dispatching this publishes `<short-sha>` with an
|
||||
# EMPTY key and the Dockerfile will refuse it — so if you dispatch it, pass the
|
||||
# key yourself or expect the gate to fire.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: deploy-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
image:
|
||||
# hanzo-build-linux-amd64, not ubuntu-latest. This file lives in
|
||||
# .hanzo/workflows, which GitHub never reads -- git.hanzo.ai is the only
|
||||
# thing that can run it, and the fleet deliberately advertises no generic
|
||||
# ubuntu-* label (~1400 mirrored forks all ask for it; one bad job was
|
||||
# retried ~520 times across 10 runners). An unmatched label is not an
|
||||
# error here, it is silence: the job queues until the 24h timeout, so this
|
||||
# deploy has never produced an image and nothing ever said so.
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: build and push
|
||||
# GHCR_TOKEN/GHCR_USER, which are the org secrets that actually exist.
|
||||
# This job asked for REGISTRY_TOKEN, which was never defined anywhere —
|
||||
# the org has exactly GHCR_TOKEN, GHCR_USER, GH_PAT, KMS_CLIENT_ID,
|
||||
# KMS_CLIENT_SECRET, OCI_TOKEN, OCI_USER — so the guard below fired on
|
||||
# every run and nothing was ever published. Every other image build in
|
||||
# the org already uses the GHCR_* pair; this file and papers were the
|
||||
# two that invented a name.
|
||||
#
|
||||
# The username comes from the secret too, rather than being hardcoded to
|
||||
# hanzo-dev, so rotating the publishing identity is one org-level change.
|
||||
env:
|
||||
GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }}
|
||||
GHCR_USER: ${{ secrets.GHCR_USER }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${GHCR_TOKEN:-}" ] || [ -z "${GHCR_USER:-}" ]; then
|
||||
echo "::error::GHCR_TOKEN/GHCR_USER are unset, so nothing was published."
|
||||
exit 1
|
||||
fi
|
||||
tag="$(git rev-parse --short HEAD)"
|
||||
image="ghcr.io/hanzoai/ui:${tag}"
|
||||
echo "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USER}" --password-stdin
|
||||
docker build -t "${image}" .
|
||||
docker push "${image}"
|
||||
echo "published ${image} — set image.tag AND image.digest in universe charts/app/values/hanzo/ui.yaml"
|
||||
@@ -1,343 +0,0 @@
|
||||
name: Publish Packages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
# BOTH package roots, and the singular one is not a typo — `@hanzo/ui` and
|
||||
# `@hanzo/data` live under pkg/, everything else under pkgs/.
|
||||
#
|
||||
# ⚠️ This list and the `for pkg_json in …` loop below are ONE FACT. The loop
|
||||
# was already fixed to walk both roots, with a comment explaining that a
|
||||
# `pkgs/*` glob made pkg/ packages invisible — but this gate was left
|
||||
# matching `pkgs/*` only, so for a pkg/-only change the corrected job could
|
||||
# never be REACHED. The fix was reasoned about in the body and not applied
|
||||
# to the thing that decides whether the body runs.
|
||||
#
|
||||
# Cost: @hanzo/ui 8.0.29 sat unpublished while npmjs served 8.0.28, so
|
||||
# every consumer resolving `^8.0.17` silently got a version without the
|
||||
# `./chat` entrypoint — an import error in the dependent, nothing at all in
|
||||
# this repo. Add a root here whenever one is added to the loop.
|
||||
- 'pkg/*/package.json'
|
||||
- 'pkgs/*/package.json'
|
||||
# A publish that fails for an infrastructure reason — the runner missing a
|
||||
# tool, npmjs answering slowly — could only be retried by pushing another
|
||||
# commit that touches a package.json, i.e. by burning a version number to
|
||||
# re-run a job that was never wrong about the code. detect-changes reads what
|
||||
# npmjs SERVES, so a dispatch is idempotent by construction: it publishes
|
||||
# exactly the packages that are ahead of the registry, and nothing when none
|
||||
# are.
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
outputs:
|
||||
packages: ${{ steps.changed.outputs.packages }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Detect changed packages
|
||||
id: changed
|
||||
run: |
|
||||
CHANGED=()
|
||||
# Both package roots. `@hanzo/ui` and `@hanzo/data` live under pkg/ (singular)
|
||||
# and were invisible to a `pkgs/*` glob, so no version bump of either could
|
||||
# ever reach npmjs from here.
|
||||
for pkg_json in pkg/*/package.json pkgs/*/package.json; do
|
||||
[ ! -f "$pkg_json" ] && continue
|
||||
# Skip private packages
|
||||
IS_PRIVATE=$(jq -r '.private // false' "$pkg_json")
|
||||
[ "$IS_PRIVATE" = "true" ] && continue
|
||||
|
||||
# Only publish @hanzo/* packages
|
||||
PKG_NAME=$(jq -r '.name' "$pkg_json")
|
||||
case "$PKG_NAME" in
|
||||
@hanzo/*) ;;
|
||||
*) continue ;;
|
||||
esac
|
||||
|
||||
# What npm SERVES, not what the previous commit said. HEAD~1 is the
|
||||
# FIRST PARENT, so a merge whose first parent is the feature branch
|
||||
# already carries the new version and the diff is empty — the publish
|
||||
# is skipped and npm keeps serving the old release, silently. Asking
|
||||
# the registry is independent of merge topology and of how many
|
||||
# commits the runner fetched.
|
||||
NEW=$(jq -r '.version' "$pkg_json")
|
||||
OLD=$(curl -sf "https://registry.npmjs.org/${PKG_NAME}" \
|
||||
| jq -r '."dist-tags".latest // "0.0.0"' 2>/dev/null || echo "0.0.0")
|
||||
|
||||
# FORWARD ONLY. `!=` fires in both directions, and several packages
|
||||
# sit BEHIND npm (a release cut elsewhere, a revert) — publishing
|
||||
# those walks the registry backwards. Only a strictly greater local
|
||||
# version is a release.
|
||||
NEWEST=$(printf '%s\n%s\n' "$OLD" "$NEW" | sort -V | tail -1)
|
||||
if [ "$OLD" != "$NEW" ] && [ "$NEWEST" = "$NEW" ]; then
|
||||
echo "Version change: $PKG_NAME ($OLD -> $NEW)"
|
||||
# The package NAME, because every downstream step spends this as a
|
||||
# `pnpm --filter` argument and a directory basename matches nothing.
|
||||
# An unmatched filter exits 0, so the build silently no-ops and the
|
||||
# publish ships an unbuilt tarball — how 8.0.17 and 8.0.19 shipped broken.
|
||||
CHANGED+=("$PKG_NAME")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#CHANGED[@]} -eq 0 ]; then
|
||||
echo "packages=[]" >> $GITHUB_OUTPUT
|
||||
else
|
||||
JSON=$(printf '%s\n' "${CHANGED[@]}" | jq -R . | jq -s -c .)
|
||||
echo "packages=$JSON" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
publish:
|
||||
needs: detect-changes
|
||||
if: needs.detect-changes.outputs.packages != '[]'
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
strategy:
|
||||
# One package's broken build must not withhold every other package's
|
||||
# release: the matrix legs are independent publishes, not one artifact.
|
||||
fail-fast: false
|
||||
matrix:
|
||||
package: ${{ fromJson(needs.detect-changes.outputs.packages) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build package
|
||||
# The trailing `...` is load-bearing: it builds the package's WORKSPACE
|
||||
# DEPENDENCIES first, in topological order.
|
||||
#
|
||||
# Without it, `pnpm --filter @hanzo/ui build` runs alone against siblings
|
||||
# that have no `dist/`. Those siblings type themselves through
|
||||
# `"types": "dist/index.d.ts"`, so tsc reports them as missing modules and
|
||||
# the errors do not name the real cause:
|
||||
# src/product/SiteNav.tsx: Cannot find module '@hanzo/products'
|
||||
# src/core/tokens.ts: Cannot find module '@hanzo/tokens'
|
||||
# src/gitops.ts: Cannot find module '@hanzo/cd'
|
||||
# plus a wave of implicit-any errors in the files that imported them,
|
||||
# which read like a source problem in @hanzo/ui and are not.
|
||||
run: pnpm --filter ${{ matrix.package }}... build
|
||||
|
||||
- name: Provision bun (only for a package whose test script asks for it)
|
||||
# @hanzo/canvas declares `bun test` and this runner has no bun, so its
|
||||
# suite has been `spawn ENOENT` on every run — which fails the leg before
|
||||
# the publish and is why canvas has sat at 0.2.2 here against 0.2.1 on
|
||||
# npmjs. The step that exists to stop an untested release was itself the
|
||||
# thing stopping the release.
|
||||
#
|
||||
# Read from the package's OWN manifest, not from a list here, so a
|
||||
# package that adopts or drops bun needs no edit to this file. A package
|
||||
# that does not ask for bun does not pay for it.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PKG_DIR=$(pnpm --filter ${{ matrix.package }} exec pwd | tail -1)
|
||||
if ! jq -r '.scripts.test // ""' "$PKG_DIR/package.json" | grep -qw bun; then
|
||||
echo "::notice::${{ matrix.package }} does not run bun"
|
||||
exit 0
|
||||
fi
|
||||
if command -v bun >/dev/null 2>&1; then
|
||||
echo "bun already on PATH: $(bun --version)"
|
||||
exit 0
|
||||
fi
|
||||
# From npmjs, not bun.sh/install: this job already reaches the npm
|
||||
# registry (it is what the job exists to publish to) and setup-node
|
||||
# already put the global bin on PATH, so this adds no new host to
|
||||
# trust and no new failure mode. The shell installer would also want
|
||||
# unzip, which a minimal runner image need not carry.
|
||||
npm install -g bun
|
||||
bun --version
|
||||
|
||||
- name: Test package
|
||||
# A published version is IMMUTABLE, so this is the last point at which a
|
||||
# defect costs nothing. Nothing else runs a package's own tests before it
|
||||
# ships: ci.yml's test job runs `cd pkgs/ui && …` — that one directory —
|
||||
# and this workflow went checkout → build → publish. So @hanzo/event's
|
||||
# suite, which pins the version the client stamps on every event, ran in
|
||||
# no workflow that gates a release, and the stale stamp it was written to
|
||||
# catch could still have reached npmjs.
|
||||
#
|
||||
# `--if-present` so a package with no test script is skipped rather than
|
||||
# failing the release: the set of testable packages is read from each
|
||||
# package.json, not listed here, so a new package is covered the day it
|
||||
# adds a `test` script.
|
||||
#
|
||||
# This step needs `test` to mean the same thing in every package — the
|
||||
# package's own suite, no browser, no network. @hanzo/ui briefly chained
|
||||
# its two CONSUMER suites onto it (pack a tarball, npm-install it into a
|
||||
# throwaway app, drive it in chromium), which is a real gate and belongs
|
||||
# exactly where hanzo.yml already runs it: on the push, in its own
|
||||
# `ui-consumer` job, next to the `playwright install` that gives it a
|
||||
# browser. Here there is no such step, so a chained `test` could only
|
||||
# fail — the last gate before an immutable version would have been one
|
||||
# that cannot pass, which is the failure mode this repo has already paid
|
||||
# for twice.
|
||||
run: pnpm --filter ${{ matrix.package }} run --if-present test
|
||||
|
||||
- name: Verify the tarball carries what package.json promises
|
||||
# `types` is a PROMISE to every consumer, and tsup writes dist/*.mjs in a
|
||||
# separate pass from dist/*.d.ts — so a declaration failure yields a
|
||||
# package whose JS is fine and whose types are absent. That is invisible
|
||||
# here and surfaces in dependents as "Could not find a declaration file".
|
||||
#
|
||||
# Asserted from the package's OWN manifest, so it holds for every package
|
||||
# this workflow publishes and needs no per-package list.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
PKG_DIR=$(pnpm --filter ${{ matrix.package }} exec pwd | tail -1)
|
||||
TYPES=$(jq -r '.types // .typings // empty' "$PKG_DIR/package.json")
|
||||
if [ -z "$TYPES" ]; then
|
||||
echo "::notice::${{ matrix.package }} declares no types entrypoint — nothing to verify"
|
||||
exit 0
|
||||
fi
|
||||
if [ ! -f "$PKG_DIR/$TYPES" ]; then
|
||||
echo "::error::${{ matrix.package }} declares types at $TYPES but the build produced no such file."
|
||||
echo "::error::Publishing would ship a package that silently has no types. Fix the declaration build."
|
||||
exit 1
|
||||
fi
|
||||
echo "types present: $TYPES"
|
||||
|
||||
- name: Fetch the npm token from KMS
|
||||
id: npmtok
|
||||
# publish.yml used secrets.NPM_TOKEN, which exists on NEITHER the hanzoai
|
||||
# org nor this repo on git.hanzo.ai. An absent secret interpolates to the
|
||||
# empty string rather than failing, so every publish reached npmjs
|
||||
# unauthenticated and 401'd -- the reason @hanzo/ui has never shipped from
|
||||
# CI and each release was a hand publish.
|
||||
#
|
||||
# KMS is where a secret lives, so the token is read at run time from the
|
||||
# same org path and with the same machine identity every other workflow
|
||||
# here already uses. Nothing new to rotate, and no npm credential is
|
||||
# stored on the forge.
|
||||
env:
|
||||
KMS_CLIENT_ID: ${{ secrets.KMS_CLIENT_ID }}
|
||||
KMS_CLIENT_SECRET: ${{ secrets.KMS_CLIENT_SECRET }}
|
||||
KMS_ENDPOINT: ${{ vars.KMS_ENDPOINT || 'https://kms.hanzo.ai' }}
|
||||
KMS_ORG: ${{ vars.KMS_ORG || 'hanzo' }}
|
||||
KMS_SECRET_ENV: ${{ vars.KMS_SECRET_ENV || 'prod' }}
|
||||
# Where the token actually lives, MEASURED: NPM_TOKEN sits at the org
|
||||
# root, not under deploy/ (which holds CLOUDFLARE_*, GIT_TOKEN,
|
||||
# KUBECONFIG, UNIVERSE_PIN_TOKEN). Empty means root; set the
|
||||
# KMS_NPM_PATH variable to move it without editing this file.
|
||||
KMS_NPM_PATH: ${{ vars.KMS_NPM_PATH || '' }}
|
||||
run: |
|
||||
token=$(curl -fsS "${KMS_ENDPOINT}/v1/kms/auth/login" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"clientId\":\"${KMS_CLIENT_ID}\",\"clientSecret\":\"${KMS_CLIENT_SECRET}\"}" \
|
||||
| jq -r '.accessToken // empty')
|
||||
if [ -z "${token}" ]; then
|
||||
echo "::error::KMS login failed at ${KMS_ENDPOINT}/v1/kms/auth/login (check KMS_CLIENT_ID/KMS_CLIENT_SECRET)."
|
||||
exit 1
|
||||
fi
|
||||
# The read is org-scoped by the TOKEN's owner claim, not by a path
|
||||
# segment: the flat form is the contract cloud's embedded KMS serves,
|
||||
# and it answers {name, env, value}. The older
|
||||
# /v1/kms/orgs/<org>/secrets/... form with .secret.value 404s here.
|
||||
secret_url="${KMS_ENDPOINT}/v1/kms/secrets/${KMS_NPM_PATH:+${KMS_NPM_PATH}/}NPM_TOKEN?env=${KMS_SECRET_ENV}"
|
||||
# No -f: a 404 must report WHICH path was empty, not just exit 22.
|
||||
npm_token=$(curl -sS "${secret_url}" -H "Authorization: Bearer ${token}" | jq -r '.value // empty')
|
||||
if [ -z "${npm_token}" ]; then
|
||||
echo "::error::No NPM_TOKEN at ${secret_url}."
|
||||
echo "::error::Put it there, or set the KMS_NPM_PATH variable to the path that has it."
|
||||
exit 1
|
||||
fi
|
||||
# Masked before it is ever an output, so it cannot surface in a log.
|
||||
echo "::add-mask::${npm_token}"
|
||||
echo "token=${npm_token}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Publish package
|
||||
# Idempotent on purpose: the desired state is "npmjs holds this version", and
|
||||
# a version already there satisfies it. Versions are immutable, so a conflict
|
||||
# means the release already happened (a re-run, or a hand publish) — that is
|
||||
# success, not a failure. Every other error still fails the job.
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ steps.npmtok.outputs.token }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
OUT=$(pnpm --filter ${{ matrix.package }} publish \
|
||||
--no-git-checks --access public 2>&1) || true
|
||||
echo "$OUT"
|
||||
case "$OUT" in
|
||||
*EPUBLISHCONFLICT*|*"cannot publish over"*|*"previously published versions"*)
|
||||
echo "::notice::${{ matrix.package }} is already on npmjs at this version — nothing to do" ;;
|
||||
*)
|
||||
# Not a conflict: confirm the version really landed, else fail loudly.
|
||||
#
|
||||
# RETRIED, because npmjs is read-after-write eventually consistent
|
||||
# and this asked it exactly once, about two seconds after the
|
||||
# write. On run 26906 both @hanzo/og@1.0.0 and @hanzo/shop@1.0.0
|
||||
# failed here having printed npm's own `+ @hanzo/og@1.0.0` success
|
||||
# line moments earlier, and both are on the registry now: the
|
||||
# publishes worked and the check was simply too early.
|
||||
#
|
||||
# A false red here is worse than a slow green. It reports that a
|
||||
# release did not happen when it did, so the next person bumps the
|
||||
# version to "fix" it and burns a number over a replication lag —
|
||||
# and the real signal, a publish that genuinely failed, becomes
|
||||
# indistinguishable from the noise.
|
||||
PKG_DIR=$(pnpm --filter ${{ matrix.package }} exec pwd | tail -1)
|
||||
NAME=$(jq -r '.name' "$PKG_DIR/package.json")
|
||||
WANT=$(jq -r '.version' "$PKG_DIR/package.json")
|
||||
landed=
|
||||
for attempt in 1 2 3 4 5 6; do
|
||||
if npm view "$NAME@$WANT" version >/dev/null 2>&1; then landed=1; break; fi
|
||||
echo "$NAME@$WANT not visible to npmjs yet (attempt $attempt/6); waiting 10s"
|
||||
sleep 10
|
||||
done
|
||||
[ -n "$landed" ] \
|
||||
|| { echo "::error::$NAME@$WANT is not on npmjs 60s after publish"; exit 1; }
|
||||
echo "published $NAME@$WANT" ;;
|
||||
esac
|
||||
|
||||
- name: Publish to the Hanzo registry
|
||||
# Second home for the same tarball: api.hanzo.ai/v1/packages/hanzo/npm, our
|
||||
# own registry (hanzoai/git), so an install does not have to reach npmjs.
|
||||
# Same artifact, same version — this republishes what the step above just
|
||||
# built, it does not rebuild or re-version.
|
||||
#
|
||||
# BEST-EFFORT by construction. No token ⇒ skip with a notice, so this can
|
||||
# land before the credential exists and starts working the moment it does.
|
||||
# An already-published version is a success, not a failure: the registry
|
||||
# holding it is the desired state either way. npmjs is authoritative and is
|
||||
# never affected by anything here.
|
||||
env:
|
||||
# REGISTRY_TOKEN is the fleet-wide name (six other workflows use it and
|
||||
# the hanzoai org carries it). This asked for HANZO_REGISTRY_TOKEN, which
|
||||
# is defined nowhere, so it read as empty and the step below took its
|
||||
# "not set" branch and exited 0 on every run -- the mirror to
|
||||
# api.hanzo.ai has never happened, and said so only as a notice.
|
||||
HANZO_REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
set -uo pipefail
|
||||
if [ -z "${HANZO_REGISTRY_TOKEN:-}" ]; then
|
||||
echo "::notice::HANZO_REGISTRY_TOKEN not set — package published to npmjs only."
|
||||
echo "::notice::Add it (a Hanzo Git token with package:write) to mirror to api.hanzo.ai."
|
||||
exit 0
|
||||
fi
|
||||
REG=https://api.hanzo.ai/v1/packages/hanzo/npm/
|
||||
NPMRC="$RUNNER_TEMP/.npmrc-hanzo"
|
||||
{
|
||||
echo "@hanzo:registry=${REG}"
|
||||
echo "//api.hanzo.ai/v1/packages/hanzo/npm/:_authToken=${HANZO_REGISTRY_TOKEN}"
|
||||
} > "$NPMRC"
|
||||
out=$(npm_config_userconfig="$NPMRC" \
|
||||
pnpm --filter ${{ matrix.package }} publish \
|
||||
--no-git-checks --access public --registry "$REG" 2>&1) || true
|
||||
echo "$out"
|
||||
case "$out" in
|
||||
*EPUBLISHCONFLICT*|*"cannot publish over"*|*"already exists"*)
|
||||
echo "::notice::already in the Hanzo registry at this version — nothing to do" ;;
|
||||
*) echo "$out" | grep -qiE 'error|failed' \
|
||||
&& echo "::warning::mirror to api.hanzo.ai failed (npmjs publish unaffected)" \
|
||||
|| echo "mirrored to the Hanzo registry" ;;
|
||||
esac
|
||||
@@ -1,91 +0,0 @@
|
||||
name: Validate Registries
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "apps/v4/public/r/registries.json"
|
||||
- "apps/v4/registry/directory.json"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "apps/v4/public/r/registries.json"
|
||||
- "apps/v4/registry/directory.json"
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
name: pnpm validate:registries
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Block reserved registry namespaces
|
||||
env:
|
||||
RESERVED_NAMESPACES: "@shadcn,@ui,@blocks,@components,@block,@component,@util,@utils,@registry,@lib,@hook,@hooks,@theme,@themes,@chart,@charts"
|
||||
run: |
|
||||
node <<'EOF'
|
||||
const fs = require("node:fs")
|
||||
|
||||
const files = [
|
||||
"apps/v4/public/r/registries.json",
|
||||
"apps/v4/registry/directory.json",
|
||||
]
|
||||
const reservedNamespaces = new Set(
|
||||
process.env.RESERVED_NAMESPACES.split(",").filter(Boolean)
|
||||
)
|
||||
|
||||
function readNames(filePath) {
|
||||
return JSON.parse(fs.readFileSync(filePath, "utf8")).map(
|
||||
(entry) => entry.name
|
||||
)
|
||||
}
|
||||
|
||||
const violations = files.flatMap((filePath) => {
|
||||
return readNames(filePath)
|
||||
.filter((name) => reservedNamespaces.has(name))
|
||||
.map((name) => `${filePath}: ${name}`)
|
||||
})
|
||||
|
||||
if (violations.length > 0) {
|
||||
console.error("Reserved registry namespaces are not allowed:")
|
||||
|
||||
for (const violation of violations) {
|
||||
console.error(`- ${violation}`)
|
||||
}
|
||||
|
||||
process.exit(1)
|
||||
}
|
||||
EOF
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 9.0.6
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Validate registries
|
||||
run: pnpm --filter=v4 validate:registries
|
||||
@@ -1,18 +0,0 @@
|
||||
# .kodiak.toml
|
||||
version = 1
|
||||
|
||||
[merge]
|
||||
automerge_label = "automerge"
|
||||
require_automerge_label = true
|
||||
method = "squash"
|
||||
delete_branch_on_merge = true
|
||||
optimistic_updates = false
|
||||
prioritize_ready_to_merge = true
|
||||
notify_on_conflict = true
|
||||
|
||||
[merge.message]
|
||||
title = "pull_request_title"
|
||||
body = "pull_request_body"
|
||||
include_pr_number = true
|
||||
body_type = "markdown"
|
||||
strip_html_comments = true
|
||||
@@ -1,3 +0,0 @@
|
||||
auto-install-peers=true
|
||||
link-workspace-packages=true
|
||||
puppeteer_skip_download=true
|
||||
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 255 KiB |
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 256 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 243 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 520 KiB |
|
After Width: | Height: | Size: 414 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 257 KiB |
|
After Width: | Height: | Size: 351 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 427 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 413 KiB |
|
After Width: | Height: | Size: 251 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 523 KiB |
|
After Width: | Height: | Size: 701 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 410 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 689 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 257 KiB |
|
After Width: | Height: | Size: 255 KiB |
|
After Width: | Height: | Size: 317 KiB |
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 511 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 256 KiB |
|
After Width: | Height: | Size: 511 KiB |
|
After Width: | Height: | Size: 331 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 900 KiB |
|
After Width: | Height: | Size: 428 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 231 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 425 KiB |
|
After Width: | Height: | Size: 643 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 196 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 400 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 372 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 400 KiB |
|
After Width: | Height: | Size: 144 KiB |