Compare commits
721 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e1b0e6179 | ||
|
|
b4f34ed319 | ||
|
|
ba992bb822 | ||
|
|
345531d0a4 | ||
|
|
2e620f9c90 | ||
|
|
0162b2cf8b | ||
|
|
7397cfe37c | ||
|
|
a3d5eee63a | ||
|
|
85c3d8b7f3 | ||
|
|
22773fa848 | ||
|
|
cbf7323bc1 | ||
|
|
382ab4c9ac | ||
|
|
b0b34198c4 | ||
|
|
842eaf5ac0 | ||
|
|
2f0f57f46e | ||
|
|
4f8b9ae301 | ||
|
|
0aaa94bdee | ||
|
|
654afbf8c5 | ||
|
|
d256fc587d | ||
|
|
ca8ad9e7ab | ||
|
|
53aedd9542 | ||
|
|
01fb6c8d3b | ||
|
|
6439a13308 | ||
|
|
a6ccf4cb79 | ||
|
|
333909f560 | ||
|
|
0b7584385a | ||
|
|
3a94f7311f | ||
|
|
f2404dca2f | ||
|
|
8bae8c963f | ||
|
|
c00b0d2393 | ||
|
|
f861f8df56 | ||
|
|
7b8ae12eb0 | ||
|
|
10fbe0d8d4 | ||
|
|
8ba5f4ae6f | ||
|
|
fcb1e5a298 | ||
|
|
459eee50e8 | ||
|
|
9c67bc4427 | ||
|
|
d86ab59115 | ||
|
|
945d269b25 | ||
|
|
692b091ac0 | ||
|
|
3984b38120 | ||
|
|
57c7ba07e5 | ||
|
|
73ff711ca0 | ||
|
|
ce2ae460d6 | ||
|
|
f61800c7a9 | ||
|
|
45b39556af | ||
|
|
5172be8e2f | ||
|
|
1ded416304 | ||
|
|
2ea2c9d9ee | ||
|
|
9442c70243 | ||
|
|
36dc518728 | ||
|
|
a05039c77d | ||
|
|
eb8ed6b687 | ||
|
|
44e7279490 | ||
|
|
5e6dd63795 | ||
|
|
9ab04625a7 | ||
|
|
974eb14a42 | ||
|
|
b13a880f18 | ||
|
|
a198dbc46d | ||
|
|
d82a614b83 | ||
|
|
945397f145 | ||
|
|
33cdba4686 | ||
|
|
5eeec21377 | ||
|
|
cc10fd84d6 | ||
|
|
48394148f4 | ||
|
|
3c97831db9 | ||
|
|
2aaf8dc22d | ||
|
|
d4379528b4 | ||
|
|
8b935c624b | ||
|
|
e0deaff943 | ||
|
|
2149af8d90 | ||
|
|
1e11a6ae9d | ||
|
|
8ef5b18fcf | ||
|
|
7d9e85a9da | ||
|
|
3616f2901b | ||
|
|
b1d718004d | ||
|
|
077fb8ba53 | ||
|
|
2a71af4445 | ||
|
|
4a30d04fe2 | ||
|
|
0c34b0e7cf | ||
|
|
c447ec0b97 | ||
|
|
7b4504332f | ||
|
|
a980bcd0c5 | ||
|
|
7a87dc0d65 | ||
|
|
18946344af | ||
|
|
3d735ba61a | ||
|
|
14952de7ed | ||
|
|
12285e1fc3 | ||
|
|
473d258161 | ||
|
|
8d87ba5a72 | ||
|
|
841fd33bb7 | ||
|
|
a3709540ed | ||
|
|
6371b3d325 | ||
|
|
f8df53283c | ||
|
|
f312d8d21e | ||
|
|
41a2ea0c9b | ||
|
|
d5209cea68 | ||
|
|
4f0696b47c | ||
|
|
f0de40cffa | ||
|
|
abec938c9b | ||
|
|
1d22f02ce4 | ||
|
|
a5ead9a86c | ||
|
|
b42885d9a9 | ||
|
|
8d01bf1bfc | ||
|
|
ccdd59f096 | ||
|
|
949f09fa44 | ||
|
|
5f53738d84 | ||
|
|
a111fe1e61 | ||
|
|
ccfdc68a38 | ||
|
|
9c05197992 | ||
|
|
764a608ae0 | ||
|
|
be39e7c75a | ||
|
|
81f1dd4f57 | ||
|
|
4634011afa | ||
|
|
535c57eda3 | ||
|
|
d57249b699 | ||
|
|
0bc914c6cd | ||
|
|
f636ea29ca | ||
|
|
3fe3252d57 | ||
|
|
5e6eb921cf | ||
|
|
ce5e865551 | ||
|
|
7736c355dc | ||
|
|
944ec75cf6 | ||
|
|
d727f06dc0 | ||
|
|
3c4372146e | ||
|
|
d5be659121 | ||
|
|
2f9b11c5ca | ||
|
|
93ca750952 | ||
|
|
fbfc9b33af | ||
|
|
bb9028cd44 | ||
|
|
72fab21aba | ||
|
|
ad7ffdebbe | ||
|
|
a9e04b410c | ||
|
|
747bc1653d | ||
|
|
8dac860c22 | ||
|
|
074578feee | ||
|
|
22bb9492bf | ||
|
|
5515e9705a | ||
|
|
517e370b73 | ||
|
|
4f8424eebb | ||
|
|
d018ed13d0 | ||
|
|
fd15fa02c0 | ||
|
|
4eade91d5b | ||
|
|
d235481ee7 | ||
|
|
f0bd06d036 | ||
|
|
e958ed5b3f | ||
|
|
29f8f30aa9 | ||
|
|
6aa7c206c6 | ||
|
|
e05a413e8a | ||
|
|
965b96d275 | ||
|
|
f04e1d3acb | ||
|
|
2a13876756 | ||
|
|
5197b8fa3d | ||
|
|
fc1b7fac4b | ||
|
|
af0095404d | ||
|
|
7ee633887d | ||
|
|
9c7140767c | ||
|
|
7cb0fac5c0 | ||
|
|
9b9d27dc4c | ||
|
|
e5e1cd0f99 | ||
|
|
a84516d0dd | ||
|
|
85dfc7a573 | ||
|
|
5c04d3904d | ||
|
|
d8def31251 | ||
|
|
7ab28f9678 | ||
|
|
6bd8db31fe | ||
|
|
b449e6efd0 | ||
|
|
764b218deb | ||
|
|
f592739bbc | ||
|
|
dd7595981f | ||
|
|
8ba2bc9036 | ||
|
|
18535e8207 | ||
|
|
8032ed96f6 | ||
|
|
efa21ec9ac | ||
|
|
3588cc8ad4 | ||
|
|
bbd652b087 | ||
|
|
e85f11c5bd | ||
|
|
5d9b7822a6 | ||
|
|
b4f8e5f0f9 | ||
|
|
3ed33f61c4 | ||
|
|
a61e8fdb65 | ||
|
|
364d8e8cda | ||
|
|
1c0dc52a0e | ||
|
|
36cc95143c | ||
|
|
24b234cb06 | ||
|
|
b2a04264d7 | ||
|
|
019e7ff457 | ||
|
|
0ea9d89ee1 | ||
|
|
1764424b68 | ||
|
|
dfe6c8d9e5 | ||
|
|
0f9a1c9368 | ||
|
|
6b0ff671bc | ||
|
|
5b8fb95ca3 | ||
|
|
9ada6fdf12 | ||
|
|
b0b427d52f | ||
|
|
0a93f2f5be | ||
|
|
1de1c446bf | ||
|
|
16d264a310 | ||
|
|
1dc98594b3 | ||
|
|
e436a08992 | ||
|
|
75cde1582a | ||
|
|
2bef6ba8d9 | ||
|
|
437b1870cc | ||
|
|
2acf5409f8 | ||
|
|
0d894f0870 | ||
|
|
f8d7170ef4 | ||
|
|
d970614050 | ||
|
|
503a033f4a | ||
|
|
8e64b4303b | ||
|
|
3249537c32 | ||
|
|
dd7082cfe3 | ||
|
|
5568d95611 | ||
|
|
3c7308e1e3 | ||
|
|
08239d0545 | ||
|
|
660f4c287e | ||
|
|
779136b849 | ||
|
|
0c5ce444d7 | ||
|
|
907e9d8118 | ||
|
|
c9db613fce | ||
|
|
73904748dc | ||
|
|
40cb100aa4 | ||
|
|
6b7c32c45e | ||
|
|
e6b5804ee1 | ||
|
|
f219785672 | ||
|
|
87262f28a1 | ||
|
|
dd8f44d9e0 | ||
|
|
edee0fa2c0 | ||
|
|
fa3bc45740 | ||
|
|
69c6b19130 | ||
|
|
445300bbc6 | ||
|
|
d57a631bdc | ||
|
|
2169fa7066 | ||
|
|
7b4f4f5e38 | ||
|
|
46ecfc67a8 | ||
|
|
063e15b4d1 | ||
|
|
eff67f5f78 | ||
|
|
45a37f0bfd | ||
|
|
4422472369 | ||
|
|
e5b030e66b | ||
|
|
97dcad9699 | ||
|
|
01f6429e21 | ||
|
|
29e291e74b | ||
|
|
94f3c26bb6 | ||
|
|
7caef13745 | ||
|
|
063adad3cf | ||
|
|
05c231f81d | ||
|
|
de12a30676 | ||
|
|
73653a12a4 | ||
|
|
395917aada | ||
|
|
e93e6442aa | ||
|
|
237511a26b | ||
|
|
fb411f67b8 | ||
|
|
41c2b21211 | ||
|
|
1599ebac93 | ||
|
|
f52ee8216e | ||
|
|
73cdd9ca0c | ||
|
|
73a0026f5d | ||
|
|
47fe3b74db | ||
|
|
f8afff957a | ||
|
|
da5c7028c4 | ||
|
|
ddbc043c1b | ||
|
|
14bc533241 | ||
|
|
0c7d839e0b | ||
|
|
58031512a9 | ||
|
|
1172cc928e | ||
|
|
65f39025a8 | ||
|
|
4f494c037c | ||
|
|
d4aa70d4c0 | ||
|
|
6e168cc25e | ||
|
|
35991a06a0 | ||
|
|
50543349b4 | ||
|
|
00e0ea4a5b | ||
|
|
e804718f2d | ||
|
|
266da332cd | ||
|
|
bd65081400 | ||
|
|
ea6ea13a87 | ||
|
|
ea895c7e4e | ||
|
|
7e457f7c85 | ||
|
|
db3ff5c1eb | ||
|
|
b2ffab917f | ||
|
|
83a325be96 | ||
|
|
af8a156cc2 | ||
|
|
cda43ae9ae | ||
|
|
b11e480862 | ||
|
|
1c5138ccdd | ||
|
|
c006aedf93 | ||
|
|
f06b6e729c | ||
|
|
2bf380ec27 | ||
|
|
6d37992f6f | ||
|
|
ee56fb8ef5 | ||
|
|
118c87c80f | ||
|
|
138224b138 | ||
|
|
633bcf1936 | ||
|
|
414bfa4864 | ||
|
|
126f70ef0b | ||
|
|
349c31e4be | ||
|
|
8b99173e2f | ||
|
|
7f18246934 | ||
|
|
5cab49bf34 | ||
|
|
4c0aba7764 | ||
|
|
20f83fbb18 | ||
|
|
6c1bec71a0 | ||
|
|
2e23307cfd | ||
|
|
7f3d74b83d | ||
|
|
b58200a858 | ||
|
|
e0b40bb755 | ||
|
|
70344da3c1 | ||
|
|
28eac7018d | ||
|
|
62d7dc4060 | ||
|
|
06b1747c94 | ||
|
|
6ffec23867 | ||
|
|
70bdb203ef | ||
|
|
e80250a7ec | ||
|
|
49eec7eec9 | ||
|
|
42e32959ef | ||
|
|
0723bdfc3e | ||
|
|
512e9bf560 | ||
|
|
2dc44d5d81 | ||
|
|
5fa7bea59b | ||
|
|
a6055db0a1 | ||
|
|
76f06a5079 | ||
|
|
f59da75486 | ||
|
|
1d5755a47e | ||
|
|
b692e6d7ee | ||
|
|
4720b49f24 | ||
|
|
f5a8b11574 | ||
|
|
f7f2c7014b | ||
|
|
02f5c6520e | ||
|
|
8afe7117e7 | ||
|
|
6135b49e29 | ||
|
|
ada84b3298 | ||
|
|
7c6fb390df | ||
|
|
bc5018ec16 | ||
|
|
284fe3b3af | ||
|
|
f879c028cb | ||
|
|
a9ecb0c114 | ||
|
|
d94dcc623b | ||
|
|
f0ea685edd | ||
|
|
133c9694f3 | ||
|
|
f55e3b3f37 | ||
|
|
467c3685fd | ||
|
|
63869fed42 | ||
|
|
85e65d7025 | ||
|
|
26fda91092 | ||
|
|
424b98ba19 | ||
|
|
cdd85dddec | ||
|
|
6202649b3b | ||
|
|
28cb27f01f | ||
|
|
99eda99314 | ||
|
|
852552a317 | ||
|
|
2e0033b995 | ||
|
|
f3b6010231 | ||
|
|
73ce67c895 | ||
|
|
d9a8918b85 | ||
|
|
abfc9c328e | ||
|
|
fcf78a4555 | ||
|
|
6cdc93adc5 | ||
|
|
084dec0e7b | ||
|
|
e24930f9b6 | ||
|
|
b01c83d8ba | ||
|
|
256057c80c | ||
|
|
9d13ced5ec | ||
|
|
a7603d5893 | ||
|
|
1f18959d76 | ||
|
|
de3d72c03e | ||
|
|
784a4d75f3 | ||
|
|
70d55f7fa2 | ||
|
|
2910ea5cdb | ||
|
|
e03210d324 | ||
|
|
38e2ddbdf4 | ||
|
|
8c9de189c5 | ||
|
|
933da017c7 | ||
|
|
ae8086d624 | ||
|
|
8ac845da3d | ||
|
|
3b7de7949e | ||
|
|
19211b29ba | ||
|
|
1fa551e525 | ||
|
|
5488358f5e | ||
|
|
7e4151a9f9 | ||
|
|
fd2b858d39 | ||
|
|
834f65080b | ||
|
|
5bed554061 | ||
|
|
42e6cecf05 | ||
|
|
e1fe1e9bf0 | ||
|
|
e2bb58898d | ||
|
|
f70c2911e7 | ||
|
|
2ef044b120 | ||
|
|
46954a73c3 | ||
|
|
c0eab67a94 | ||
|
|
426d5f68b3 | ||
|
|
726db5a47a | ||
|
|
664bc50587 | ||
|
|
c8e714a354 | ||
|
|
e9303368d1 | ||
|
|
9671601b41 | ||
|
|
5204ff2122 | ||
|
|
dc75e74ba5 | ||
|
|
868117a604 | ||
|
|
b01158e255 | ||
|
|
d1d39a2073 | ||
|
|
7728f28325 | ||
|
|
511fe6a3ad | ||
|
|
316aad663d | ||
|
|
f472c05360 | ||
|
|
88d39b6b65 | ||
|
|
8c0b64dc2d | ||
|
|
34ddc492b5 | ||
|
|
793f1ea4f4 | ||
|
|
a4662bb97e | ||
|
|
2525b9b8d5 | ||
|
|
d10fb805e1 | ||
|
|
0fc1c66aa9 | ||
|
|
255a1acd5c | ||
|
|
9b0a40cd16 | ||
|
|
6691b2b0c0 | ||
|
|
b16fac0b68 | ||
|
|
cc1a989b3a | ||
|
|
1e2fcf0428 | ||
|
|
ee9866a77d | ||
|
|
de6233751c | ||
|
|
85a5355fe3 | ||
|
|
e5d6bb0f2d | ||
|
|
f6f1c2a529 | ||
|
|
2ac8bbf481 | ||
|
|
b39426e79d | ||
|
|
77b856179e | ||
|
|
c4e9006a17 | ||
|
|
634a701c58 | ||
|
|
0cf2dd4875 | ||
|
|
170581741c | ||
|
|
0144d89bcb | ||
|
|
6c4b7e3eec | ||
|
|
10a61cac65 | ||
|
|
1a0ad8897c | ||
|
|
7fc7da70b2 | ||
|
|
6bdec1ac0a | ||
|
|
2376759217 | ||
|
|
c9d77f0994 | ||
|
|
d39a6106a7 | ||
|
|
ed434d90f8 | ||
|
|
ba0e8d7ed8 | ||
|
|
b1674ba4f9 | ||
|
|
d3666a8896 | ||
|
|
252649554a | ||
|
|
e1533840b8 | ||
|
|
2d519db022 | ||
|
|
ff509b09e3 | ||
|
|
794148e937 | ||
|
|
68fd63a69e | ||
|
|
a619d07b13 | ||
|
|
7a2707542f | ||
|
|
b9e1a8724d | ||
|
|
68633e712c | ||
|
|
8a5874c915 | ||
|
|
121f70dc94 | ||
|
|
ad06f2a639 | ||
|
|
b6da7a2050 | ||
|
|
bb3b1ba599 | ||
|
|
ea697eb50e | ||
|
|
7b4015430d | ||
|
|
1bfdd1d8c0 | ||
|
|
c7a53cd33e | ||
|
|
976ef75074 | ||
|
|
b23c9810de | ||
|
|
5ab8d39173 | ||
|
|
fec5979e2a | ||
|
|
edf0c6e0df | ||
|
|
41439563c4 | ||
|
|
5e5ef36a8e | ||
|
|
c09122e635 | ||
|
|
aa82a2fc79 | ||
|
|
bcb7741d19 | ||
|
|
58866dcebd | ||
|
|
09bf2161e9 | ||
|
|
6f40bf1fe2 | ||
|
|
04e7d5416b | ||
|
|
4dc0686a1f | ||
|
|
5a20e819d2 | ||
|
|
be98587238 | ||
|
|
d1f4283ae5 | ||
|
|
fccce81f9c | ||
|
|
0e821a0c1f | ||
|
|
a4f2334d09 | ||
|
|
b2c080aba3 | ||
|
|
6d5e976102 | ||
|
|
a874a29054 | ||
|
|
feaf48d463 | ||
|
|
ce74df3e8c | ||
|
|
3d078e8211 | ||
|
|
43f27ccecf | ||
|
|
4731c96418 | ||
|
|
e1c74199da | ||
|
|
e12c042e86 | ||
|
|
f630d6c05e | ||
|
|
5dba2fe582 | ||
|
|
fea2daff92 | ||
|
|
28314383db | ||
|
|
495227c371 | ||
|
|
232976be61 | ||
|
|
c8b99c2422 | ||
|
|
044181df46 | ||
|
|
990a226a96 | ||
|
|
238b35d5ec | ||
|
|
70df5c1471 | ||
|
|
94a5190281 | ||
|
|
81aefc93a4 | ||
|
|
3b90a8be48 | ||
|
|
bc8619386e | ||
|
|
34677a2e0a | ||
|
|
46ff1377e2 | ||
|
|
59501e62b4 | ||
|
|
fa8b332d39 | ||
|
|
1a0e910dd6 | ||
|
|
ce1befb3f6 | ||
|
|
edd4df2160 | ||
|
|
052fb0d672 | ||
|
|
b7b0b4c90e | ||
|
|
6ddae4e63e | ||
|
|
01c877d58f | ||
|
|
53963b9b70 | ||
|
|
c04b6bed97 | ||
|
|
3f7ebbd664 | ||
|
|
7361719af0 | ||
|
|
dc66f26c9f | ||
|
|
b14c41d999 | ||
|
|
9209bef96d | ||
|
|
f473a29cad | ||
|
|
1f0b6fae3c | ||
|
|
447ec66e02 | ||
|
|
d3a8ffa1b2 | ||
|
|
204c4d7e38 | ||
|
|
201d5c7c28 | ||
|
|
6c78ea88af | ||
|
|
6da579582a | ||
|
|
62a0cec76c | ||
|
|
f3e619ac0d | ||
|
|
86e6d2d813 | ||
|
|
3f928383ff | ||
|
|
1b5a7ad8cb | ||
|
|
b381f09fbb | ||
|
|
88374b9d89 | ||
|
|
2eb7c42ef6 | ||
|
|
c87163fbe4 | ||
|
|
e9c2b861e8 | ||
|
|
be2b07b476 | ||
|
|
e6e9ee8c00 | ||
|
|
fa1fc6bf68 | ||
|
|
21d9e67d3d | ||
|
|
aaaec24fee | ||
|
|
739fe4a80c | ||
|
|
8c4124d200 | ||
|
|
76c63e19da | ||
|
|
ace326f534 | ||
|
|
d439fcbe10 | ||
|
|
5891a8ba9c | ||
|
|
c574cb7c80 | ||
|
|
091de209c9 | ||
|
|
c369f5eabd | ||
|
|
bad91fef5a | ||
|
|
eec732af11 | ||
|
|
6ddef8a463 | ||
|
|
1de251545a | ||
|
|
af76018577 | ||
|
|
7c54b0d570 | ||
|
|
977644b1c4 | ||
|
|
d5da34a80b | ||
|
|
de3328fb33 | ||
|
|
391c776af6 | ||
|
|
8d2c24dd89 | ||
|
|
43b8598a0b | ||
|
|
5a96697651 | ||
|
|
02d0feb7df | ||
|
|
b5f9106e08 | ||
|
|
f93cd6712c | ||
|
|
6cd97b3669 | ||
|
|
4a13975fd1 | ||
|
|
97a949444d | ||
|
|
77e52fe6b0 | ||
|
|
60f9b4c28d | ||
|
|
2a091a2c69 | ||
|
|
62397de881 | ||
|
|
834b79b6b3 | ||
|
|
a83640a03c | ||
|
|
ec774f564b | ||
|
|
51a104851d | ||
|
|
af36b73f0f | ||
|
|
4e27e0c148 | ||
|
|
17de3961ec | ||
|
|
5ec79aa91e | ||
|
|
fd005ff6bd | ||
|
|
44525b4c00 | ||
|
|
c1a823ad97 | ||
|
|
2a3bfd0f48 | ||
|
|
4ecc47d56a | ||
|
|
9408be1597 | ||
|
|
a66547715c | ||
|
|
d6de3818d5 | ||
|
|
3b8fc6d50c | ||
|
|
67d9ba86a9 | ||
|
|
ea9281e5c7 | ||
|
|
9692462ba3 | ||
|
|
278be13d5c | ||
|
|
a50587eea4 | ||
|
|
b279e571bd | ||
|
|
4a3bd8a107 | ||
|
|
d81b8b7eba | ||
|
|
7e6c67aea2 | ||
|
|
9a44e6e916 | ||
|
|
c91976e40d | ||
|
|
04d9e88a88 | ||
|
|
bf532ecbf3 | ||
|
|
e9b479a6b6 | ||
|
|
1cacc175a5 | ||
|
|
4d25d37a04 | ||
|
|
814ebfcf9c | ||
|
|
cce3bda2c4 | ||
|
|
752172b953 | ||
|
|
da806c7a72 | ||
|
|
e7b2ffaa07 | ||
|
|
d1d0bdb690 | ||
|
|
aebb71c0a7 | ||
|
|
26d4e15b95 | ||
|
|
d749a37a94 | ||
|
|
eb73b82786 | ||
|
|
076df0c172 | ||
|
|
43e4bfc11b | ||
|
|
43319f41b9 | ||
|
|
d6e7855c71 | ||
|
|
96fbf6ca32 | ||
|
|
39e9b0e5c1 | ||
|
|
0804e7ee73 | ||
|
|
568184333d | ||
|
|
5caa3ec458 | ||
|
|
3c328a53eb | ||
|
|
2c62255f2d | ||
|
|
ed7e9a44e0 | ||
|
|
dd0f91b30b | ||
|
|
5c369b71ab | ||
|
|
8ac9d9c3bd | ||
|
|
c6b95cb147 | ||
|
|
4b7b2c4fd1 | ||
|
|
ea42e3a061 | ||
|
|
0bcd5b25a2 | ||
|
|
4b68aa828a | ||
|
|
ba8d872626 | ||
|
|
2ecc3150d2 | ||
|
|
5bc1041760 | ||
|
|
ed5ad08108 | ||
|
|
acc213a00a | ||
|
|
e6e18dee25 | ||
|
|
d9bd2d45ba | ||
|
|
1229986252 | ||
|
|
2925ff2bef | ||
|
|
41bd4c9503 | ||
|
|
b93cb9e902 | ||
|
|
6e5cf7117a | ||
|
|
6b5c60adb0 | ||
|
|
1b6fc2257f | ||
|
|
dd2160f477 | ||
|
|
a54d83c644 | ||
|
|
3cdc15c881 | ||
|
|
c901021fb1 | ||
|
|
5b8e902c4d | ||
|
|
cab9e2952c | ||
|
|
ac9dc8b527 | ||
|
|
9b3822d698 | ||
|
|
84930a3d2d | ||
|
|
1195b4311b | ||
|
|
f8d303b336 | ||
|
|
4a31b494f0 | ||
|
|
703a1d1973 | ||
|
|
e75da9cf2f | ||
|
|
f3bf577877 | ||
|
|
9ed9b1d1aa | ||
|
|
38fd60d94a | ||
|
|
246ac9634b | ||
|
|
afc5fed49b | ||
|
|
88b5826b8a | ||
|
|
d49a8c5927 | ||
|
|
f5f997cc54 | ||
|
|
2f6f85d000 | ||
|
|
f2b7ab25b0 | ||
|
|
f795e92af9 | ||
|
|
e46ec802f8 | ||
|
|
f2e802cdcd | ||
|
|
e02b7d7dab | ||
|
|
9881e80bfd | ||
|
|
a824931115 | ||
|
|
cc12dc0f23 | ||
|
|
13bd9c8b43 | ||
|
|
231937b397 | ||
|
|
54bdcf6c08 | ||
|
|
b754abce91 | ||
|
|
73473a8d30 | ||
|
|
1fcf059bc3 | ||
|
|
e36200f754 | ||
|
|
7811a01457 | ||
|
|
bfc74cf338 | ||
|
|
d78e250f06 | ||
|
|
9c90456f05 | ||
|
|
d973aa3819 | ||
|
|
8a08fe2806 | ||
|
|
6187bb12a9 | ||
|
|
4198f608fc | ||
|
|
f3bd84d2d9 | ||
|
|
7d8134f7ee | ||
|
|
b8e5bf5d47 | ||
|
|
fd7471e4b3 | ||
|
|
de32b3cb22 | ||
|
|
8e982c7ecb | ||
|
|
7fe0176aa4 | ||
|
|
ea0e154248 | ||
|
|
6dba1dff74 | ||
|
|
6e604a85da | ||
|
|
97f8928706 | ||
|
|
a7d1113dcb | ||
|
|
c37ffdb5fc | ||
|
|
621224b486 | ||
|
|
3537a9ed79 | ||
|
|
b67f68d8d3 | ||
|
|
068b0dcb39 |
@@ -1,4 +0,0 @@
|
||||
/.yarn/**
|
||||
/lib/**
|
||||
/coverage/**
|
||||
/node_modules/**
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"mocha": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/typescript", // this is needed to allow importing typescript files from JS
|
||||
"plugin:import/warnings",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2023,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"jest",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"import/no-unresolved": [
|
||||
"error", {
|
||||
"ignore": ["csv-parse/sync", "@octokit/openapi-types"]
|
||||
}
|
||||
],
|
||||
"jest/no-disabled-tests": 0
|
||||
}
|
||||
}
|
||||
17
.github/actions/macos-setup-qemu/action.yml
vendored
17
.github/actions/macos-setup-qemu/action.yml
vendored
@@ -1,17 +0,0 @@
|
||||
name: 'Setup QEMU on macOS'
|
||||
description: 'Set up QEMU on macOS runners'
|
||||
|
||||
# FIXME: Remove this composite once QEMU issue is fixed on macOS runners
|
||||
# https://github.com/docker/actions-toolkit/issues/455
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- run: |
|
||||
set -ex
|
||||
brew uninstall --ignore-dependencies qemu || true
|
||||
brew autoremove || true
|
||||
curl -o /tmp/qemu.rb https://raw.githubusercontent.com/Homebrew/homebrew-core/f1a9cf104a9a51779c7a532b658c490f69974839/Formula/q/qemu.rb
|
||||
brew install /tmp/qemu.rb
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
1652
.github/buildx-lab-releases.json
vendored
1652
.github/buildx-lab-releases.json
vendored
File diff suppressed because it is too large
Load Diff
2498
.github/buildx-releases.json
vendored
2498
.github/buildx-releases.json
vendored
File diff suppressed because it is too large
Load Diff
1305
.github/compose-lab-releases.json
vendored
Normal file
1305
.github/compose-lab-releases.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6210
.github/compose-releases.json
vendored
Normal file
6210
.github/compose-releases.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6826
.github/cosign-releases.json
vendored
Normal file
6826
.github/cosign-releases.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -1,6 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
open-pull-requests-limit: 20
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -8,6 +9,7 @@ updates:
|
||||
- "dependencies"
|
||||
- "bot"
|
||||
- package-ecosystem: "npm"
|
||||
open-pull-requests-limit: 20
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
366
.github/docker-releases.json
vendored
366
.github/docker-releases.json
vendored
@@ -1,8 +1,362 @@
|
||||
{
|
||||
"latest": {
|
||||
"id": 189756585,
|
||||
"tag_name": "v27.4.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.4.0",
|
||||
"id": 275290406,
|
||||
"tag_name": "docker-v29.1.4",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.4",
|
||||
"assets": []
|
||||
},
|
||||
"v29.1.4": {
|
||||
"id": 275290406,
|
||||
"tag_name": "docker-v29.1.4",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.4",
|
||||
"assets": []
|
||||
},
|
||||
"edge": {
|
||||
"id": 271147963,
|
||||
"tag_name": "docker-v29.2.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.2.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v29.2.0-rc.1": {
|
||||
"id": 271147963,
|
||||
"tag_name": "docker-v29.2.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.2.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v29.1.3": {
|
||||
"id": 269884470,
|
||||
"tag_name": "docker-v29.1.3",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.3",
|
||||
"assets": []
|
||||
},
|
||||
"v29.1.2": {
|
||||
"id": 266898070,
|
||||
"tag_name": "docker-v29.1.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.2",
|
||||
"assets": []
|
||||
},
|
||||
"v29.1.1": {
|
||||
"id": 265971746,
|
||||
"tag_name": "docker-v29.1.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.1",
|
||||
"assets": []
|
||||
},
|
||||
"v29.1.0": {
|
||||
"id": 265770897,
|
||||
"tag_name": "docker-v29.1.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.0",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.4": {
|
||||
"id": 264940208,
|
||||
"tag_name": "docker-v29.0.4",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.4",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.3": {
|
||||
"id": 264058657,
|
||||
"tag_name": "docker-v29.0.3",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.3",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.2": {
|
||||
"id": 262951416,
|
||||
"tag_name": "docker-v29.0.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.2",
|
||||
"assets": []
|
||||
},
|
||||
"v29.1.0-rc.1": {
|
||||
"id": 263125085,
|
||||
"tag_name": "docker-v29.1.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.1.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.1": {
|
||||
"id": 262245944,
|
||||
"tag_name": "docker-v29.0.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.1",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.0": {
|
||||
"id": 261265152,
|
||||
"tag_name": "docker-v29.0.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.0",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.0-rc.3": {
|
||||
"id": 260452080,
|
||||
"tag_name": "docker-v29.0.0-rc.3",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.0-rc.3",
|
||||
"assets": []
|
||||
},
|
||||
"v28.5.2": {
|
||||
"id": 259852183,
|
||||
"tag_name": "v28.5.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.5.2",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.0-rc.2": {
|
||||
"id": 258289954,
|
||||
"tag_name": "docker-v29.0.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v29.0.0-rc.1": {
|
||||
"id": 252020476,
|
||||
"tag_name": "docker-v29.0.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/docker-v29.0.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.5.1": {
|
||||
"id": 252833798,
|
||||
"tag_name": "v28.5.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.5.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.5.0": {
|
||||
"id": 251798390,
|
||||
"tag_name": "v28.5.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.5.0",
|
||||
"assets": []
|
||||
},
|
||||
"v28.5.0-rc.1": {
|
||||
"id": 249763924,
|
||||
"tag_name": "v28.5.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.5.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.4.0": {
|
||||
"id": 244504005,
|
||||
"tag_name": "v28.4.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.4.0",
|
||||
"assets": []
|
||||
},
|
||||
"v28.4.0-rc.2": {
|
||||
"id": 244065281,
|
||||
"tag_name": "v28.4.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.4.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.4.0-rc.1": {
|
||||
"id": 243821467,
|
||||
"tag_name": "v28.4.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.4.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v25.0.13": {
|
||||
"id": 244806783,
|
||||
"tag_name": "v25.0.13",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v25.0.13",
|
||||
"assets": []
|
||||
},
|
||||
"v28.3.3": {
|
||||
"id": 235196329,
|
||||
"tag_name": "v28.3.3",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.3.3",
|
||||
"assets": []
|
||||
},
|
||||
"v25.0.12": {
|
||||
"id": 232634573,
|
||||
"tag_name": "v25.0.12",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v25.0.12",
|
||||
"assets": []
|
||||
},
|
||||
"v28.3.2": {
|
||||
"id": 231184033,
|
||||
"tag_name": "v28.3.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.3.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.3.1": {
|
||||
"id": 229534501,
|
||||
"tag_name": "v28.3.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.3.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.3.0": {
|
||||
"id": 227302240,
|
||||
"tag_name": "v28.3.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.3.0",
|
||||
"assets": []
|
||||
},
|
||||
"v28.3.0-rc.2": {
|
||||
"id": 226745561,
|
||||
"tag_name": "v28.3.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.3.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v25.0.11": {
|
||||
"id": 226304708,
|
||||
"tag_name": "v25.0.11",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v25.0.11",
|
||||
"assets": []
|
||||
},
|
||||
"v28.3.0-rc.1": {
|
||||
"id": 225132759,
|
||||
"tag_name": "v28.3.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.3.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.2.2": {
|
||||
"id": 222034216,
|
||||
"tag_name": "v28.2.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.2.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.2.1": {
|
||||
"id": 221664376,
|
||||
"tag_name": "v28.2.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.2.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.2.0": {
|
||||
"id": 221225663,
|
||||
"tag_name": "v28.2.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.2.0",
|
||||
"assets": []
|
||||
},
|
||||
"v28.2.0-rc.2": {
|
||||
"id": 220155575,
|
||||
"tag_name": "v28.2.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.2.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.2.0-rc.1": {
|
||||
"id": 218898330,
|
||||
"tag_name": "v28.2.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.2.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v25.0.10": {
|
||||
"id": 218958962,
|
||||
"tag_name": "v25.0.10",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v25.0.10",
|
||||
"assets": []
|
||||
},
|
||||
"v25.0.9": {
|
||||
"id": 218957753,
|
||||
"tag_name": "v25.0.9",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v25.0.9",
|
||||
"assets": []
|
||||
},
|
||||
"v23.0.18": {
|
||||
"id": 218962082,
|
||||
"tag_name": "v23.0.18",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v23.0.18",
|
||||
"assets": []
|
||||
},
|
||||
"v23.0.17": {
|
||||
"id": 218961915,
|
||||
"tag_name": "v23.0.17",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v23.0.17",
|
||||
"assets": []
|
||||
},
|
||||
"v28.1.1": {
|
||||
"id": 213296967,
|
||||
"tag_name": "v28.1.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.1.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.1.0": {
|
||||
"id": 213053128,
|
||||
"tag_name": "v28.1.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.1.0",
|
||||
"assets": []
|
||||
},
|
||||
"v28.1.0-rc.2": {
|
||||
"id": 212786864,
|
||||
"tag_name": "v28.1.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.1.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.1.0-rc.1": {
|
||||
"id": 211865941,
|
||||
"tag_name": "v28.1.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.1.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.4": {
|
||||
"id": 208163246,
|
||||
"tag_name": "v28.0.4",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.4",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.3": {
|
||||
"id": 208121902,
|
||||
"tag_name": "v28.0.3",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.3",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.2": {
|
||||
"id": 205678192,
|
||||
"tag_name": "v28.0.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.1": {
|
||||
"id": 202550735,
|
||||
"tag_name": "v28.0.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.1",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.0": {
|
||||
"id": 201152110,
|
||||
"tag_name": "v28.0.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.0",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.0-rc.3": {
|
||||
"id": 201046359,
|
||||
"tag_name": "v28.0.0-rc.3",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.0-rc.3",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.0-rc.2": {
|
||||
"id": 200732563,
|
||||
"tag_name": "v28.0.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v28.0.0-rc.1": {
|
||||
"id": 198950838,
|
||||
"tag_name": "v28.0.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v28.0.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v25.0.8": {
|
||||
"id": 198023936,
|
||||
"tag_name": "v25.0.8",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v25.0.8",
|
||||
"assets": []
|
||||
},
|
||||
"v27.5.1": {
|
||||
"id": 196137348,
|
||||
"tag_name": "v27.5.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.5.1",
|
||||
"assets": []
|
||||
},
|
||||
"v27.5.0": {
|
||||
"id": 194138446,
|
||||
"tag_name": "v27.5.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.5.0",
|
||||
"assets": []
|
||||
},
|
||||
"v27.5.0-rc.2": {
|
||||
"id": 193567140,
|
||||
"tag_name": "v27.5.0-rc.2",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.5.0-rc.2",
|
||||
"assets": []
|
||||
},
|
||||
"v27.5.0-rc.1": {
|
||||
"id": 192090825,
|
||||
"tag_name": "v27.5.0-rc.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.5.0-rc.1",
|
||||
"assets": []
|
||||
},
|
||||
"v27.4.1": {
|
||||
"id": 190678909,
|
||||
"tag_name": "v27.4.1",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.4.1",
|
||||
"assets": []
|
||||
},
|
||||
"v27.4.0": {
|
||||
@@ -23,12 +377,6 @@
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v23.0.16",
|
||||
"assets": []
|
||||
},
|
||||
"edge": {
|
||||
"id": 189756585,
|
||||
"tag_name": "v27.4.0",
|
||||
"html_url": "https://github.com/moby/moby/releases/tag/v27.4.0",
|
||||
"assets": []
|
||||
},
|
||||
"v27.4.0-rc.4": {
|
||||
"id": 189120203,
|
||||
"tag_name": "v27.4.0-rc.4",
|
||||
|
||||
1268
.github/regclient-releases.json
vendored
Normal file
1268
.github/regclient-releases.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
292
.github/undock-releases.json
vendored
292
.github/undock-releases.json
vendored
@@ -1,46 +1,178 @@
|
||||
{
|
||||
"latest": {
|
||||
"id": 162880608,
|
||||
"tag_name": "v0.8.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.8.0",
|
||||
"id": 273439938,
|
||||
"tag_name": "v0.11.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.11.0",
|
||||
"assets": [
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_arm64.zip"
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.zip"
|
||||
]
|
||||
},
|
||||
"v0.11.0": {
|
||||
"id": 273439938,
|
||||
"tag_name": "v0.11.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.11.0",
|
||||
"assets": [
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.zip"
|
||||
]
|
||||
},
|
||||
"v0.10.0": {
|
||||
"id": 213293369,
|
||||
"tag_name": "v0.10.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.10.0",
|
||||
"assets": [
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.10.0/undock_0.10.0_windows_arm64.zip"
|
||||
]
|
||||
},
|
||||
"v0.9.0": {
|
||||
"id": 192171889,
|
||||
"tag_name": "v0.9.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.9.0",
|
||||
"assets": [
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.9.0/undock_0.9.0_windows_arm64.zip"
|
||||
]
|
||||
},
|
||||
"v0.8.0": {
|
||||
@@ -109,47 +241,47 @@
|
||||
]
|
||||
},
|
||||
"edge": {
|
||||
"id": 162880608,
|
||||
"tag_name": "v0.8.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.8.0",
|
||||
"id": 273439938,
|
||||
"tag_name": "v0.11.0",
|
||||
"html_url": "https://github.com/crazy-max/undock/releases/tag/v0.11.0",
|
||||
"assets": [
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.8.0/undock_0.8.0_windows_arm64.zip"
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/checksums.txt",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_darwin_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_amd64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_arm64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv5.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv6.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_armv7.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_ppc64le.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_riscv64.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_linux_s390x.tar.gz",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_amd64.zip",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.provenance.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.sbom.json",
|
||||
"https://github.com/crazy-max/undock/releases/download/v0.11.0/undock_0.11.0_windows_arm64.zip"
|
||||
]
|
||||
},
|
||||
"v0.7.0-rc.1": {
|
||||
|
||||
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -19,15 +19,13 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node_version:
|
||||
- 24
|
||||
- 20
|
||||
- 18
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v5
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: build
|
||||
env:
|
||||
|
||||
10
.github/workflows/buildx-lab-releases-json.yml
vendored
10
.github/workflows/buildx-lab-releases-json.yml
vendored
@@ -17,7 +17,7 @@ on:
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@7f83a5a887650a38e4d0e05d5262309cfaa31459
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: docker/buildx-desktop
|
||||
artifact_name: buildx-lab-releases-json
|
||||
@@ -25,17 +25,17 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: buildx-lab-releases-json
|
||||
path: .github
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/buildx-lab-releases-json
|
||||
|
||||
10
.github/workflows/buildx-releases-json.yml
vendored
10
.github/workflows/buildx-releases-json.yml
vendored
@@ -17,7 +17,7 @@ on:
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@7f83a5a887650a38e4d0e05d5262309cfaa31459
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: docker/buildx
|
||||
artifact_name: buildx-releases-json
|
||||
@@ -25,17 +25,17 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: buildx-releases-json
|
||||
path: .github
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/buildx-releases-json
|
||||
|
||||
10
.github/workflows/codeql.yml
vendored
10
.github/workflows/codeql.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Enable corepack
|
||||
run: |
|
||||
@@ -28,19 +28,19 @@ jobs:
|
||||
yarn --version
|
||||
-
|
||||
name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
-
|
||||
name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: javascript-typescript
|
||||
-
|
||||
name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
-
|
||||
name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:javascript-typescript"
|
||||
|
||||
58
.github/workflows/compose-lab-releases-json.yml
vendored
Normal file
58
.github/workflows/compose-lab-releases-json.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: compose-lab-releases-json
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 */12 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/compose-lab-releases-json.yml'
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: docker/compose-desktop
|
||||
artifact_name: compose-lab-releases-json
|
||||
filename: compose-lab-releases.json
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: compose-lab-releases-json
|
||||
path: .github
|
||||
-
|
||||
name: Commit changes
|
||||
run: |
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/compose-lab-releases-json
|
||||
commit-message: "github: update .github/compose-lab-releases.json"
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
title: "Update `.github/compose-lab-releases.json`"
|
||||
body: |
|
||||
Update `.github/compose-lab-releases.json` to keep in sync with [https://github.com/docker/compose-desktop](https://github.com/docker/compose-desktop).
|
||||
draft: false
|
||||
58
.github/workflows/compose-releases-json.yml
vendored
Normal file
58
.github/workflows/compose-releases-json.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: compose-releases-json
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 */12 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/compose-releases-json.yml'
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: docker/compose
|
||||
artifact_name: compose-releases-json
|
||||
filename: compose-releases.json
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: compose-releases-json
|
||||
path: .github
|
||||
-
|
||||
name: Commit changes
|
||||
run: |
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/compose-releases-json
|
||||
commit-message: "github: update .github/compose-releases.json"
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
title: "Update `.github/compose-releases.json`"
|
||||
body: |
|
||||
Update `.github/compose-releases.json` to keep in sync with [https://github.com/docker/compose](https://github.com/docker/compose).
|
||||
draft: false
|
||||
58
.github/workflows/cosign-releases-json.yml
vendored
Normal file
58
.github/workflows/cosign-releases-json.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: cosign-releases-json
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 */12 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/cosign-releases-json.yml'
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: sigstore/cosign
|
||||
artifact_name: cosign-releases-json
|
||||
filename: cosign-releases.json
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: cosign-releases-json
|
||||
path: .github
|
||||
-
|
||||
name: Commit changes
|
||||
run: |
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/cosign-releases-json
|
||||
commit-message: "github: update .github/cosign-releases.json"
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
title: "Update `.github/cosign-releases.json`"
|
||||
body: |
|
||||
Update `.github/cosign-releases.json` to keep in sync with [https://github.com/sigstore/cosign](https://github.com/sigstore/cosign).
|
||||
draft: false
|
||||
13
.github/workflows/docker-releases-json.yml
vendored
13
.github/workflows/docker-releases-json.yml
vendored
@@ -17,25 +17,28 @@ on:
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@7f83a5a887650a38e4d0e05d5262309cfaa31459
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: moby/moby
|
||||
artifact_name: docker-releases-json
|
||||
filename: docker-releases.json
|
||||
tag_patterns: |
|
||||
^docker-(.*)$
|
||||
^(v.*)$
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: docker-releases-json
|
||||
path: .github
|
||||
@@ -45,7 +48,7 @@ jobs:
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/docker-releases-json
|
||||
|
||||
17
.github/workflows/pr-assign-author.yml
vendored
Normal file
17
.github/workflows/pr-assign-author.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: pr-assign-author
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: crazy-max/.github/.github/workflows/pr-assign-author.yml@1b673f36fad86812f538c1df9794904038a23cbf
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
45
.github/workflows/publish.yml
vendored
45
.github/workflows/publish.yml
vendored
@@ -1,5 +1,9 @@
|
||||
name: publish
|
||||
|
||||
permissions:
|
||||
id-token: write # required for OIDC
|
||||
contents: write # required to create GitHub Release
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
@@ -9,20 +13,49 @@ on:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
NODE_VERSION: "24" # at least Node 24 is required for Trusted Publishing with OIDC
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
name: Enable corepack
|
||||
run: |
|
||||
corepack enable
|
||||
yarn --version
|
||||
-
|
||||
name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'yarn'
|
||||
package-manager-cache: false
|
||||
-
|
||||
name: Print versions
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
yarn --version
|
||||
-
|
||||
name: Build
|
||||
run: |
|
||||
yarn install
|
||||
yarn run build
|
||||
-
|
||||
name: Publish
|
||||
uses: docker/bake-action@v5
|
||||
run: |
|
||||
npm version --no-git-tag-version ${GITHUB_REF#refs/tags/v}
|
||||
npm publish --provenance --access public
|
||||
-
|
||||
name: Create Release
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||
with:
|
||||
targets: publish
|
||||
draft: true
|
||||
generate_release_notes: true
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
58
.github/workflows/regclient-releases-json.yml
vendored
Normal file
58
.github/workflows/regclient-releases-json.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: regclient-releases-json
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 */12 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/regclient-releases-json.yml'
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: regclient/regclient
|
||||
artifact_name: regclient-releases-json
|
||||
filename: regclient-releases.json
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: regclient-releases-json
|
||||
path: .github
|
||||
-
|
||||
name: Commit changes
|
||||
run: |
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/regclient-releases-json
|
||||
commit-message: "github: update .github/regclient-releases.json"
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
title: "Update `.github/regclient-releases.json`"
|
||||
body: |
|
||||
Update `.github/regclient-releases.json` to keep in sync with [https://github.com/regclient/regclient](https://github.com/regclient/regclient).
|
||||
draft: false
|
||||
52
.github/workflows/test.yml
vendored
52
.github/workflows/test.yml
vendored
@@ -15,26 +15,31 @@ on:
|
||||
|
||||
env:
|
||||
NODE_VERSION: "20"
|
||||
BUILDX_VERSION: "v0.19.1"
|
||||
BUILDKIT_IMAGE: "moby/buildkit:v0.18.1"
|
||||
BUILDX_VERSION: "edge"
|
||||
BUILDKIT_IMAGE: "moby/buildkit:v0.26.3"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- ubuntu-24.04-arm
|
||||
node_version:
|
||||
- 24
|
||||
- 20
|
||||
- 18
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v5
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: .
|
||||
targets: test-coverage
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -64,7 +69,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Enable corepack
|
||||
run: |
|
||||
@@ -72,7 +77,7 @@ jobs:
|
||||
yarn --version
|
||||
-
|
||||
name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'yarn'
|
||||
@@ -82,7 +87,7 @@ jobs:
|
||||
-
|
||||
name: Create includes
|
||||
id: set
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
let tests = [];
|
||||
@@ -101,19 +106,24 @@ jobs:
|
||||
});
|
||||
await core.group(`Set includes`, async () => {
|
||||
let includes = [];
|
||||
for (const os of ['ubuntu-latest', 'macos-13', 'windows-latest']) {
|
||||
for (const os of ['ubuntu-latest', 'ubuntu-24.04-arm', 'macos-15-intel', 'windows-latest']) {
|
||||
for (const test of tests) {
|
||||
if (test === 'docker/install.test.itg.ts') {
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: '27.3.1' });
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: 'master' });
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: 'latest' });
|
||||
if (os !== 'windows-latest') {
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: '27.3.1' });
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: 'master' });
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'image', docker_install_version: 'latest' });
|
||||
}
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'archive', docker_install_version: 'v26.1.4' });
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'archive', docker_install_version: 'latest' });
|
||||
includes.push({ os: os, test: test, test_name: 'root', docker_install_type: 'archive', docker_install_version: 'v29.0.0-rc.1', docker_install_channel: 'test' });
|
||||
if (os === 'ubuntu-latest') {
|
||||
includes.push({ os: os, test: test, test_name: 'rootless', docker_install_type: 'image', docker_install_version: 'latest' });
|
||||
includes.push({ os: os, test: test, test_name: 'rootless', docker_install_type: 'archive', docker_install_version: 'latest' });
|
||||
}
|
||||
includes.push({ os: os, test: test, test_name: 'tcp', docker_install_type: 'image', docker_install_version: 'latest' });
|
||||
if (os !== 'windows-latest') {
|
||||
includes.push({ os: os, test: test, test_name: 'tcp', docker_install_type: 'image', docker_install_version: 'latest' });
|
||||
}
|
||||
includes.push({ os: os, test: test, test_name: 'tcp', docker_install_type: 'archive', docker_install_version: 'latest' });
|
||||
} else {
|
||||
includes.push({ os: os, test: test });
|
||||
@@ -136,20 +146,25 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.prepare-itg.outputs.includes) }}
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # needed for signing with GitHub OIDC Token
|
||||
packages: write # needed for pushing to GitHub Container Registry
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Expose GitHub Runtime
|
||||
uses: crazy-max/ghaction-github-runtime@v3
|
||||
-
|
||||
# FIXME: Needs to setup node twice on Windows due to a bug with runner
|
||||
# FIXME: Needs to setup node twice on Windows: https://github.com/actions/setup-node/issues/1357#issuecomment-3254613964
|
||||
name: Setup Node
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
package-manager-cache: false
|
||||
-
|
||||
name: Enable corepack
|
||||
run: |
|
||||
@@ -157,7 +172,7 @@ jobs:
|
||||
yarn --version
|
||||
-
|
||||
name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'yarn'
|
||||
@@ -182,7 +197,7 @@ jobs:
|
||||
run: yarn install
|
||||
-
|
||||
name: Test
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const testName = `${{ matrix.test_name }}`;
|
||||
@@ -198,6 +213,7 @@ jobs:
|
||||
TEST_FOR_SUMMARY: ${{ secrets.TEST_FOR_SUMMARY }}
|
||||
DOCKER_INSTALL_TYPE: ${{ matrix.docker_install_type }}
|
||||
DOCKER_INSTALL_VERSION: ${{ matrix.docker_install_version }}
|
||||
DOCKER_INSTALL_CHANNEL: ${{ matrix.docker_install_channel }}
|
||||
-
|
||||
name: Check coverage
|
||||
run: |
|
||||
|
||||
10
.github/workflows/undock-releases-json.yml
vendored
10
.github/workflows/undock-releases-json.yml
vendored
@@ -17,7 +17,7 @@ on:
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@7f83a5a887650a38e4d0e05d5262309cfaa31459
|
||||
uses: crazy-max/.github/.github/workflows/releases-json.yml@2842b806167c9dbacf5f972e0fcf47204a99d987
|
||||
with:
|
||||
repository: crazy-max/undock
|
||||
artifact_name: undock-releases-json
|
||||
@@ -25,17 +25,17 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
open-pr:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.event_name != 'pull_request'
|
||||
needs:
|
||||
- generate
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Download
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: undock-releases-json
|
||||
path: .github
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
git add -A .
|
||||
-
|
||||
name: Create PR
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
|
||||
with:
|
||||
base: main
|
||||
branch: bot/undock-releases-json
|
||||
|
||||
11
.github/workflows/validate.yml
vendored
11
.github/workflows/validate.yml
vendored
@@ -15,17 +15,17 @@ on:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
targets: ${{ steps.generate.outputs.targets }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: List targets
|
||||
id: generate
|
||||
uses: docker/bake-action/subaction/list-targets@v5
|
||||
uses: docker/bake-action/subaction/list-targets@v6
|
||||
with:
|
||||
target: validate
|
||||
|
||||
@@ -38,11 +38,8 @@ jobs:
|
||||
matrix:
|
||||
target: ${{ fromJson(needs.prepare.outputs.targets) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v5
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
3
.github/workflows/virtual-env.yml
vendored
3
.github/workflows/virtual-env.yml
vendored
@@ -23,7 +23,8 @@ jobs:
|
||||
- ubuntu-latest
|
||||
- ubuntu-24.04
|
||||
- ubuntu-22.04
|
||||
- ubuntu-20.04
|
||||
- ubuntu-24.04-arm
|
||||
- ubuntu-22.04-arm
|
||||
steps:
|
||||
-
|
||||
name: File system
|
||||
|
||||
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
File diff suppressed because one or more lines are too long
12
.yarnrc.yml
12
.yarnrc.yml
@@ -1,3 +1,9 @@
|
||||
# https://yarnpkg.com/configuration/yarnrc
|
||||
|
||||
compressionLevel: mixed
|
||||
enableGlobalCache: false
|
||||
enableHardenedMode: true
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
@@ -5,11 +11,9 @@ logFilters:
|
||||
level: discard
|
||||
- code: YN0076
|
||||
level: discard
|
||||
- code: YN0086
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
npmAuthToken: "${NODE_AUTH_TOKEN:-fallback}"
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
||||
|
||||
@@ -25,6 +25,7 @@ a library by most of our GitHub Actions:
|
||||
* [docker/login-action](https://github.com/docker/login-action)
|
||||
* [docker/metadata-action](https://github.com/docker/metadata-action)
|
||||
* [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action)
|
||||
* [docker/setup-compose-action](https://github.com/docker/setup-compose-action)
|
||||
* [docker/setup-docker-action](https://github.com/docker/setup-docker-action)
|
||||
* [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action)
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
"linux/amd64"
|
||||
],
|
||||
"output": [
|
||||
"type=docker"
|
||||
{
|
||||
"type": "docker"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
"GO_VERSION": "1.20"
|
||||
},
|
||||
"output": [
|
||||
"type=cacheonly"
|
||||
{
|
||||
"type": "cacheonly"
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate-docs": {
|
||||
@@ -36,7 +38,9 @@
|
||||
},
|
||||
"target": "validate",
|
||||
"output": [
|
||||
"type=cacheonly"
|
||||
{
|
||||
"type": "cacheonly"
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate-vendor": {
|
||||
@@ -48,7 +52,9 @@
|
||||
},
|
||||
"target": "validate",
|
||||
"output": [
|
||||
"type=cacheonly"
|
||||
{
|
||||
"type": "cacheonly"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
68
__tests__/.fixtures/bake-03-default.json
Normal file
68
__tests__/.fixtures/bake-03-default.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"group": {
|
||||
"default": {
|
||||
"targets": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"default": {
|
||||
"context": ".",
|
||||
"dockerfile": "Dockerfile",
|
||||
"attest": [
|
||||
{
|
||||
"mode": "max",
|
||||
"type": "provenance"
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"type": "sbom"
|
||||
}
|
||||
],
|
||||
"cache-from": [
|
||||
{
|
||||
"scope": "build",
|
||||
"type": "gha"
|
||||
},
|
||||
{
|
||||
"ref": "user/repo:cache",
|
||||
"type": "registry"
|
||||
}
|
||||
],
|
||||
"cache-to": [
|
||||
{
|
||||
"mode": "max",
|
||||
"scope": "build",
|
||||
"type": "gha"
|
||||
},
|
||||
{
|
||||
"type": "inline"
|
||||
}
|
||||
],
|
||||
"output": [
|
||||
{
|
||||
"dest": "./release-out",
|
||||
"type": "local"
|
||||
},
|
||||
{
|
||||
"ref": "user/app",
|
||||
"type": "registry"
|
||||
}
|
||||
],
|
||||
"secret": [
|
||||
{
|
||||
"env": "GITHUB_TOKEN",
|
||||
"id": "GITHUB_TOKEN"
|
||||
},
|
||||
{
|
||||
"id": "aws",
|
||||
"src": "__tests__/.fixtures/secret.txt"
|
||||
},
|
||||
{
|
||||
"id": "GITHUB_REPOSITORY"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
37
__tests__/.fixtures/bake-03.hcl
Normal file
37
__tests__/.fixtures/bake-03.hcl
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2024 actions-toolkit authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
target "default" {
|
||||
attest = [
|
||||
"type=provenance,mode=max",
|
||||
"type=sbom,disabled=true",
|
||||
]
|
||||
cache-from = [
|
||||
"type=gha,scope=build",
|
||||
"user/repo:cache",
|
||||
]
|
||||
cache-to = [
|
||||
"type=gha,scope=build,mode=max",
|
||||
"type=inline"
|
||||
]
|
||||
output = [
|
||||
"./release-out",
|
||||
"type=registry,ref=user/app"
|
||||
]
|
||||
secret = [
|
||||
"id=GITHUB_TOKEN,env=GITHUB_TOKEN",
|
||||
"id=aws,src=__tests__/.fixtures/secret.txt",
|
||||
"id=GITHUB_REPOSITORY"
|
||||
]
|
||||
}
|
||||
@@ -29,7 +29,10 @@
|
||||
"windows/arm64"
|
||||
],
|
||||
"output": [
|
||||
"./bin/build"
|
||||
{
|
||||
"dest": "./bin/build",
|
||||
"type": "local"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
300
__tests__/.fixtures/cosign/sign-output1.txt
Normal file
300
__tests__/.fixtures/cosign/sign-output1.txt
Normal file
File diff suppressed because one or more lines are too long
408
__tests__/.fixtures/cosign/sign-output2.txt
Normal file
408
__tests__/.fixtures/cosign/sign-output2.txt
Normal file
File diff suppressed because one or more lines are too long
329
__tests__/.fixtures/cosign/sign-output3.txt
Normal file
329
__tests__/.fixtures/cosign/sign-output3.txt
Normal file
File diff suppressed because one or more lines are too long
96
__tests__/.fixtures/cosign/verify-output-err1.txt
Normal file
96
__tests__/.fixtures/cosign/verify-output-err1.txt
Normal file
@@ -0,0 +1,96 @@
|
||||
2025/10/31 13:57:03 --> GET https://index.docker.io/v2/
|
||||
2025/10/31 13:57:03 GET /v2/ HTTP/1.1
|
||||
Host: index.docker.io
|
||||
User-Agent: cosign/v3.0.2 (linux; amd64) go-containerregistry/v0.20.6
|
||||
Accept-Encoding: gzip
|
||||
|
||||
|
||||
2025/10/31 13:57:03 <-- 401 https://index.docker.io/v2/ (191.948348ms)
|
||||
2025/10/31 13:57:03 HTTP/2.0 401 Unauthorized
|
||||
Content-Length: 87
|
||||
Content-Type: application/json
|
||||
Date: Fri, 31 Oct 2025 13:57:03 GMT
|
||||
Docker-Distribution-Api-Version: registry/2.0
|
||||
Strict-Transport-Security: max-age=31536000
|
||||
Www-Authenticate: ***"https://auth.docker.io/token",service="registry.docker.io"
|
||||
|
||||
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
|
||||
|
||||
2025/10/31 13:57:03 --> GET https://auth.docker.io/token?scope=repository%3Acrazymax%2Fgithub-builder-test%3Apull&service=registry.docker.io [body redacted: basic token response contains credentials]
|
||||
2025/10/31 13:57:03 GET /token?scope=repository%3Acrazymax%2Fgithub-builder-test%3Apull&service=registry.docker.io HTTP/1.1
|
||||
Host: auth.docker.io
|
||||
User-Agent: cosign/v3.0.2 (linux; amd64) go-containerregistry/v0.20.6
|
||||
Authorization: <redacted>
|
||||
Accept-Encoding: gzip
|
||||
|
||||
|
||||
2025/10/31 13:57:03 <-- 200 https://auth.docker.io/token?scope=repository%3Acrazymax%2Fgithub-builder-test%3Apull&service=registry.docker.io (180.01561ms) [body redacted: basic token response contains credentials]
|
||||
2025/10/31 13:57:03 HTTP/2.0 200 OK
|
||||
Connection: close
|
||||
Content-Type: application/json
|
||||
Date: Fri, 31 Oct 2025 13:57:03 GMT
|
||||
Strict-Transport-Security: max-age=31536000
|
||||
X-Trace-Id: 8d63fbce36baf5f2a0c5f2542efa7a7a
|
||||
X-Trace-Sampled: false
|
||||
|
||||
|
||||
2025/10/31 13:57:03 --> GET https://index.docker.io/v2/crazymax/github-builder-test/referrers/sha256:6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0
|
||||
2025/10/31 13:57:03 GET /v2/crazymax/github-builder-test/referrers/sha256:6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0 HTTP/1.1
|
||||
Host: index.docker.io
|
||||
User-Agent: cosign/v3.0.2 (linux; amd64) go-containerregistry/v0.20.6
|
||||
Accept: application/vnd.oci.image.index.v1+json
|
||||
Authorization: <redacted>
|
||||
Accept-Encoding: gzip
|
||||
|
||||
|
||||
2025/10/31 13:57:03 <-- 200 https://index.docker.io/v2/crazymax/github-builder-test/referrers/sha256:6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0 (84.160823ms)
|
||||
2025/10/31 13:57:03 HTTP/2.0 200 OK
|
||||
Content-Length: 89
|
||||
Content-Type: application/vnd.oci.image.index.v1+json
|
||||
Date: Fri, 31 Oct 2025 13:57:03 GMT
|
||||
Docker-Distribution-Api-Version: registry/2.0
|
||||
Strict-Transport-Security: max-age=31536000
|
||||
|
||||
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[]}
|
||||
|
||||
2025/10/31 13:57:03 --> GET https://index.docker.io/v2/crazymax/github-builder-test/referrers/sha256:6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0
|
||||
2025/10/31 13:57:03 GET /v2/crazymax/github-builder-test/referrers/sha256:6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0 HTTP/1.1
|
||||
Host: index.docker.io
|
||||
User-Agent: cosign/v3.0.2 (linux; amd64) go-containerregistry/v0.20.6
|
||||
Accept: application/vnd.oci.image.index.v1+json
|
||||
Authorization: <redacted>
|
||||
Accept-Encoding: gzip
|
||||
|
||||
|
||||
2025/10/31 13:57:03 <-- 200 https://index.docker.io/v2/crazymax/github-builder-test/referrers/sha256:6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0 (95.303988ms)
|
||||
2025/10/31 13:57:03 HTTP/2.0 200 OK
|
||||
Content-Length: 89
|
||||
Content-Type: application/vnd.oci.image.index.v1+json
|
||||
Date: Fri, 31 Oct 2025 13:57:03 GMT
|
||||
Docker-Distribution-Api-Version: registry/2.0
|
||||
Strict-Transport-Security: max-age=31536000
|
||||
|
||||
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[]}
|
||||
|
||||
2025/10/31 13:57:03 --> GET https://index.docker.io/v2/crazymax/github-builder-test/manifests/sha256-6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0.sig
|
||||
2025/10/31 13:57:03 GET /v2/crazymax/github-builder-test/manifests/sha256-6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0.sig HTTP/1.1
|
||||
Host: index.docker.io
|
||||
User-Agent: cosign/v3.0.2 (linux; amd64) go-containerregistry/v0.20.6
|
||||
Accept: application/vnd.docker.distribution.manifest.v1+json,application/vnd.docker.distribution.manifest.v1+prettyjws,application/vnd.docker.distribution.manifest.v2+json,application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.index.v1+json
|
||||
Authorization: <redacted>
|
||||
Accept-Encoding: gzip
|
||||
|
||||
|
||||
2025/10/31 13:57:03 <-- 404 https://index.docker.io/v2/crazymax/github-builder-test/manifests/sha256-6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0.sig (66.155995ms)
|
||||
2025/10/31 13:57:03 HTTP/2.0 404 Not Found
|
||||
Content-Length: 169
|
||||
Content-Type: application/json
|
||||
Date: Fri, 31 Oct 2025 13:57:03 GMT
|
||||
Docker-Distribution-Api-Version: registry/2.0
|
||||
Docker-Ratelimit-Source: d2fd3209-1e2e-451f-b428-29c5bbf3b4b7
|
||||
Strict-Transport-Security: max-age=31536000
|
||||
|
||||
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown","detail":"unknown tag=sha256-6cc021c733ae2760b2493f449d9885b1606002962b51a9c4f0d0d1568b6dc5c0.sig"}]}
|
||||
|
||||
Error: no signatures found
|
||||
error during command execution: no signatures found
|
||||
74
__tests__/.fixtures/imagetools-01.json
Normal file
74
__tests__/.fixtures/imagetools-01.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"architecture": "amd64",
|
||||
"os": "linux",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:75654b8eeebd3beae97271a102f57cdeb794cc91e442648544963a7e951e9558",
|
||||
"sha256:6a1b167dc4f30367cc713f6d48710dff20eb913bfaf14d7df23cfbe8a235319c",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:cc4513cba548800cba786895e269f78eff73e7685e80b0447070f8c116652eea"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-x86_64.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:52.845698088Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
}
|
||||
447
__tests__/.fixtures/imagetools-02.json
Normal file
447
__tests__/.fixtures/imagetools-02.json
Normal file
@@ -0,0 +1,447 @@
|
||||
{
|
||||
"linux/amd64": {
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"architecture": "amd64",
|
||||
"os": "linux",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:75654b8eeebd3beae97271a102f57cdeb794cc91e442648544963a7e951e9558",
|
||||
"sha256:6a1b167dc4f30367cc713f6d48710dff20eb913bfaf14d7df23cfbe8a235319c",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:cc4513cba548800cba786895e269f78eff73e7685e80b0447070f8c116652eea"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-x86_64.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:52.845698088Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.698098711Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux/arm/v7": {
|
||||
"created": "2024-12-16T23:44:35.805758197Z",
|
||||
"architecture": "arm",
|
||||
"os": "linux",
|
||||
"variant": "v7",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:0cee9b6e126689480f812b337d8926e8b051e2c1e40b3e36701ea2554f367b9d",
|
||||
"sha256:4cfff05f912cc67c6ff688b2f53f84e6d74fe415725a228115a296634d919fd3",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:e0962dfb9d203ce37963e41ec72119610633651f760570d20b0217db3632b5d5"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-armv7.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:36:02.690991835Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:35.805758197Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:35.805758197Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:35.805758197Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:35.805758197Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux/arm64": {
|
||||
"created": "2024-12-16T23:44:45.848423966Z",
|
||||
"architecture": "arm64",
|
||||
"os": "linux",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:651d9022c23486dfbd396c13db293af6845731cbd098a5f5606db4bc9f5573e8",
|
||||
"sha256:9c138da7f7ea7cc8190f71ce15f125e2eb79fd360f4cc2d34513dad016cb1096",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:9422ca7e65701d8eba4a5a31e325443dcbc753c2edef64e431c96702c94d2672"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-aarch64.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:36:03.586014466Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.848423966Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.848423966Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.848423966Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.848423966Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux/ppc64le": {
|
||||
"created": "2024-12-16T23:44:45.864267959Z",
|
||||
"architecture": "ppc64le",
|
||||
"os": "linux",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:fc80c1f6e8bee4861c27b2cee0f8edf887bd4d88d20063ba179f0caa93088770",
|
||||
"sha256:e9fbfe005c7e2cd7d4f3159f07f6fbe82dad25c7e868a1ee2dd6503830d468c4",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:86e0c30fb5e087f5cd324e082a0529c6326af1025f1a030fc1d2ac2979dec81c"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-ppc64le.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:36:03.82451378Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.864267959Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.864267959Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.864267959Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:45.864267959Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux/riscv64": {
|
||||
"created": "2024-12-16T23:44:51.369236518Z",
|
||||
"architecture": "riscv64",
|
||||
"os": "linux",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:f9a3c4be4be59ad69b98da83e848450a28193c63ecdb40736f854308873152f9",
|
||||
"sha256:231aa6f6a7db1c4ac8dc807a8bdd250f92be3ffac79ef9fec89ca8ac2f78e688",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:555c2f18bbe5d71e09387bdf745023055a8e5a6667905143c09a689e65f5ceff"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-riscv64.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:36:02.869897238Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:51.369236518Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:51.369236518Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:51.369236518Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:51.369236518Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux/s390x": {
|
||||
"created": "2024-12-16T23:44:38.777675109Z",
|
||||
"architecture": "s390x",
|
||||
"os": "linux",
|
||||
"config": {
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"BUILDKIT_SETUP_CGROUPV2_ROOT=1"
|
||||
],
|
||||
"Entrypoint": [
|
||||
"buildkitd"
|
||||
],
|
||||
"Volumes": {
|
||||
"/var/lib/buildkit": {}
|
||||
},
|
||||
"WorkingDir": "/",
|
||||
"ArgsEscaped": true
|
||||
},
|
||||
"rootfs": {
|
||||
"type": "layers",
|
||||
"diff_ids": [
|
||||
"sha256:a772154591ea8d876b24f25db93db4753a9f05c6500413a5ff966d581957655e",
|
||||
"sha256:920529bf8be4087e77ec129bbcd9f3c4a179ede2f35cac38c6f8517fc9e41b9b",
|
||||
"sha256:37453f29fa93eccde9d8ffa21c0b92c41a981c727ad6c32acee11caf4f5e42a8",
|
||||
"sha256:2b99eb6f0070abe514fde85b61fa4993f1edfb32365b2a246841521f24fc38c0"
|
||||
]
|
||||
},
|
||||
"history": [
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "ADD alpine-minirootfs-3.20.3-s390x.tar.gz / # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-09-06T12:05:36Z",
|
||||
"created_by": "CMD [\"/bin/sh\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:36:04.705568496Z",
|
||||
"created_by": "RUN /bin/sh -c apk add --no-cache fuse3 git openssh pigz xz iptables ip6tables \u0026\u0026 ln -s fusermount3 /usr/bin/fusermount # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:35:49.452745107Z",
|
||||
"created_by": "COPY examples/buildctl-daemonless/buildctl-daemonless.sh /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.777675109Z",
|
||||
"created_by": "VOLUME [/var/lib/buildkit]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.777675109Z",
|
||||
"created_by": "COPY / /usr/bin/ # buildkit",
|
||||
"comment": "buildkit.dockerfile.v0"
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.777675109Z",
|
||||
"created_by": "ENV BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
},
|
||||
{
|
||||
"created": "2024-12-16T23:44:38.777675109Z",
|
||||
"created_by": "ENTRYPOINT [\"buildkitd\"]",
|
||||
"comment": "buildkit.dockerfile.v0",
|
||||
"empty_layer": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
5
__tests__/.fixtures/imagetools-03.json
Normal file
5
__tests__/.fixtures/imagetools-03.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:dccc69dd895968c4f21aa9e43e715f25f0cedfce4b17f1014c88c307928e22fc",
|
||||
"size": 1599
|
||||
}
|
||||
141
__tests__/.fixtures/imagetools-04.json
Normal file
141
__tests__/.fixtures/imagetools-04.json
Normal file
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.oci.image.index.v1+json",
|
||||
"digest": "sha256:79cc6476ab1a3371c9afd8b44e7c55610057c43e18d9b39b68e2b0c2475cc1b6",
|
||||
"size": 4654,
|
||||
"manifests": [
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:dccc69dd895968c4f21aa9e43e715f25f0cedfce4b17f1014c88c307928e22fc",
|
||||
"size": 1599,
|
||||
"platform": {
|
||||
"architecture": "amd64",
|
||||
"os": "linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:1b6bce668653f08e2d0f9f7c9b646675b2cbce94ce8abdf4eb0eabaef4353045",
|
||||
"size": 1599,
|
||||
"platform": {
|
||||
"architecture": "arm",
|
||||
"os": "linux",
|
||||
"variant": "v7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:8f251fda6057e9dffc54f7874b249920f15f1813e9b1406a0cebeca5e4ab1ad9",
|
||||
"size": 1599,
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"os": "linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:d306cbc2d506547f136c8e0ea040b929743f298fb2813d9030efdb9d9eee4d51",
|
||||
"size": 1599,
|
||||
"platform": {
|
||||
"architecture": "s390x",
|
||||
"os": "linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:9d195ff2dc9ef347bb52ebb1c2a6e6587d4bd87019d2ea11df3e7046a3d19708",
|
||||
"size": 1599,
|
||||
"platform": {
|
||||
"architecture": "ppc64le",
|
||||
"os": "linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:72410c2c4529fca9339ebbcc8db2a1d5cb4d72d72c669f50b6d45d8a0f79fc22",
|
||||
"size": 1599,
|
||||
"platform": {
|
||||
"architecture": "riscv64",
|
||||
"os": "linux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:2ba4ad6eae1efcafee73a971953093c7c32b6938f2f9fd4998c8bf4d0fbe76f2",
|
||||
"size": 1113,
|
||||
"annotations": {
|
||||
"vnd.docker.reference.digest": "sha256:dccc69dd895968c4f21aa9e43e715f25f0cedfce4b17f1014c88c307928e22fc",
|
||||
"vnd.docker.reference.type": "attestation-manifest"
|
||||
},
|
||||
"platform": {
|
||||
"architecture": "unknown",
|
||||
"os": "unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:0709528fae1747ce17638ad2978ee7936b38a294136eaadaf692e415f64b1e03",
|
||||
"size": 1113,
|
||||
"annotations": {
|
||||
"vnd.docker.reference.digest": "sha256:1b6bce668653f08e2d0f9f7c9b646675b2cbce94ce8abdf4eb0eabaef4353045",
|
||||
"vnd.docker.reference.type": "attestation-manifest"
|
||||
},
|
||||
"platform": {
|
||||
"architecture": "unknown",
|
||||
"os": "unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:241b7159129d53923c89708bcc052b3398086a826519896be2f025545916e43e",
|
||||
"size": 1113,
|
||||
"annotations": {
|
||||
"vnd.docker.reference.digest": "sha256:8f251fda6057e9dffc54f7874b249920f15f1813e9b1406a0cebeca5e4ab1ad9",
|
||||
"vnd.docker.reference.type": "attestation-manifest"
|
||||
},
|
||||
"platform": {
|
||||
"architecture": "unknown",
|
||||
"os": "unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:97f4a222a7992dba6dc1a43991d0cca1fcffdc25593033c6a3a7ff14c8651cbf",
|
||||
"size": 1113,
|
||||
"annotations": {
|
||||
"vnd.docker.reference.digest": "sha256:d306cbc2d506547f136c8e0ea040b929743f298fb2813d9030efdb9d9eee4d51",
|
||||
"vnd.docker.reference.type": "attestation-manifest"
|
||||
},
|
||||
"platform": {
|
||||
"architecture": "unknown",
|
||||
"os": "unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:aa933713d8094b2708120e889acb6f7153dee4e0f3298ccd3e37a584cd0c260d",
|
||||
"size": 1113,
|
||||
"annotations": {
|
||||
"vnd.docker.reference.digest": "sha256:9d195ff2dc9ef347bb52ebb1c2a6e6587d4bd87019d2ea11df3e7046a3d19708",
|
||||
"vnd.docker.reference.type": "attestation-manifest"
|
||||
},
|
||||
"platform": {
|
||||
"architecture": "unknown",
|
||||
"os": "unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
"digest": "sha256:d95ca72d4f2a6bc416d4b2f3003b2af9d5f4dea99acec6ad3ab0c2082000a98c",
|
||||
"size": 1113,
|
||||
"annotations": {
|
||||
"vnd.docker.reference.digest": "sha256:72410c2c4529fca9339ebbcc8db2a1d5cb4d72d72c669f50b6d45d8a0f79fc22",
|
||||
"vnd.docker.reference.type": "attestation-manifest"
|
||||
},
|
||||
"platform": {
|
||||
"architecture": "unknown",
|
||||
"os": "unknown"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
80
__tests__/.fixtures/imagetools-05.json
Normal file
80
__tests__/.fixtures/imagetools-05.json
Normal file
@@ -0,0 +1,80 @@
|
||||
[
|
||||
{
|
||||
"mediaType":"application/vnd.oci.image.manifest.v1+json",
|
||||
"digest":"sha256:2ba4ad6eae1efcafee73a971953093c7c32b6938f2f9fd4998c8bf4d0fbe76f2",
|
||||
"size":1113,
|
||||
"annotations":{
|
||||
"vnd.docker.reference.digest":"sha256:dccc69dd895968c4f21aa9e43e715f25f0cedfce4b17f1014c88c307928e22fc",
|
||||
"vnd.docker.reference.type":"attestation-manifest"
|
||||
},
|
||||
"platform":{
|
||||
"architecture":"unknown",
|
||||
"os":"unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType":"application/vnd.oci.image.manifest.v1+json",
|
||||
"digest":"sha256:0709528fae1747ce17638ad2978ee7936b38a294136eaadaf692e415f64b1e03",
|
||||
"size":1113,
|
||||
"annotations":{
|
||||
"vnd.docker.reference.digest":"sha256:1b6bce668653f08e2d0f9f7c9b646675b2cbce94ce8abdf4eb0eabaef4353045",
|
||||
"vnd.docker.reference.type":"attestation-manifest"
|
||||
},
|
||||
"platform":{
|
||||
"architecture":"unknown",
|
||||
"os":"unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType":"application/vnd.oci.image.manifest.v1+json",
|
||||
"digest":"sha256:241b7159129d53923c89708bcc052b3398086a826519896be2f025545916e43e",
|
||||
"size":1113,
|
||||
"annotations":{
|
||||
"vnd.docker.reference.digest":"sha256:8f251fda6057e9dffc54f7874b249920f15f1813e9b1406a0cebeca5e4ab1ad9",
|
||||
"vnd.docker.reference.type":"attestation-manifest"
|
||||
},
|
||||
"platform":{
|
||||
"architecture":"unknown",
|
||||
"os":"unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType":"application/vnd.oci.image.manifest.v1+json",
|
||||
"digest":"sha256:97f4a222a7992dba6dc1a43991d0cca1fcffdc25593033c6a3a7ff14c8651cbf",
|
||||
"size":1113,
|
||||
"annotations":{
|
||||
"vnd.docker.reference.digest":"sha256:d306cbc2d506547f136c8e0ea040b929743f298fb2813d9030efdb9d9eee4d51",
|
||||
"vnd.docker.reference.type":"attestation-manifest"
|
||||
},
|
||||
"platform":{
|
||||
"architecture":"unknown",
|
||||
"os":"unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType":"application/vnd.oci.image.manifest.v1+json",
|
||||
"digest":"sha256:aa933713d8094b2708120e889acb6f7153dee4e0f3298ccd3e37a584cd0c260d",
|
||||
"size":1113,
|
||||
"annotations":{
|
||||
"vnd.docker.reference.digest":"sha256:9d195ff2dc9ef347bb52ebb1c2a6e6587d4bd87019d2ea11df3e7046a3d19708",
|
||||
"vnd.docker.reference.type":"attestation-manifest"
|
||||
},
|
||||
"platform":{
|
||||
"architecture":"unknown",
|
||||
"os":"unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mediaType":"application/vnd.oci.image.manifest.v1+json",
|
||||
"digest":"sha256:d95ca72d4f2a6bc416d4b2f3003b2af9d5f4dea99acec6ad3ab0c2082000a98c",
|
||||
"size":1113,
|
||||
"annotations":{
|
||||
"vnd.docker.reference.digest":"sha256:72410c2c4529fca9339ebbcc8db2a1d5cb4d72d72c669f50b6d45d8a0f79fc22",
|
||||
"vnd.docker.reference.type":"attestation-manifest"
|
||||
},
|
||||
"platform":{
|
||||
"architecture":"unknown",
|
||||
"os":"unknown"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -37,3 +37,15 @@ GC Policy rule#2:
|
||||
GC Policy rule#3:
|
||||
All: true
|
||||
Keep Bytes: 94.06GiB
|
||||
File#buildkitd.toml:
|
||||
> debug = true
|
||||
> insecure-entitlements = ["network.host", "security.insecure"]
|
||||
> trace = true
|
||||
>
|
||||
> [log]
|
||||
> format = "text"
|
||||
>
|
||||
File#foo.txt:
|
||||
> foo = bar
|
||||
> baz = qux
|
||||
>
|
||||
|
||||
55
__tests__/.fixtures/inspect12.txt
Normal file
55
__tests__/.fixtures/inspect12.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
Name: nvidia
|
||||
Driver: docker-container
|
||||
Last Activity: 2025-02-14 15:57:45 +0000 UTC
|
||||
|
||||
Nodes:
|
||||
Name: nvidia0
|
||||
Endpoint: unix:///var/run/docker.sock
|
||||
Driver Options: image="moby/buildkit:local"
|
||||
Status: running
|
||||
BuildKit daemon flags: --allow-insecure-entitlement=network.host
|
||||
BuildKit version: v0.20.0-rc2-4-gd30d8e22c.m
|
||||
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
|
||||
Features:
|
||||
Cache export: true
|
||||
Docker exporter: true
|
||||
Multi-platform build: true
|
||||
OCI exporter: true
|
||||
Labels:
|
||||
org.mobyproject.buildkit.worker.executor: oci
|
||||
org.mobyproject.buildkit.worker.hostname: 76ac9a510d96
|
||||
org.mobyproject.buildkit.worker.network: host
|
||||
org.mobyproject.buildkit.worker.oci.process-mode: sandbox
|
||||
org.mobyproject.buildkit.worker.selinux.enabled: false
|
||||
org.mobyproject.buildkit.worker.snapshotter: overlayfs
|
||||
Devices:
|
||||
Name: nvidia.com/gpu=all
|
||||
Automatically allowed: true
|
||||
Annotations:
|
||||
foo: bar
|
||||
org.mobyproject.buildkit.device.autoallow: true
|
||||
Name: docker.com/gpu=venus
|
||||
Automatically allowed: false
|
||||
Annotations:
|
||||
bar: baz
|
||||
GC Policy rule#0:
|
||||
All: false
|
||||
Filters: type==source.local,type==exec.cachemount,type==source.git.checkout
|
||||
Keep Duration: 48h0m0s
|
||||
Max Used Space: 488.3MiB
|
||||
GC Policy rule#1:
|
||||
All: false
|
||||
Keep Duration: 1440h0m0s
|
||||
Reserved Space: 9.313GiB
|
||||
Max Used Space: 93.13GiB
|
||||
Min Free Space: 188.1GiB
|
||||
GC Policy rule#2:
|
||||
All: false
|
||||
Reserved Space: 9.313GiB
|
||||
Max Used Space: 93.13GiB
|
||||
Min Free Space: 188.1GiB
|
||||
GC Policy rule#3:
|
||||
All: true
|
||||
Reserved Space: 9.313GiB
|
||||
Max Used Space: 93.13GiB
|
||||
Min Free Space: 188.1GiB
|
||||
1
__tests__/.fixtures/sigstore/multi/linux_amd64/hello.txt
Normal file
1
__tests__/.fixtures/sigstore/multi/linux_amd64/hello.txt
Normal file
@@ -0,0 +1 @@
|
||||
Hello, World! This is linux/amd64
|
||||
462
__tests__/.fixtures/sigstore/multi/linux_amd64/provenance.json
Normal file
462
__tests__/.fixtures/sigstore/multi/linux_amd64/provenance.json
Normal file
@@ -0,0 +1,462 @@
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v0.1",
|
||||
"predicateType": "https://slsa.dev/provenance/v1",
|
||||
"subject": [
|
||||
{
|
||||
"name": "hello.txt",
|
||||
"digest": {
|
||||
"sha256": "1b37929e66644beb58b3d28d44fba0d82aa90cab03c55a492adb81fe6e833ec8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"predicate": {
|
||||
"buildDefinition": {
|
||||
"buildType": "https://github.com/moby/buildkit/blob/master/docs/attestations/slsa-definitions.md",
|
||||
"resolvedDependencies": [
|
||||
{
|
||||
"uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1",
|
||||
"digest": {
|
||||
"sha256": "e930c2697be77cb7271d316ecfa78768b5eac73de3b16018ed38eb0ea0b5a7cb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
"digest": {
|
||||
"sha256": "4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
|
||||
}
|
||||
},
|
||||
{
|
||||
"uri": "https://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"digest": {
|
||||
"sha1": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
}
|
||||
}
|
||||
],
|
||||
"externalParameters": {
|
||||
"configSource": {
|
||||
"uri": "https://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"digest": {
|
||||
"sha1": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
},
|
||||
"path": "hello.Dockerfile"
|
||||
},
|
||||
"request": {
|
||||
"frontend": "dockerfile.v0",
|
||||
"secrets": [
|
||||
{
|
||||
"id": "GIT_AUTH_HEADER",
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"id": "GIT_AUTH_TOKEN",
|
||||
"optional": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"internalParameters": {
|
||||
"buildConfig": {
|
||||
"digestMapping": {
|
||||
"sha256:23dcbc3cce701a8a9bbb1e33f2ea88304527a4a935c89c4564af698095463ac2": "step3",
|
||||
"sha256:3192c1bd53f90cca959db778dcee30edc9a79f8cd3f9a2c54adc4606507fd3b6": "step0",
|
||||
"sha256:7f1c9e959980ea3e2cf4af8ef97b6c3797a0926752b436bff11474e436defe7f": "step1",
|
||||
"sha256:c8737331fb8e5f5bcb6b22320012d975057514982c788e63db13332a4219b984": "step2"
|
||||
},
|
||||
"llbDefinition": [
|
||||
{
|
||||
"id": "step0",
|
||||
"op": {
|
||||
"Op": {
|
||||
"source": {
|
||||
"identifier": "docker-image://docker.io/library/alpine:latest@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
|
||||
}
|
||||
},
|
||||
"constraints": {},
|
||||
"platform": {
|
||||
"Architecture": "amd64",
|
||||
"OS": "linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step1",
|
||||
"inputs": [
|
||||
"step0:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {
|
||||
"exec": {
|
||||
"meta": {
|
||||
"args": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"echo \"Hello, World! This is ${TARGETPLATFORM}\" \u003e /hello.txt"
|
||||
],
|
||||
"cwd": "/",
|
||||
"env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TARGETPLATFORM=linux/amd64"
|
||||
],
|
||||
"removeMountStubsRecursive": true
|
||||
},
|
||||
"mounts": [
|
||||
{
|
||||
"dest": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"constraints": {},
|
||||
"platform": {
|
||||
"Architecture": "amd64",
|
||||
"OS": "linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step2",
|
||||
"inputs": [
|
||||
"step1:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {
|
||||
"file": {
|
||||
"actions": [
|
||||
{
|
||||
"Action": {
|
||||
"copy": {
|
||||
"allowEmptyWildcard": true,
|
||||
"allowWildcard": true,
|
||||
"createDestPath": true,
|
||||
"dest": "/",
|
||||
"dirCopyContents": true,
|
||||
"followSymlink": true,
|
||||
"mode": -1,
|
||||
"src": "/hello.txt",
|
||||
"timestamp": -1
|
||||
}
|
||||
},
|
||||
"input": -1,
|
||||
"output": 0,
|
||||
"secondaryInput": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"constraints": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step3",
|
||||
"inputs": [
|
||||
"step2:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"builderPlatform": "linux/amd64",
|
||||
"github_actor": "crazy-max",
|
||||
"github_actor_id": "1951866",
|
||||
"github_event_name": "workflow_dispatch",
|
||||
"github_event_payload": {
|
||||
"enterprise": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/b/19176?v=4",
|
||||
"created_at": "2022-12-30T23:53:17Z",
|
||||
"description": null,
|
||||
"html_url": "https://github.com/enterprises/docker",
|
||||
"id": 19176,
|
||||
"name": "Docker",
|
||||
"node_id": "E_kgDNSug",
|
||||
"slug": "docker",
|
||||
"updated_at": "2025-10-20T20:39:05Z",
|
||||
"website_url": null
|
||||
},
|
||||
"inputs": null,
|
||||
"organization": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
|
||||
"description": "Docker helps developers bring their ideas to life by conquering the complexity of app development.",
|
||||
"events_url": "https://api.github.com/orgs/docker/events",
|
||||
"hooks_url": "https://api.github.com/orgs/docker/hooks",
|
||||
"id": 5429470,
|
||||
"issues_url": "https://api.github.com/orgs/docker/issues",
|
||||
"login": "docker",
|
||||
"members_url": "https://api.github.com/orgs/docker/members{/member}",
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
|
||||
"public_members_url": "https://api.github.com/orgs/docker/public_members{/member}",
|
||||
"repos_url": "https://api.github.com/orgs/docker/repos",
|
||||
"url": "https://api.github.com/orgs/docker"
|
||||
},
|
||||
"ref": "refs/heads/main",
|
||||
"repository": {
|
||||
"allow_forking": true,
|
||||
"archive_url": "https://api.github.com/repos/docker/github-builder-test/{archive_format}{/ref}",
|
||||
"archived": false,
|
||||
"assignees_url": "https://api.github.com/repos/docker/github-builder-test/assignees{/user}",
|
||||
"blobs_url": "https://api.github.com/repos/docker/github-builder-test/git/blobs{/sha}",
|
||||
"branches_url": "https://api.github.com/repos/docker/github-builder-test/branches{/branch}",
|
||||
"clone_url": "https://github.com/docker/github-builder-test.git",
|
||||
"collaborators_url": "https://api.github.com/repos/docker/github-builder-test/collaborators{/collaborator}",
|
||||
"comments_url": "https://api.github.com/repos/docker/github-builder-test/comments{/number}",
|
||||
"commits_url": "https://api.github.com/repos/docker/github-builder-test/commits{/sha}",
|
||||
"compare_url": "https://api.github.com/repos/docker/github-builder-test/compare/{base}...{head}",
|
||||
"contents_url": "https://api.github.com/repos/docker/github-builder-test/contents/{+path}",
|
||||
"contributors_url": "https://api.github.com/repos/docker/github-builder-test/contributors",
|
||||
"created_at": "2025-08-19T08:08:29Z",
|
||||
"custom_properties": {},
|
||||
"default_branch": "main",
|
||||
"deployments_url": "https://api.github.com/repos/docker/github-builder-test/deployments",
|
||||
"description": "Test repo for https://github.com/docker/github-builder-experimental",
|
||||
"disabled": false,
|
||||
"downloads_url": "https://api.github.com/repos/docker/github-builder-test/downloads",
|
||||
"events_url": "https://api.github.com/repos/docker/github-builder-test/events",
|
||||
"fork": false,
|
||||
"forks": 0,
|
||||
"forks_count": 0,
|
||||
"forks_url": "https://api.github.com/repos/docker/github-builder-test/forks",
|
||||
"full_name": "docker/github-builder-test",
|
||||
"git_commits_url": "https://api.github.com/repos/docker/github-builder-test/git/commits{/sha}",
|
||||
"git_refs_url": "https://api.github.com/repos/docker/github-builder-test/git/refs{/sha}",
|
||||
"git_tags_url": "https://api.github.com/repos/docker/github-builder-test/git/tags{/sha}",
|
||||
"git_url": "git://github.com/docker/github-builder-test.git",
|
||||
"has_discussions": false,
|
||||
"has_downloads": true,
|
||||
"has_issues": false,
|
||||
"has_pages": false,
|
||||
"has_projects": false,
|
||||
"has_wiki": false,
|
||||
"homepage": null,
|
||||
"hooks_url": "https://api.github.com/repos/docker/github-builder-test/hooks",
|
||||
"html_url": "https://github.com/docker/github-builder-test",
|
||||
"id": 1040594287,
|
||||
"is_template": false,
|
||||
"issue_comment_url": "https://api.github.com/repos/docker/github-builder-test/issues/comments{/number}",
|
||||
"issue_events_url": "https://api.github.com/repos/docker/github-builder-test/issues/events{/number}",
|
||||
"issues_url": "https://api.github.com/repos/docker/github-builder-test/issues{/number}",
|
||||
"keys_url": "https://api.github.com/repos/docker/github-builder-test/keys{/key_id}",
|
||||
"labels_url": "https://api.github.com/repos/docker/github-builder-test/labels{/name}",
|
||||
"language": "Dockerfile",
|
||||
"languages_url": "https://api.github.com/repos/docker/github-builder-test/languages",
|
||||
"license": null,
|
||||
"merges_url": "https://api.github.com/repos/docker/github-builder-test/merges",
|
||||
"milestones_url": "https://api.github.com/repos/docker/github-builder-test/milestones{/number}",
|
||||
"mirror_url": null,
|
||||
"name": "github-builder-test",
|
||||
"node_id": "R_kgDOPgY1bw",
|
||||
"notifications_url": "https://api.github.com/repos/docker/github-builder-test/notifications{?since,all,participating}",
|
||||
"open_issues": 0,
|
||||
"open_issues_count": 0,
|
||||
"owner": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
|
||||
"events_url": "https://api.github.com/users/docker/events{/privacy}",
|
||||
"followers_url": "https://api.github.com/users/docker/followers",
|
||||
"following_url": "https://api.github.com/users/docker/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/docker/gists{/gist_id}",
|
||||
"gravatar_id": "",
|
||||
"html_url": "https://github.com/docker",
|
||||
"id": 5429470,
|
||||
"login": "docker",
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
|
||||
"organizations_url": "https://api.github.com/users/docker/orgs",
|
||||
"received_events_url": "https://api.github.com/users/docker/received_events",
|
||||
"repos_url": "https://api.github.com/users/docker/repos",
|
||||
"site_admin": false,
|
||||
"starred_url": "https://api.github.com/users/docker/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/docker/subscriptions",
|
||||
"type": "Organization",
|
||||
"url": "https://api.github.com/users/docker",
|
||||
"user_view_type": "public"
|
||||
},
|
||||
"private": true,
|
||||
"pulls_url": "https://api.github.com/repos/docker/github-builder-test/pulls{/number}",
|
||||
"pushed_at": "2025-10-30T10:04:10Z",
|
||||
"releases_url": "https://api.github.com/repos/docker/github-builder-test/releases{/id}",
|
||||
"size": 25,
|
||||
"ssh_url": "git@github.com:docker/github-builder-test.git",
|
||||
"stargazers_count": 0,
|
||||
"stargazers_url": "https://api.github.com/repos/docker/github-builder-test/stargazers",
|
||||
"statuses_url": "https://api.github.com/repos/docker/github-builder-test/statuses/{sha}",
|
||||
"subscribers_url": "https://api.github.com/repos/docker/github-builder-test/subscribers",
|
||||
"subscription_url": "https://api.github.com/repos/docker/github-builder-test/subscription",
|
||||
"svn_url": "https://github.com/docker/github-builder-test",
|
||||
"tags_url": "https://api.github.com/repos/docker/github-builder-test/tags",
|
||||
"teams_url": "https://api.github.com/repos/docker/github-builder-test/teams",
|
||||
"topics": [],
|
||||
"trees_url": "https://api.github.com/repos/docker/github-builder-test/git/trees{/sha}",
|
||||
"updated_at": "2025-10-30T10:04:14Z",
|
||||
"url": "https://api.github.com/repos/docker/github-builder-test",
|
||||
"visibility": "internal",
|
||||
"watchers": 0,
|
||||
"watchers_count": 0,
|
||||
"web_commit_signoff_required": false
|
||||
},
|
||||
"sender": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1951866?v=4",
|
||||
"events_url": "https://api.github.com/users/crazy-max/events{/privacy}",
|
||||
"followers_url": "https://api.github.com/users/crazy-max/followers",
|
||||
"following_url": "https://api.github.com/users/crazy-max/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/crazy-max/gists{/gist_id}",
|
||||
"gravatar_id": "",
|
||||
"html_url": "https://github.com/crazy-max",
|
||||
"id": 1951866,
|
||||
"login": "crazy-max",
|
||||
"node_id": "MDQ6VXNlcjE5NTE4NjY=",
|
||||
"organizations_url": "https://api.github.com/users/crazy-max/orgs",
|
||||
"received_events_url": "https://api.github.com/users/crazy-max/received_events",
|
||||
"repos_url": "https://api.github.com/users/crazy-max/repos",
|
||||
"site_admin": false,
|
||||
"starred_url": "https://api.github.com/users/crazy-max/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/crazy-max/subscriptions",
|
||||
"type": "User",
|
||||
"url": "https://api.github.com/users/crazy-max",
|
||||
"user_view_type": "public"
|
||||
},
|
||||
"workflow": ".github/workflows/ci.yml"
|
||||
},
|
||||
"github_job": "build",
|
||||
"github_ref": "refs/heads/main",
|
||||
"github_ref_name": "main",
|
||||
"github_ref_protected": "false",
|
||||
"github_ref_type": "branch",
|
||||
"github_repository": "docker/github-builder-test",
|
||||
"github_repository_id": "1040594287",
|
||||
"github_repository_owner": "docker",
|
||||
"github_repository_owner_id": "5429470",
|
||||
"github_run_attempt": "1",
|
||||
"github_run_id": "18937328894",
|
||||
"github_run_number": "183",
|
||||
"github_runner_arch": "X64",
|
||||
"github_runner_environment": "github-hosted",
|
||||
"github_runner_image_os": "ubuntu24",
|
||||
"github_runner_image_version": "20250929.60.1",
|
||||
"github_runner_name": "GitHub Actions 1002376925",
|
||||
"github_runner_os": "Linux",
|
||||
"github_runner_tracking_id": "github_7c0a7521-2999-41e5-af30-b7f0681f204f",
|
||||
"github_server_url": "https://github.com",
|
||||
"github_triggering_actor": "crazy-max",
|
||||
"github_workflow": "ci",
|
||||
"github_workflow_ref": "docker/github-builder-test/.github/workflows/ci.yml@refs/heads/main",
|
||||
"github_workflow_sha": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
}
|
||||
},
|
||||
"runDetails": {
|
||||
"builder": {
|
||||
"id": "https://github.com/docker/github-builder-test/actions/runs/18937328894/attempts/1"
|
||||
},
|
||||
"metadata": {
|
||||
"invocationID": "7qg2yuux3iklv02ktbmbtwgeb",
|
||||
"startedOn": "2025-10-30T10:19:52.868710505Z",
|
||||
"finishedOn": "2025-10-30T10:19:57.635810119Z",
|
||||
"buildkit_metadata": {
|
||||
"source": {
|
||||
"locations": {
|
||||
"step0": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"step1": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 3
|
||||
},
|
||||
"end": {
|
||||
"line": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"step2": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"infos": [
|
||||
{
|
||||
"filename": "hello.Dockerfile",
|
||||
"language": "Dockerfile",
|
||||
"data": "RlJPTSBhbHBpbmUgQVMgYmFzZQpBUkcgVEFSR0VUUExBVEZPUk0KUlVOIGVjaG8gIkhlbGxvLCBXb3JsZCEgVGhpcyBpcyAke1RBUkdFVFBMQVRGT1JNfSIgPiAvaGVsbG8udHh0CkFSRyBCVUlMREtJVF9TQk9NX1NDQU5fU1RBR0U9dHJ1ZQoKRlJPTSBzY3JhdGNoCkNPUFkgLS1mcm9tPWJhc2UgL2hlbGxvLnR4dCAvCg==",
|
||||
"llbDefinition": [
|
||||
{
|
||||
"id": "step0",
|
||||
"op": {
|
||||
"Op": {
|
||||
"source": {
|
||||
"identifier": "git://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"attrs": {
|
||||
"git.authheadersecret": "GIT_AUTH_HEADER",
|
||||
"git.authtokensecret": "GIT_AUTH_TOKEN",
|
||||
"git.fullurl": "https://github.com/docker/github-builder-test.git"
|
||||
}
|
||||
}
|
||||
},
|
||||
"constraints": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step1",
|
||||
"op": {
|
||||
"Op": {}
|
||||
},
|
||||
"inputs": [
|
||||
"step0:0"
|
||||
]
|
||||
}
|
||||
],
|
||||
"digestMapping": {
|
||||
"sha256:47540f0959d81a7ff2fc9742b9ef0bb37d7eca99c13aa6df83b883d06e808ef2": "step0",
|
||||
"sha256:96933c546ff00debd500304305864192fcb51d348e8c41b6a6e1569a051e66ed": "step1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"layers": {
|
||||
"step0:0": [
|
||||
[
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||
"digest": "sha256:2d35ebdb57d9971fea0cac1582aa78935adf8058b2cc32db163c98822e5dfa1b",
|
||||
"size": 3802452
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"buildkit_completeness": {
|
||||
"request": true,
|
||||
"resolvedDependencies": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
__tests__/.fixtures/sigstore/multi/linux_arm64/hello.txt
Normal file
1
__tests__/.fixtures/sigstore/multi/linux_arm64/hello.txt
Normal file
@@ -0,0 +1 @@
|
||||
Hello, World! This is linux/arm64
|
||||
462
__tests__/.fixtures/sigstore/multi/linux_arm64/provenance.json
Normal file
462
__tests__/.fixtures/sigstore/multi/linux_arm64/provenance.json
Normal file
@@ -0,0 +1,462 @@
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v0.1",
|
||||
"predicateType": "https://slsa.dev/provenance/v1",
|
||||
"subject": [
|
||||
{
|
||||
"name": "hello.txt",
|
||||
"digest": {
|
||||
"sha256": "870e0065e68cbdeacbf9cec21b598bb579b0ef55bc48b65b71509667edb570bd"
|
||||
}
|
||||
}
|
||||
],
|
||||
"predicate": {
|
||||
"buildDefinition": {
|
||||
"buildType": "https://github.com/moby/buildkit/blob/master/docs/attestations/slsa-definitions.md",
|
||||
"resolvedDependencies": [
|
||||
{
|
||||
"uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1",
|
||||
"digest": {
|
||||
"sha256": "e930c2697be77cb7271d316ecfa78768b5eac73de3b16018ed38eb0ea0b5a7cb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"uri": "pkg:docker/alpine@latest?platform=linux%2Farm64",
|
||||
"digest": {
|
||||
"sha256": "4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
|
||||
}
|
||||
},
|
||||
{
|
||||
"uri": "https://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"digest": {
|
||||
"sha1": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
}
|
||||
}
|
||||
],
|
||||
"externalParameters": {
|
||||
"configSource": {
|
||||
"uri": "https://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"digest": {
|
||||
"sha1": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
},
|
||||
"path": "hello.Dockerfile"
|
||||
},
|
||||
"request": {
|
||||
"frontend": "dockerfile.v0",
|
||||
"secrets": [
|
||||
{
|
||||
"id": "GIT_AUTH_HEADER",
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"id": "GIT_AUTH_TOKEN",
|
||||
"optional": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"internalParameters": {
|
||||
"buildConfig": {
|
||||
"digestMapping": {
|
||||
"sha256:69f88b22af1cbbe236f4b5d834dfe9c4adb9535c1c602f726fd90212c302a7da": "step0",
|
||||
"sha256:98c0e3a8b1a38f5aa8db558b99aace8e7645a18b0e24d6807018146d21788ae2": "step2",
|
||||
"sha256:a560219f1e0cfb232a9727b9bbf9d6735c0b2190f8e00364f844cfc82bd42479": "step1",
|
||||
"sha256:c7edeef726371083a69f15a3565d6c62be55a91e820f251d9a965f8e36fe3e32": "step3"
|
||||
},
|
||||
"llbDefinition": [
|
||||
{
|
||||
"id": "step0",
|
||||
"op": {
|
||||
"Op": {
|
||||
"source": {
|
||||
"identifier": "docker-image://docker.io/library/alpine:latest@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
|
||||
}
|
||||
},
|
||||
"constraints": {},
|
||||
"platform": {
|
||||
"Architecture": "arm64",
|
||||
"OS": "linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step1",
|
||||
"inputs": [
|
||||
"step0:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {
|
||||
"exec": {
|
||||
"meta": {
|
||||
"args": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"echo \"Hello, World! This is ${TARGETPLATFORM}\" \u003e /hello.txt"
|
||||
],
|
||||
"cwd": "/",
|
||||
"env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TARGETPLATFORM=linux/arm64"
|
||||
],
|
||||
"removeMountStubsRecursive": true
|
||||
},
|
||||
"mounts": [
|
||||
{
|
||||
"dest": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"constraints": {},
|
||||
"platform": {
|
||||
"Architecture": "arm64",
|
||||
"OS": "linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step2",
|
||||
"inputs": [
|
||||
"step1:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {
|
||||
"file": {
|
||||
"actions": [
|
||||
{
|
||||
"Action": {
|
||||
"copy": {
|
||||
"allowEmptyWildcard": true,
|
||||
"allowWildcard": true,
|
||||
"createDestPath": true,
|
||||
"dest": "/",
|
||||
"dirCopyContents": true,
|
||||
"followSymlink": true,
|
||||
"mode": -1,
|
||||
"src": "/hello.txt",
|
||||
"timestamp": -1
|
||||
}
|
||||
},
|
||||
"input": -1,
|
||||
"output": 0,
|
||||
"secondaryInput": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"constraints": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step3",
|
||||
"inputs": [
|
||||
"step2:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"builderPlatform": "linux/amd64",
|
||||
"github_actor": "crazy-max",
|
||||
"github_actor_id": "1951866",
|
||||
"github_event_name": "workflow_dispatch",
|
||||
"github_event_payload": {
|
||||
"enterprise": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/b/19176?v=4",
|
||||
"created_at": "2022-12-30T23:53:17Z",
|
||||
"description": null,
|
||||
"html_url": "https://github.com/enterprises/docker",
|
||||
"id": 19176,
|
||||
"name": "Docker",
|
||||
"node_id": "E_kgDNSug",
|
||||
"slug": "docker",
|
||||
"updated_at": "2025-10-20T20:39:05Z",
|
||||
"website_url": null
|
||||
},
|
||||
"inputs": null,
|
||||
"organization": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
|
||||
"description": "Docker helps developers bring their ideas to life by conquering the complexity of app development.",
|
||||
"events_url": "https://api.github.com/orgs/docker/events",
|
||||
"hooks_url": "https://api.github.com/orgs/docker/hooks",
|
||||
"id": 5429470,
|
||||
"issues_url": "https://api.github.com/orgs/docker/issues",
|
||||
"login": "docker",
|
||||
"members_url": "https://api.github.com/orgs/docker/members{/member}",
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
|
||||
"public_members_url": "https://api.github.com/orgs/docker/public_members{/member}",
|
||||
"repos_url": "https://api.github.com/orgs/docker/repos",
|
||||
"url": "https://api.github.com/orgs/docker"
|
||||
},
|
||||
"ref": "refs/heads/main",
|
||||
"repository": {
|
||||
"allow_forking": true,
|
||||
"archive_url": "https://api.github.com/repos/docker/github-builder-test/{archive_format}{/ref}",
|
||||
"archived": false,
|
||||
"assignees_url": "https://api.github.com/repos/docker/github-builder-test/assignees{/user}",
|
||||
"blobs_url": "https://api.github.com/repos/docker/github-builder-test/git/blobs{/sha}",
|
||||
"branches_url": "https://api.github.com/repos/docker/github-builder-test/branches{/branch}",
|
||||
"clone_url": "https://github.com/docker/github-builder-test.git",
|
||||
"collaborators_url": "https://api.github.com/repos/docker/github-builder-test/collaborators{/collaborator}",
|
||||
"comments_url": "https://api.github.com/repos/docker/github-builder-test/comments{/number}",
|
||||
"commits_url": "https://api.github.com/repos/docker/github-builder-test/commits{/sha}",
|
||||
"compare_url": "https://api.github.com/repos/docker/github-builder-test/compare/{base}...{head}",
|
||||
"contents_url": "https://api.github.com/repos/docker/github-builder-test/contents/{+path}",
|
||||
"contributors_url": "https://api.github.com/repos/docker/github-builder-test/contributors",
|
||||
"created_at": "2025-08-19T08:08:29Z",
|
||||
"custom_properties": {},
|
||||
"default_branch": "main",
|
||||
"deployments_url": "https://api.github.com/repos/docker/github-builder-test/deployments",
|
||||
"description": "Test repo for https://github.com/docker/github-builder-experimental",
|
||||
"disabled": false,
|
||||
"downloads_url": "https://api.github.com/repos/docker/github-builder-test/downloads",
|
||||
"events_url": "https://api.github.com/repos/docker/github-builder-test/events",
|
||||
"fork": false,
|
||||
"forks": 0,
|
||||
"forks_count": 0,
|
||||
"forks_url": "https://api.github.com/repos/docker/github-builder-test/forks",
|
||||
"full_name": "docker/github-builder-test",
|
||||
"git_commits_url": "https://api.github.com/repos/docker/github-builder-test/git/commits{/sha}",
|
||||
"git_refs_url": "https://api.github.com/repos/docker/github-builder-test/git/refs{/sha}",
|
||||
"git_tags_url": "https://api.github.com/repos/docker/github-builder-test/git/tags{/sha}",
|
||||
"git_url": "git://github.com/docker/github-builder-test.git",
|
||||
"has_discussions": false,
|
||||
"has_downloads": true,
|
||||
"has_issues": false,
|
||||
"has_pages": false,
|
||||
"has_projects": false,
|
||||
"has_wiki": false,
|
||||
"homepage": null,
|
||||
"hooks_url": "https://api.github.com/repos/docker/github-builder-test/hooks",
|
||||
"html_url": "https://github.com/docker/github-builder-test",
|
||||
"id": 1040594287,
|
||||
"is_template": false,
|
||||
"issue_comment_url": "https://api.github.com/repos/docker/github-builder-test/issues/comments{/number}",
|
||||
"issue_events_url": "https://api.github.com/repos/docker/github-builder-test/issues/events{/number}",
|
||||
"issues_url": "https://api.github.com/repos/docker/github-builder-test/issues{/number}",
|
||||
"keys_url": "https://api.github.com/repos/docker/github-builder-test/keys{/key_id}",
|
||||
"labels_url": "https://api.github.com/repos/docker/github-builder-test/labels{/name}",
|
||||
"language": "Dockerfile",
|
||||
"languages_url": "https://api.github.com/repos/docker/github-builder-test/languages",
|
||||
"license": null,
|
||||
"merges_url": "https://api.github.com/repos/docker/github-builder-test/merges",
|
||||
"milestones_url": "https://api.github.com/repos/docker/github-builder-test/milestones{/number}",
|
||||
"mirror_url": null,
|
||||
"name": "github-builder-test",
|
||||
"node_id": "R_kgDOPgY1bw",
|
||||
"notifications_url": "https://api.github.com/repos/docker/github-builder-test/notifications{?since,all,participating}",
|
||||
"open_issues": 0,
|
||||
"open_issues_count": 0,
|
||||
"owner": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
|
||||
"events_url": "https://api.github.com/users/docker/events{/privacy}",
|
||||
"followers_url": "https://api.github.com/users/docker/followers",
|
||||
"following_url": "https://api.github.com/users/docker/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/docker/gists{/gist_id}",
|
||||
"gravatar_id": "",
|
||||
"html_url": "https://github.com/docker",
|
||||
"id": 5429470,
|
||||
"login": "docker",
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
|
||||
"organizations_url": "https://api.github.com/users/docker/orgs",
|
||||
"received_events_url": "https://api.github.com/users/docker/received_events",
|
||||
"repos_url": "https://api.github.com/users/docker/repos",
|
||||
"site_admin": false,
|
||||
"starred_url": "https://api.github.com/users/docker/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/docker/subscriptions",
|
||||
"type": "Organization",
|
||||
"url": "https://api.github.com/users/docker",
|
||||
"user_view_type": "public"
|
||||
},
|
||||
"private": true,
|
||||
"pulls_url": "https://api.github.com/repos/docker/github-builder-test/pulls{/number}",
|
||||
"pushed_at": "2025-10-30T10:04:10Z",
|
||||
"releases_url": "https://api.github.com/repos/docker/github-builder-test/releases{/id}",
|
||||
"size": 25,
|
||||
"ssh_url": "git@github.com:docker/github-builder-test.git",
|
||||
"stargazers_count": 0,
|
||||
"stargazers_url": "https://api.github.com/repos/docker/github-builder-test/stargazers",
|
||||
"statuses_url": "https://api.github.com/repos/docker/github-builder-test/statuses/{sha}",
|
||||
"subscribers_url": "https://api.github.com/repos/docker/github-builder-test/subscribers",
|
||||
"subscription_url": "https://api.github.com/repos/docker/github-builder-test/subscription",
|
||||
"svn_url": "https://github.com/docker/github-builder-test",
|
||||
"tags_url": "https://api.github.com/repos/docker/github-builder-test/tags",
|
||||
"teams_url": "https://api.github.com/repos/docker/github-builder-test/teams",
|
||||
"topics": [],
|
||||
"trees_url": "https://api.github.com/repos/docker/github-builder-test/git/trees{/sha}",
|
||||
"updated_at": "2025-10-30T10:04:14Z",
|
||||
"url": "https://api.github.com/repos/docker/github-builder-test",
|
||||
"visibility": "internal",
|
||||
"watchers": 0,
|
||||
"watchers_count": 0,
|
||||
"web_commit_signoff_required": false
|
||||
},
|
||||
"sender": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1951866?v=4",
|
||||
"events_url": "https://api.github.com/users/crazy-max/events{/privacy}",
|
||||
"followers_url": "https://api.github.com/users/crazy-max/followers",
|
||||
"following_url": "https://api.github.com/users/crazy-max/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/crazy-max/gists{/gist_id}",
|
||||
"gravatar_id": "",
|
||||
"html_url": "https://github.com/crazy-max",
|
||||
"id": 1951866,
|
||||
"login": "crazy-max",
|
||||
"node_id": "MDQ6VXNlcjE5NTE4NjY=",
|
||||
"organizations_url": "https://api.github.com/users/crazy-max/orgs",
|
||||
"received_events_url": "https://api.github.com/users/crazy-max/received_events",
|
||||
"repos_url": "https://api.github.com/users/crazy-max/repos",
|
||||
"site_admin": false,
|
||||
"starred_url": "https://api.github.com/users/crazy-max/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/crazy-max/subscriptions",
|
||||
"type": "User",
|
||||
"url": "https://api.github.com/users/crazy-max",
|
||||
"user_view_type": "public"
|
||||
},
|
||||
"workflow": ".github/workflows/ci.yml"
|
||||
},
|
||||
"github_job": "build",
|
||||
"github_ref": "refs/heads/main",
|
||||
"github_ref_name": "main",
|
||||
"github_ref_protected": "false",
|
||||
"github_ref_type": "branch",
|
||||
"github_repository": "docker/github-builder-test",
|
||||
"github_repository_id": "1040594287",
|
||||
"github_repository_owner": "docker",
|
||||
"github_repository_owner_id": "5429470",
|
||||
"github_run_attempt": "1",
|
||||
"github_run_id": "18937328894",
|
||||
"github_run_number": "183",
|
||||
"github_runner_arch": "X64",
|
||||
"github_runner_environment": "github-hosted",
|
||||
"github_runner_image_os": "ubuntu24",
|
||||
"github_runner_image_version": "20250929.60.1",
|
||||
"github_runner_name": "GitHub Actions 1002376925",
|
||||
"github_runner_os": "Linux",
|
||||
"github_runner_tracking_id": "github_7c0a7521-2999-41e5-af30-b7f0681f204f",
|
||||
"github_server_url": "https://github.com",
|
||||
"github_triggering_actor": "crazy-max",
|
||||
"github_workflow": "ci",
|
||||
"github_workflow_ref": "docker/github-builder-test/.github/workflows/ci.yml@refs/heads/main",
|
||||
"github_workflow_sha": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
}
|
||||
},
|
||||
"runDetails": {
|
||||
"builder": {
|
||||
"id": "https://github.com/docker/github-builder-test/actions/runs/18937328894/attempts/1"
|
||||
},
|
||||
"metadata": {
|
||||
"invocationID": "7qg2yuux3iklv02ktbmbtwgeb",
|
||||
"startedOn": "2025-10-30T10:19:52.868710505Z",
|
||||
"finishedOn": "2025-10-30T10:19:57.635810119Z",
|
||||
"buildkit_metadata": {
|
||||
"source": {
|
||||
"locations": {
|
||||
"step0": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"step1": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 3
|
||||
},
|
||||
"end": {
|
||||
"line": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"step2": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"infos": [
|
||||
{
|
||||
"filename": "hello.Dockerfile",
|
||||
"language": "Dockerfile",
|
||||
"data": "RlJPTSBhbHBpbmUgQVMgYmFzZQpBUkcgVEFSR0VUUExBVEZPUk0KUlVOIGVjaG8gIkhlbGxvLCBXb3JsZCEgVGhpcyBpcyAke1RBUkdFVFBMQVRGT1JNfSIgPiAvaGVsbG8udHh0CkFSRyBCVUlMREtJVF9TQk9NX1NDQU5fU1RBR0U9dHJ1ZQoKRlJPTSBzY3JhdGNoCkNPUFkgLS1mcm9tPWJhc2UgL2hlbGxvLnR4dCAvCg==",
|
||||
"llbDefinition": [
|
||||
{
|
||||
"id": "step0",
|
||||
"op": {
|
||||
"Op": {
|
||||
"source": {
|
||||
"identifier": "git://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"attrs": {
|
||||
"git.authheadersecret": "GIT_AUTH_HEADER",
|
||||
"git.authtokensecret": "GIT_AUTH_TOKEN",
|
||||
"git.fullurl": "https://github.com/docker/github-builder-test.git"
|
||||
}
|
||||
}
|
||||
},
|
||||
"constraints": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step1",
|
||||
"op": {
|
||||
"Op": {}
|
||||
},
|
||||
"inputs": [
|
||||
"step0:0"
|
||||
]
|
||||
}
|
||||
],
|
||||
"digestMapping": {
|
||||
"sha256:47540f0959d81a7ff2fc9742b9ef0bb37d7eca99c13aa6df83b883d06e808ef2": "step0",
|
||||
"sha256:96933c546ff00debd500304305864192fcb51d348e8c41b6a6e1569a051e66ed": "step1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"layers": {
|
||||
"step0:0": [
|
||||
[
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||
"digest": "sha256:6b59a28fa20117e6048ad0616b8d8c901877ef15ff4c7f18db04e4f01f43bc39",
|
||||
"size": 4138069
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"buildkit_completeness": {
|
||||
"request": true,
|
||||
"resolvedDependencies": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
__tests__/.fixtures/sigstore/single/hello.txt
Normal file
1
__tests__/.fixtures/sigstore/single/hello.txt
Normal file
@@ -0,0 +1 @@
|
||||
Hello, World! This is linux/amd64
|
||||
462
__tests__/.fixtures/sigstore/single/provenance.json
Normal file
462
__tests__/.fixtures/sigstore/single/provenance.json
Normal file
@@ -0,0 +1,462 @@
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v0.1",
|
||||
"predicateType": "https://slsa.dev/provenance/v1",
|
||||
"subject": [
|
||||
{
|
||||
"name": "hello.txt",
|
||||
"digest": {
|
||||
"sha256": "1b37929e66644beb58b3d28d44fba0d82aa90cab03c55a492adb81fe6e833ec8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"predicate": {
|
||||
"buildDefinition": {
|
||||
"buildType": "https://github.com/moby/buildkit/blob/master/docs/attestations/slsa-definitions.md",
|
||||
"resolvedDependencies": [
|
||||
{
|
||||
"uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1",
|
||||
"digest": {
|
||||
"sha256": "e930c2697be77cb7271d316ecfa78768b5eac73de3b16018ed38eb0ea0b5a7cb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||
"digest": {
|
||||
"sha256": "4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
|
||||
}
|
||||
},
|
||||
{
|
||||
"uri": "https://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"digest": {
|
||||
"sha1": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
}
|
||||
}
|
||||
],
|
||||
"externalParameters": {
|
||||
"configSource": {
|
||||
"uri": "https://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"digest": {
|
||||
"sha1": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
},
|
||||
"path": "hello.Dockerfile"
|
||||
},
|
||||
"request": {
|
||||
"frontend": "dockerfile.v0",
|
||||
"secrets": [
|
||||
{
|
||||
"id": "GIT_AUTH_HEADER",
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"id": "GIT_AUTH_TOKEN",
|
||||
"optional": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"internalParameters": {
|
||||
"buildConfig": {
|
||||
"digestMapping": {
|
||||
"sha256:23dcbc3cce701a8a9bbb1e33f2ea88304527a4a935c89c4564af698095463ac2": "step3",
|
||||
"sha256:3192c1bd53f90cca959db778dcee30edc9a79f8cd3f9a2c54adc4606507fd3b6": "step0",
|
||||
"sha256:7f1c9e959980ea3e2cf4af8ef97b6c3797a0926752b436bff11474e436defe7f": "step1",
|
||||
"sha256:c8737331fb8e5f5bcb6b22320012d975057514982c788e63db13332a4219b984": "step2"
|
||||
},
|
||||
"llbDefinition": [
|
||||
{
|
||||
"id": "step0",
|
||||
"op": {
|
||||
"Op": {
|
||||
"source": {
|
||||
"identifier": "docker-image://docker.io/library/alpine:latest@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412"
|
||||
}
|
||||
},
|
||||
"constraints": {},
|
||||
"platform": {
|
||||
"Architecture": "amd64",
|
||||
"OS": "linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step1",
|
||||
"inputs": [
|
||||
"step0:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {
|
||||
"exec": {
|
||||
"meta": {
|
||||
"args": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"echo \"Hello, World! This is ${TARGETPLATFORM}\" \u003e /hello.txt"
|
||||
],
|
||||
"cwd": "/",
|
||||
"env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TARGETPLATFORM=linux/amd64"
|
||||
],
|
||||
"removeMountStubsRecursive": true
|
||||
},
|
||||
"mounts": [
|
||||
{
|
||||
"dest": "/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"constraints": {},
|
||||
"platform": {
|
||||
"Architecture": "amd64",
|
||||
"OS": "linux"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step2",
|
||||
"inputs": [
|
||||
"step1:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {
|
||||
"file": {
|
||||
"actions": [
|
||||
{
|
||||
"Action": {
|
||||
"copy": {
|
||||
"allowEmptyWildcard": true,
|
||||
"allowWildcard": true,
|
||||
"createDestPath": true,
|
||||
"dest": "/",
|
||||
"dirCopyContents": true,
|
||||
"followSymlink": true,
|
||||
"mode": -1,
|
||||
"src": "/hello.txt",
|
||||
"timestamp": -1
|
||||
}
|
||||
},
|
||||
"input": -1,
|
||||
"output": 0,
|
||||
"secondaryInput": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"constraints": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step3",
|
||||
"inputs": [
|
||||
"step2:0"
|
||||
],
|
||||
"op": {
|
||||
"Op": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"builderPlatform": "linux/amd64",
|
||||
"github_actor": "crazy-max",
|
||||
"github_actor_id": "1951866",
|
||||
"github_event_name": "workflow_dispatch",
|
||||
"github_event_payload": {
|
||||
"enterprise": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/b/19176?v=4",
|
||||
"created_at": "2022-12-30T23:53:17Z",
|
||||
"description": null,
|
||||
"html_url": "https://github.com/enterprises/docker",
|
||||
"id": 19176,
|
||||
"name": "Docker",
|
||||
"node_id": "E_kgDNSug",
|
||||
"slug": "docker",
|
||||
"updated_at": "2025-10-20T20:39:05Z",
|
||||
"website_url": null
|
||||
},
|
||||
"inputs": null,
|
||||
"organization": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
|
||||
"description": "Docker helps developers bring their ideas to life by conquering the complexity of app development.",
|
||||
"events_url": "https://api.github.com/orgs/docker/events",
|
||||
"hooks_url": "https://api.github.com/orgs/docker/hooks",
|
||||
"id": 5429470,
|
||||
"issues_url": "https://api.github.com/orgs/docker/issues",
|
||||
"login": "docker",
|
||||
"members_url": "https://api.github.com/orgs/docker/members{/member}",
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
|
||||
"public_members_url": "https://api.github.com/orgs/docker/public_members{/member}",
|
||||
"repos_url": "https://api.github.com/orgs/docker/repos",
|
||||
"url": "https://api.github.com/orgs/docker"
|
||||
},
|
||||
"ref": "refs/heads/main",
|
||||
"repository": {
|
||||
"allow_forking": true,
|
||||
"archive_url": "https://api.github.com/repos/docker/github-builder-test/{archive_format}{/ref}",
|
||||
"archived": false,
|
||||
"assignees_url": "https://api.github.com/repos/docker/github-builder-test/assignees{/user}",
|
||||
"blobs_url": "https://api.github.com/repos/docker/github-builder-test/git/blobs{/sha}",
|
||||
"branches_url": "https://api.github.com/repos/docker/github-builder-test/branches{/branch}",
|
||||
"clone_url": "https://github.com/docker/github-builder-test.git",
|
||||
"collaborators_url": "https://api.github.com/repos/docker/github-builder-test/collaborators{/collaborator}",
|
||||
"comments_url": "https://api.github.com/repos/docker/github-builder-test/comments{/number}",
|
||||
"commits_url": "https://api.github.com/repos/docker/github-builder-test/commits{/sha}",
|
||||
"compare_url": "https://api.github.com/repos/docker/github-builder-test/compare/{base}...{head}",
|
||||
"contents_url": "https://api.github.com/repos/docker/github-builder-test/contents/{+path}",
|
||||
"contributors_url": "https://api.github.com/repos/docker/github-builder-test/contributors",
|
||||
"created_at": "2025-08-19T08:08:29Z",
|
||||
"custom_properties": {},
|
||||
"default_branch": "main",
|
||||
"deployments_url": "https://api.github.com/repos/docker/github-builder-test/deployments",
|
||||
"description": "Test repo for https://github.com/docker/github-builder-experimental",
|
||||
"disabled": false,
|
||||
"downloads_url": "https://api.github.com/repos/docker/github-builder-test/downloads",
|
||||
"events_url": "https://api.github.com/repos/docker/github-builder-test/events",
|
||||
"fork": false,
|
||||
"forks": 0,
|
||||
"forks_count": 0,
|
||||
"forks_url": "https://api.github.com/repos/docker/github-builder-test/forks",
|
||||
"full_name": "docker/github-builder-test",
|
||||
"git_commits_url": "https://api.github.com/repos/docker/github-builder-test/git/commits{/sha}",
|
||||
"git_refs_url": "https://api.github.com/repos/docker/github-builder-test/git/refs{/sha}",
|
||||
"git_tags_url": "https://api.github.com/repos/docker/github-builder-test/git/tags{/sha}",
|
||||
"git_url": "git://github.com/docker/github-builder-test.git",
|
||||
"has_discussions": false,
|
||||
"has_downloads": true,
|
||||
"has_issues": false,
|
||||
"has_pages": false,
|
||||
"has_projects": false,
|
||||
"has_wiki": false,
|
||||
"homepage": null,
|
||||
"hooks_url": "https://api.github.com/repos/docker/github-builder-test/hooks",
|
||||
"html_url": "https://github.com/docker/github-builder-test",
|
||||
"id": 1040594287,
|
||||
"is_template": false,
|
||||
"issue_comment_url": "https://api.github.com/repos/docker/github-builder-test/issues/comments{/number}",
|
||||
"issue_events_url": "https://api.github.com/repos/docker/github-builder-test/issues/events{/number}",
|
||||
"issues_url": "https://api.github.com/repos/docker/github-builder-test/issues{/number}",
|
||||
"keys_url": "https://api.github.com/repos/docker/github-builder-test/keys{/key_id}",
|
||||
"labels_url": "https://api.github.com/repos/docker/github-builder-test/labels{/name}",
|
||||
"language": "Dockerfile",
|
||||
"languages_url": "https://api.github.com/repos/docker/github-builder-test/languages",
|
||||
"license": null,
|
||||
"merges_url": "https://api.github.com/repos/docker/github-builder-test/merges",
|
||||
"milestones_url": "https://api.github.com/repos/docker/github-builder-test/milestones{/number}",
|
||||
"mirror_url": null,
|
||||
"name": "github-builder-test",
|
||||
"node_id": "R_kgDOPgY1bw",
|
||||
"notifications_url": "https://api.github.com/repos/docker/github-builder-test/notifications{?since,all,participating}",
|
||||
"open_issues": 0,
|
||||
"open_issues_count": 0,
|
||||
"owner": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5429470?v=4",
|
||||
"events_url": "https://api.github.com/users/docker/events{/privacy}",
|
||||
"followers_url": "https://api.github.com/users/docker/followers",
|
||||
"following_url": "https://api.github.com/users/docker/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/docker/gists{/gist_id}",
|
||||
"gravatar_id": "",
|
||||
"html_url": "https://github.com/docker",
|
||||
"id": 5429470,
|
||||
"login": "docker",
|
||||
"node_id": "MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=",
|
||||
"organizations_url": "https://api.github.com/users/docker/orgs",
|
||||
"received_events_url": "https://api.github.com/users/docker/received_events",
|
||||
"repos_url": "https://api.github.com/users/docker/repos",
|
||||
"site_admin": false,
|
||||
"starred_url": "https://api.github.com/users/docker/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/docker/subscriptions",
|
||||
"type": "Organization",
|
||||
"url": "https://api.github.com/users/docker",
|
||||
"user_view_type": "public"
|
||||
},
|
||||
"private": true,
|
||||
"pulls_url": "https://api.github.com/repos/docker/github-builder-test/pulls{/number}",
|
||||
"pushed_at": "2025-10-30T10:04:10Z",
|
||||
"releases_url": "https://api.github.com/repos/docker/github-builder-test/releases{/id}",
|
||||
"size": 25,
|
||||
"ssh_url": "git@github.com:docker/github-builder-test.git",
|
||||
"stargazers_count": 0,
|
||||
"stargazers_url": "https://api.github.com/repos/docker/github-builder-test/stargazers",
|
||||
"statuses_url": "https://api.github.com/repos/docker/github-builder-test/statuses/{sha}",
|
||||
"subscribers_url": "https://api.github.com/repos/docker/github-builder-test/subscribers",
|
||||
"subscription_url": "https://api.github.com/repos/docker/github-builder-test/subscription",
|
||||
"svn_url": "https://github.com/docker/github-builder-test",
|
||||
"tags_url": "https://api.github.com/repos/docker/github-builder-test/tags",
|
||||
"teams_url": "https://api.github.com/repos/docker/github-builder-test/teams",
|
||||
"topics": [],
|
||||
"trees_url": "https://api.github.com/repos/docker/github-builder-test/git/trees{/sha}",
|
||||
"updated_at": "2025-10-30T10:04:14Z",
|
||||
"url": "https://api.github.com/repos/docker/github-builder-test",
|
||||
"visibility": "internal",
|
||||
"watchers": 0,
|
||||
"watchers_count": 0,
|
||||
"web_commit_signoff_required": false
|
||||
},
|
||||
"sender": {
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1951866?v=4",
|
||||
"events_url": "https://api.github.com/users/crazy-max/events{/privacy}",
|
||||
"followers_url": "https://api.github.com/users/crazy-max/followers",
|
||||
"following_url": "https://api.github.com/users/crazy-max/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/crazy-max/gists{/gist_id}",
|
||||
"gravatar_id": "",
|
||||
"html_url": "https://github.com/crazy-max",
|
||||
"id": 1951866,
|
||||
"login": "crazy-max",
|
||||
"node_id": "MDQ6VXNlcjE5NTE4NjY=",
|
||||
"organizations_url": "https://api.github.com/users/crazy-max/orgs",
|
||||
"received_events_url": "https://api.github.com/users/crazy-max/received_events",
|
||||
"repos_url": "https://api.github.com/users/crazy-max/repos",
|
||||
"site_admin": false,
|
||||
"starred_url": "https://api.github.com/users/crazy-max/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/crazy-max/subscriptions",
|
||||
"type": "User",
|
||||
"url": "https://api.github.com/users/crazy-max",
|
||||
"user_view_type": "public"
|
||||
},
|
||||
"workflow": ".github/workflows/ci.yml"
|
||||
},
|
||||
"github_job": "build",
|
||||
"github_ref": "refs/heads/main",
|
||||
"github_ref_name": "main",
|
||||
"github_ref_protected": "false",
|
||||
"github_ref_type": "branch",
|
||||
"github_repository": "docker/github-builder-test",
|
||||
"github_repository_id": "1040594287",
|
||||
"github_repository_owner": "docker",
|
||||
"github_repository_owner_id": "5429470",
|
||||
"github_run_attempt": "1",
|
||||
"github_run_id": "18937328894",
|
||||
"github_run_number": "183",
|
||||
"github_runner_arch": "X64",
|
||||
"github_runner_environment": "github-hosted",
|
||||
"github_runner_image_os": "ubuntu24",
|
||||
"github_runner_image_version": "20250929.60.1",
|
||||
"github_runner_name": "GitHub Actions 1002376925",
|
||||
"github_runner_os": "Linux",
|
||||
"github_runner_tracking_id": "github_7c0a7521-2999-41e5-af30-b7f0681f204f",
|
||||
"github_server_url": "https://github.com",
|
||||
"github_triggering_actor": "crazy-max",
|
||||
"github_workflow": "ci",
|
||||
"github_workflow_ref": "docker/github-builder-test/.github/workflows/ci.yml@refs/heads/main",
|
||||
"github_workflow_sha": "bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe"
|
||||
}
|
||||
},
|
||||
"runDetails": {
|
||||
"builder": {
|
||||
"id": "https://github.com/docker/github-builder-test/actions/runs/18937328894/attempts/1"
|
||||
},
|
||||
"metadata": {
|
||||
"invocationID": "7qg2yuux3iklv02ktbmbtwgeb",
|
||||
"startedOn": "2025-10-30T10:19:52.868710505Z",
|
||||
"finishedOn": "2025-10-30T10:19:57.635810119Z",
|
||||
"buildkit_metadata": {
|
||||
"source": {
|
||||
"locations": {
|
||||
"step0": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"step1": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 3
|
||||
},
|
||||
"end": {
|
||||
"line": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"step2": {
|
||||
"locations": [
|
||||
{
|
||||
"ranges": [
|
||||
{
|
||||
"start": {
|
||||
"line": 7
|
||||
},
|
||||
"end": {
|
||||
"line": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"infos": [
|
||||
{
|
||||
"filename": "hello.Dockerfile",
|
||||
"language": "Dockerfile",
|
||||
"data": "RlJPTSBhbHBpbmUgQVMgYmFzZQpBUkcgVEFSR0VUUExBVEZPUk0KUlVOIGVjaG8gIkhlbGxvLCBXb3JsZCEgVGhpcyBpcyAke1RBUkdFVFBMQVRGT1JNfSIgPiAvaGVsbG8udHh0CkFSRyBCVUlMREtJVF9TQk9NX1NDQU5fU1RBR0U9dHJ1ZQoKRlJPTSBzY3JhdGNoCkNPUFkgLS1mcm9tPWJhc2UgL2hlbGxvLnR4dCAvCg==",
|
||||
"llbDefinition": [
|
||||
{
|
||||
"id": "step0",
|
||||
"op": {
|
||||
"Op": {
|
||||
"source": {
|
||||
"identifier": "git://github.com/docker/github-builder-test.git#bdb96fcfe8cc9e3a54800bc2537a4d4a14f0c5fe",
|
||||
"attrs": {
|
||||
"git.authheadersecret": "GIT_AUTH_HEADER",
|
||||
"git.authtokensecret": "GIT_AUTH_TOKEN",
|
||||
"git.fullurl": "https://github.com/docker/github-builder-test.git"
|
||||
}
|
||||
}
|
||||
},
|
||||
"constraints": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step1",
|
||||
"op": {
|
||||
"Op": {}
|
||||
},
|
||||
"inputs": [
|
||||
"step0:0"
|
||||
]
|
||||
}
|
||||
],
|
||||
"digestMapping": {
|
||||
"sha256:47540f0959d81a7ff2fc9742b9ef0bb37d7eca99c13aa6df83b883d06e808ef2": "step0",
|
||||
"sha256:96933c546ff00debd500304305864192fcb51d348e8c41b6a6e1569a051e66ed": "step1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"layers": {
|
||||
"step0:0": [
|
||||
[
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||
"digest": "sha256:2d35ebdb57d9971fea0cac1582aa78935adf8058b2cc32db163c98822e5dfa1b",
|
||||
"size": 3802452
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"buildkit_completeness": {
|
||||
"request": true,
|
||||
"resolvedDependencies": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,14 @@ describe('getDefinition', () => {
|
||||
['*.output=type=docker', '*.platform=linux/amd64'],
|
||||
undefined,
|
||||
path.join(fixturesDir, 'bake-01-overrides.json')
|
||||
]
|
||||
],
|
||||
[
|
||||
[path.join(fixturesDir, 'bake-03.hcl')],
|
||||
[],
|
||||
[],
|
||||
undefined,
|
||||
path.join(fixturesDir, 'bake-03-default.json')
|
||||
],
|
||||
])('given %p', async (files: string[], targets: string[], overrides: string[], execOptions: ExecOptions | undefined, out: string) => {
|
||||
const bake = new Bake();
|
||||
const expectedDef = <BakeDefinition>JSON.parse(fs.readFileSync(out, {encoding: 'utf-8'}).trim())
|
||||
@@ -103,7 +110,7 @@ describe('getDefinition', () => {
|
||||
targets: targets,
|
||||
overrides: overrides
|
||||
}, execOptions)).toEqual(expectedDef);
|
||||
});
|
||||
}, 30 * 60 * 1000);
|
||||
});
|
||||
|
||||
describe('hasLocalExporter', () => {
|
||||
@@ -114,7 +121,9 @@ describe('hasLocalExporter', () => {
|
||||
"target": {
|
||||
"build": {
|
||||
"output": [
|
||||
"type=docker"
|
||||
{
|
||||
"type": "docker"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -136,7 +145,10 @@ describe('hasLocalExporter', () => {
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
"type=local,dest=./release-out"
|
||||
{
|
||||
"type": "local",
|
||||
"dest": "./release-out"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -148,19 +160,10 @@ describe('hasLocalExporter', () => {
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
"type=tar,dest=/tmp/image.tar"
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
'"type=tar","dest=/tmp/image.tar"',
|
||||
{
|
||||
"type": "tar",
|
||||
"dest": "/tmp/image.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -172,19 +175,10 @@ describe('hasLocalExporter', () => {
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
'" type= local" , dest=./release-out',
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
".",
|
||||
{
|
||||
"type": "local",
|
||||
"dest": "."
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -204,7 +198,10 @@ describe('hasTarExporter', () => {
|
||||
"target": {
|
||||
"reg": {
|
||||
"output": [
|
||||
"type=registry,ref=user/app"
|
||||
{
|
||||
"type": "registry",
|
||||
"ref": "user/app"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -216,7 +213,9 @@ describe('hasTarExporter', () => {
|
||||
"target": {
|
||||
"build": {
|
||||
"output": [
|
||||
"type=docker"
|
||||
{
|
||||
"type": "docker"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -228,7 +227,10 @@ describe('hasTarExporter', () => {
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
"type=local,dest=./release-out"
|
||||
{
|
||||
"type": "local",
|
||||
"dest": "./release-out"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -240,7 +242,10 @@ describe('hasTarExporter', () => {
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
"type=tar,dest=/tmp/image.tar"
|
||||
{
|
||||
"type": "tar",
|
||||
"dest": "/tmp/image.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -252,20 +257,13 @@ describe('hasTarExporter', () => {
|
||||
"target": {
|
||||
"multi": {
|
||||
"output": [
|
||||
"type=docker",
|
||||
"type=tar,dest=/tmp/image.tar"
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
'"type=tar","dest=/tmp/image.tar"',
|
||||
{
|
||||
"type": "docker"
|
||||
},
|
||||
{
|
||||
"type": "tar",
|
||||
"dest": "/tmp/image.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -277,19 +275,10 @@ describe('hasTarExporter', () => {
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
'" type= local" , dest=./release-out',
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
".",
|
||||
{
|
||||
"type": "local",
|
||||
"dest": "."
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -309,7 +298,10 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"reg": {
|
||||
"output": [
|
||||
"type=registry,ref=user/app"
|
||||
{
|
||||
"type": "registry",
|
||||
"ref": "user/app"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -322,7 +314,9 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"build": {
|
||||
"output": [
|
||||
"type=docker"
|
||||
{
|
||||
"type": "docker"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -335,8 +329,13 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"multi": {
|
||||
"output": [
|
||||
"type=docker",
|
||||
"type=tar,dest=/tmp/image.tar"
|
||||
{
|
||||
"type": "docker"
|
||||
},
|
||||
{
|
||||
"type": "tar",
|
||||
"dest": "/tmp/image.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -349,20 +348,10 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
'" type= local" , dest=./release-out'
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false,
|
||||
undefined
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
"type=local,dest=./release-out"
|
||||
{
|
||||
"type": "local",
|
||||
"dest": "./release-out"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -375,7 +364,10 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
"type=tar,dest=/tmp/image.tar"
|
||||
{
|
||||
"type": "tar",
|
||||
"dest": "/tmp/image.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -388,8 +380,13 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"multi": {
|
||||
"output": [
|
||||
"type=docker",
|
||||
"type=tar,dest=/tmp/image.tar"
|
||||
{
|
||||
"type": "docker"
|
||||
},
|
||||
{
|
||||
"type": "tar",
|
||||
"dest": "/tmp/image.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -397,51 +394,14 @@ describe('hasDockerExporter', () => {
|
||||
true,
|
||||
undefined
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
'"type=tar","dest=/tmp/image.tar"'
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false,
|
||||
undefined
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"tar": {
|
||||
"output": [
|
||||
'"type=tar","dest=/tmp/image.tar"'
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false,
|
||||
undefined
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"local": {
|
||||
"output": [
|
||||
'" type= local" , dest=./release-out'
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false,
|
||||
undefined
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"output": [
|
||||
"type=docker"
|
||||
{
|
||||
"type": "docker"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -454,7 +414,9 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"build": {
|
||||
"output": [
|
||||
"type=docker"
|
||||
{
|
||||
"type": "docker"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -467,7 +429,10 @@ describe('hasDockerExporter', () => {
|
||||
"target": {
|
||||
"build": {
|
||||
"output": [
|
||||
"."
|
||||
{
|
||||
"type": "local",
|
||||
"dest": "."
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
@@ -479,3 +444,154 @@ describe('hasDockerExporter', () => {
|
||||
expect(Bake.hasDockerExporter(def, load)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasGitAuthTokenSecret', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"reg": {
|
||||
"secret": [
|
||||
{
|
||||
"id": "A_SECRET",
|
||||
"env": "A_SECRET"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"reg": {
|
||||
"secret": [
|
||||
{
|
||||
"id": "A_SECRET",
|
||||
"env": "A_SECRET"
|
||||
},
|
||||
{
|
||||
"id": "GIT_AUTH_TOKEN"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
],
|
||||
])('given %o returns %p', async (def: BakeDefinition, expected: boolean) => {
|
||||
expect(Bake.hasGitAuthTokenSecret(def)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasProvenanceAttestation', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"attest": [
|
||||
{
|
||||
"type": "provenance",
|
||||
"mode": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"attest": [
|
||||
{
|
||||
"type": "sbom"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"attest": [
|
||||
{
|
||||
"type": "sbom"
|
||||
},
|
||||
{
|
||||
"type": "provenance",
|
||||
"mode": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
]
|
||||
])('given %o returns %p', async (def: BakeDefinition, expected: boolean) => {
|
||||
expect(Bake.hasProvenanceAttestation(def)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasSBOMAttestation', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"attest": [
|
||||
{
|
||||
"type": "provenance",
|
||||
"mode": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
false
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"attest": [
|
||||
{
|
||||
"type": "sbom"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
],
|
||||
[
|
||||
{
|
||||
"target": {
|
||||
"build": {
|
||||
"attest": [
|
||||
{
|
||||
"type": "sbom"
|
||||
},
|
||||
{
|
||||
"type": "provenance",
|
||||
"mode": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
} as unknown as BakeDefinition,
|
||||
true
|
||||
]
|
||||
])('given %o returns %p', async (def: BakeDefinition, expected: boolean) => {
|
||||
expect(Bake.hasSBOMAttestation(def)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -49,7 +49,6 @@ describe('exists', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
const builder = new Builder();
|
||||
await builder.exists('foo');
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx', 'inspect', 'foo'], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
@@ -449,6 +448,101 @@ describe('parseInspect', () => {
|
||||
"all": true,
|
||||
"keepBytes": "94.06GiB",
|
||||
}
|
||||
],
|
||||
"files": {
|
||||
"buildkitd.toml": `debug = true
|
||||
insecure-entitlements = ["network.host", "security.insecure"]
|
||||
trace = true
|
||||
|
||||
[log]
|
||||
format = "text"
|
||||
`,
|
||||
"foo.txt": `foo = bar
|
||||
baz = qux
|
||||
`,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
'inspect12.txt',
|
||||
{
|
||||
"name": "nvidia",
|
||||
"driver": "docker-container",
|
||||
"lastActivity": new Date("2025-02-14T15:57:45.000Z"),
|
||||
"nodes": [
|
||||
{
|
||||
"buildkit": "v0.20.0-rc2-4-gd30d8e22c.m",
|
||||
"buildkitd-flags": "--allow-insecure-entitlement=network.host",
|
||||
"driver-opts": [
|
||||
"image=moby/buildkit:local",
|
||||
],
|
||||
"endpoint": "unix:///var/run/docker.sock",
|
||||
"name": "nvidia0",
|
||||
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6",
|
||||
"status": "running",
|
||||
"features": {
|
||||
"Cache export": true,
|
||||
"Docker exporter": true,
|
||||
"Multi-platform build": true,
|
||||
"OCI exporter": true,
|
||||
},
|
||||
"labels": {
|
||||
"org.mobyproject.buildkit.worker.executor": "oci",
|
||||
"org.mobyproject.buildkit.worker.hostname": "76ac9a510d96",
|
||||
"org.mobyproject.buildkit.worker.network": "host",
|
||||
"org.mobyproject.buildkit.worker.oci.process-mode": "sandbox",
|
||||
"org.mobyproject.buildkit.worker.selinux.enabled": "false",
|
||||
"org.mobyproject.buildkit.worker.snapshotter": "overlayfs",
|
||||
},
|
||||
"devices": [
|
||||
{
|
||||
"annotations": {
|
||||
"foo": "bar",
|
||||
"org.mobyproject.buildkit.device.autoallow": "true"
|
||||
},
|
||||
"autoAllow": true,
|
||||
"name": "nvidia.com/gpu=all"
|
||||
},
|
||||
{
|
||||
"annotations": {
|
||||
"bar": "baz"
|
||||
},
|
||||
"autoAllow": false,
|
||||
"name": "docker.com/gpu=venus"
|
||||
}
|
||||
],
|
||||
"gcPolicy": [
|
||||
{
|
||||
"all": false,
|
||||
"filter": [
|
||||
"type==source.local",
|
||||
"type==exec.cachemount",
|
||||
"type==source.git.checkout"
|
||||
],
|
||||
"keepDuration": "48h0m0s",
|
||||
"maxUsedSpace": "488.3MiB",
|
||||
},
|
||||
{
|
||||
"all": false,
|
||||
"keepDuration": "1440h0m0s",
|
||||
"maxUsedSpace": "93.13GiB",
|
||||
"minFreeSpace": "188.1GiB",
|
||||
"reservedSpace": "9.313GiB",
|
||||
},
|
||||
{
|
||||
"all": false,
|
||||
"maxUsedSpace": "93.13GiB",
|
||||
"minFreeSpace": "188.1GiB",
|
||||
"reservedSpace": "9.313GiB",
|
||||
},
|
||||
{
|
||||
"all": true,
|
||||
"maxUsedSpace": "93.13GiB",
|
||||
"minFreeSpace": "188.1GiB",
|
||||
"reservedSpace": "9.313GiB",
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -91,7 +91,6 @@ describe('isAvailable', () => {
|
||||
standalone: false
|
||||
});
|
||||
await buildx.isAvailable();
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
@@ -103,7 +102,6 @@ describe('isAvailable', () => {
|
||||
standalone: true
|
||||
});
|
||||
await buildx.isAvailable();
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`buildx`, [], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {afterEach, beforeEach, describe, expect, it, jest, test} from '@jest/globals';
|
||||
import {describe, expect, it, test} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
@@ -30,7 +30,49 @@ const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'buildx
|
||||
|
||||
const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) ? describe : describe.skip;
|
||||
|
||||
maybe('exportBuild', () => {
|
||||
maybe('inspect', () => {
|
||||
it('build', async () => {
|
||||
const buildx = new Buildx();
|
||||
const build = new Build({buildx: buildx});
|
||||
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
await expect(
|
||||
(async () => {
|
||||
// prettier-ignore
|
||||
const buildCmd = await buildx.getCommand([
|
||||
'--builder', process.env.CTN_BUILDER_NAME ?? 'default',
|
||||
'build', '-f', path.join(fixturesDir, 'hello.Dockerfile'),
|
||||
'--metadata-file', build.getMetadataFilePath(),
|
||||
fixturesDir
|
||||
]);
|
||||
await Exec.exec(buildCmd.command, buildCmd.args);
|
||||
})()
|
||||
).resolves.not.toThrow();
|
||||
|
||||
const metadata = build.resolveMetadata();
|
||||
expect(metadata).toBeDefined();
|
||||
const buildRef = build.resolveRef(metadata);
|
||||
if (!buildRef) {
|
||||
throw new Error('buildRef is undefined');
|
||||
}
|
||||
const [builderName, nodeName, ref] = buildRef.split('/');
|
||||
expect(builderName).toBeDefined();
|
||||
expect(nodeName).toBeDefined();
|
||||
expect(ref).toBeDefined();
|
||||
|
||||
const history = new History({buildx: buildx});
|
||||
const res = await history.inspect({
|
||||
ref: ref,
|
||||
builder: builderName
|
||||
});
|
||||
|
||||
expect(res).toBeDefined();
|
||||
expect(res?.Name).toBeDefined();
|
||||
expect(res?.Ref).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
maybe('export', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
@@ -50,7 +92,7 @@ maybe('exportBuild', () => {
|
||||
fixturesDir
|
||||
],
|
||||
]
|
||||
])('export build %p', async (_, bargs) => {
|
||||
])('export with build %p', async (_, bargs) => {
|
||||
const buildx = new Buildx();
|
||||
const build = new Build({buildx: buildx});
|
||||
|
||||
@@ -110,7 +152,7 @@ maybe('exportBuild', () => {
|
||||
'hello-matrix'
|
||||
],
|
||||
]
|
||||
])('export bake build %p', async (_, bargs) => {
|
||||
])('export with bake %p', async (_, bargs) => {
|
||||
const buildx = new Buildx();
|
||||
const bake = new Bake({buildx: buildx});
|
||||
|
||||
@@ -145,22 +187,8 @@ maybe('exportBuild', () => {
|
||||
expect(fs.existsSync(exportRes?.dockerbuildFilename)).toBe(true);
|
||||
expect(exportRes?.summaries).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
maybe('exportBuild custom image', () => {
|
||||
const originalEnv = process.env;
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
DOCKER_BUILD_EXPORT_BUILD_IMAGE: 'docker.io/dockereng/export-build:0.2.2'
|
||||
};
|
||||
});
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
it('with custom image', async () => {
|
||||
it('export using container', async () => {
|
||||
const buildx = new Buildx();
|
||||
const build = new Build({buildx: buildx});
|
||||
|
||||
@@ -185,7 +213,8 @@ maybe('exportBuild custom image', () => {
|
||||
|
||||
const history = new History({buildx: buildx});
|
||||
const exportRes = await history.export({
|
||||
refs: [buildRef ?? '']
|
||||
refs: [buildRef ?? ''],
|
||||
useContainer: true
|
||||
});
|
||||
|
||||
expect(exportRes).toBeDefined();
|
||||
|
||||
78
__tests__/buildx/imagetools.test.itg.ts
Normal file
78
__tests__/buildx/imagetools.test.itg.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import {ImageTools} from '../../src/buildx/imagetools';
|
||||
|
||||
import {Manifest as ImageToolsManifest} from '../../src/types/buildx/imagetools';
|
||||
import {Image} from '../../src/types/oci/config';
|
||||
import {Descriptor} from '../../src/types/oci/descriptor';
|
||||
|
||||
const fixturesDir = path.join(__dirname, '..', '.fixtures');
|
||||
|
||||
const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) ? describe : describe.skip;
|
||||
|
||||
maybe('inspectImage', () => {
|
||||
it('inspect single platform', async () => {
|
||||
const image = await new ImageTools().inspectImage('moby/buildkit:latest@sha256:5769c54b98840147b74128f38fb0b0a049e24b11a75bd81664131edd2854593f');
|
||||
const expectedImage = <Image>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'imagetools-01.json'), {encoding: 'utf-8'}).trim());
|
||||
expect(image).toEqual(expectedImage);
|
||||
});
|
||||
it('inspect multi platform', async () => {
|
||||
const image = await new ImageTools().inspectImage('moby/buildkit:latest@sha256:86c0ad9d1137c186e9d455912167df20e530bdf7f7c19de802e892bb8ca16552');
|
||||
const expectedImage = <Record<string, Image>>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'imagetools-02.json'), {encoding: 'utf-8'}).trim());
|
||||
expect(image).toEqual(expectedImage);
|
||||
});
|
||||
});
|
||||
|
||||
maybe('inspectManifest', () => {
|
||||
it('inspect descriptor', async () => {
|
||||
const manifest = await new ImageTools().inspectManifest('moby/buildkit:latest@sha256:dccc69dd895968c4f21aa9e43e715f25f0cedfce4b17f1014c88c307928e22fc');
|
||||
const expectedManifest = <Descriptor>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'imagetools-03.json'), {encoding: 'utf-8'}).trim());
|
||||
expect(manifest).toEqual(expectedManifest);
|
||||
});
|
||||
it('inspect index', async () => {
|
||||
const manifest = await new ImageTools().inspectManifest('moby/buildkit:latest@sha256:79cc6476ab1a3371c9afd8b44e7c55610057c43e18d9b39b68e2b0c2475cc1b6');
|
||||
const expectedManifest = <ImageToolsManifest>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'imagetools-04.json'), {encoding: 'utf-8'}).trim());
|
||||
expect(manifest).toEqual(expectedManifest);
|
||||
});
|
||||
});
|
||||
|
||||
maybe('attestationDescriptors', () => {
|
||||
it('returns buildkit attestations descriptors', async () => {
|
||||
const attestations = await new ImageTools().attestationDescriptors('moby/buildkit:latest@sha256:79cc6476ab1a3371c9afd8b44e7c55610057c43e18d9b39b68e2b0c2475cc1b6');
|
||||
const expectedAttestations = <Array<Descriptor>>JSON.parse(fs.readFileSync(path.join(fixturesDir, 'imagetools-05.json'), {encoding: 'utf-8'}).trim());
|
||||
expect(attestations).toEqual(expectedAttestations);
|
||||
});
|
||||
});
|
||||
|
||||
maybe('attestationDigests', () => {
|
||||
it('returns buildkit attestations digests', async () => {
|
||||
const digests = await new ImageTools().attestationDigests('moby/buildkit:latest@sha256:79cc6476ab1a3371c9afd8b44e7c55610057c43e18d9b39b68e2b0c2475cc1b6');
|
||||
// prettier-ignore
|
||||
expect(digests).toEqual([
|
||||
'sha256:2ba4ad6eae1efcafee73a971953093c7c32b6938f2f9fd4998c8bf4d0fbe76f2',
|
||||
'sha256:0709528fae1747ce17638ad2978ee7936b38a294136eaadaf692e415f64b1e03',
|
||||
'sha256:241b7159129d53923c89708bcc052b3398086a826519896be2f025545916e43e',
|
||||
'sha256:97f4a222a7992dba6dc1a43991d0cca1fcffdc25593033c6a3a7ff14c8651cbf',
|
||||
'sha256:aa933713d8094b2708120e889acb6f7153dee4e0f3298ccd3e37a584cd0c260d',
|
||||
'sha256:d95ca72d4f2a6bc416d4b2f3003b2af9d5f4dea99acec6ad3ab0c2082000a98c'
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -37,19 +37,17 @@ describe('download', () => {
|
||||
['latest', true]
|
||||
])(
|
||||
'acquires %p of buildx (standalone: %p)', async (version, standalone) => {
|
||||
const install = new Install({standalone: standalone});
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
let buildxBin: string;
|
||||
if (standalone) {
|
||||
buildxBin = await install.installStandalone(toolPath, tmpDir);
|
||||
} else {
|
||||
buildxBin = await install.installPlugin(toolPath, tmpDir);
|
||||
}
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
},
|
||||
100000
|
||||
);
|
||||
const install = new Install({standalone: standalone});
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
let buildxBin: string;
|
||||
if (standalone) {
|
||||
buildxBin = await install.installStandalone(toolPath, tmpDir);
|
||||
} else {
|
||||
buildxBin = await install.installPlugin(toolPath, tmpDir);
|
||||
}
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
@@ -61,7 +59,7 @@ describe('download', () => {
|
||||
const install = new Install({standalone: false});
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
});
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
@@ -72,7 +70,7 @@ describe('download', () => {
|
||||
const install = new Install({standalone: false});
|
||||
const toolPath = await install.download(version, true);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
});
|
||||
}, 100000);
|
||||
|
||||
// TODO: add tests for arm
|
||||
// prettier-ignore
|
||||
@@ -87,18 +85,15 @@ describe('download', () => {
|
||||
['linux', 's390x'],
|
||||
])(
|
||||
'acquires buildx for %s/%s', async (os, arch) => {
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const buildxBin = await install.download('latest');
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
},
|
||||
100000
|
||||
);
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const buildxBin = await install.download('latest');
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('build', () => {
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('builds refs/pull/648/head', async () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.build('https://github.com/docker/buildx.git#refs/pull/648/head');
|
||||
@@ -107,7 +102,6 @@ describe('build', () => {
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('builds 67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', async () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.build('https://github.com/docker/buildx.git#67bd6f4dc82a9cd96f34133dab3f6f7af803bb14');
|
||||
@@ -123,7 +117,12 @@ describe('getDownloadVersion', () => {
|
||||
expect(version.key).toEqual('official');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/buildx/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-releases.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns official v0.10.1 download version', async () => {
|
||||
@@ -131,7 +130,12 @@ describe('getDownloadVersion', () => {
|
||||
expect(version.key).toEqual('official');
|
||||
expect(version.version).toEqual('v0.10.1');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/buildx/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-releases.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns cloud latest download version', async () => {
|
||||
@@ -139,7 +143,12 @@ describe('getDownloadVersion', () => {
|
||||
expect(version.key).toEqual('cloud');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/buildx-desktop/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-lab-releases.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns cloud v0.11.2-desktop.2 download version', async () => {
|
||||
@@ -147,7 +156,12 @@ describe('getDownloadVersion', () => {
|
||||
expect(version.key).toEqual('cloud');
|
||||
expect(version.version).toEqual('v0.11.2-desktop.2');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/buildx-desktop/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-lab-releases.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('returns cloud for lab version', async () => {
|
||||
@@ -155,7 +169,12 @@ describe('getDownloadVersion', () => {
|
||||
expect(version.key).toEqual('cloud');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/buildx-desktop/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-lab-releases.json'
|
||||
});
|
||||
});
|
||||
|
||||
it('unknown repo', async () => {
|
||||
@@ -191,6 +210,6 @@ describe('getRelease', () => {
|
||||
|
||||
it('unknown release', async () => {
|
||||
const version = await Install.getDownloadVersion('foo');
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Buildx release foo in https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-releases.json'));
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Buildx release foo in releases JSON'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,13 +20,27 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import {Cache} from '../src/cache';
|
||||
import {Util} from '../src/util';
|
||||
|
||||
const fixturesDir = path.join(__dirname, '.fixtures');
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'cache-itg-'));
|
||||
|
||||
describe('cache', () => {
|
||||
it('github-repo', async () => {
|
||||
const r = (Math.random() + 1).toString(36).substring(7);
|
||||
it('caches github-repo', async () => {
|
||||
const r = Util.generateRandomString();
|
||||
const htcName = `cache-test-github-repo-${r}`;
|
||||
const c = new Cache({
|
||||
htcName: htcName,
|
||||
htcVersion: `v1.0.0+${r}`,
|
||||
baseCacheDir: path.join(tmpDir, '.cache-test'),
|
||||
cacheFile: 'github-repo.json'
|
||||
});
|
||||
expect(await c.save(path.join(fixturesDir, 'github-repo.json'), true)).not.toEqual('');
|
||||
expect(await c.find()).not.toEqual('');
|
||||
});
|
||||
|
||||
it('caches github-repo with post state', async () => {
|
||||
const r = Util.generateRandomString();
|
||||
const htcName = `cache-test-github-repo-${r}`;
|
||||
const c = new Cache({
|
||||
htcName: htcName,
|
||||
@@ -35,6 +49,7 @@ describe('cache', () => {
|
||||
cacheFile: 'github-repo.json'
|
||||
});
|
||||
expect(await c.save(path.join(fixturesDir, 'github-repo.json'))).not.toEqual('');
|
||||
expect(await Cache.post()).not.toBeNull();
|
||||
expect(await c.find()).not.toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
107
__tests__/compose/compose.test.ts
Normal file
107
__tests__/compose/compose.test.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, jest, test, afterEach} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import {Context} from '../../src/context';
|
||||
import {Exec} from '../../src/exec';
|
||||
|
||||
import {Compose} from '../../src/compose/compose';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'compose-compose-'));
|
||||
const tmpName = path.join(tmpDir, '.tmpname-jest');
|
||||
|
||||
jest.spyOn(Context, 'tmpDir').mockImplementation((): string => {
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
return tmpDir;
|
||||
});
|
||||
|
||||
jest.spyOn(Context, 'tmpName').mockImplementation((): string => {
|
||||
return tmpName;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
rimraf.sync(tmpDir);
|
||||
});
|
||||
|
||||
describe('isAvailable', () => {
|
||||
it('docker cli', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
const compose = new Compose({
|
||||
standalone: false
|
||||
});
|
||||
await compose.isAvailable();
|
||||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['compose'], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
it('standalone', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
const compose = new Compose({
|
||||
standalone: true
|
||||
});
|
||||
await compose.isAvailable();
|
||||
expect(execSpy).toHaveBeenCalledWith(`compose`, [], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('printVersion', () => {
|
||||
it('docker cli', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'exec');
|
||||
const compose = new Compose({
|
||||
standalone: false
|
||||
});
|
||||
await compose.printVersion();
|
||||
expect(execSpy).toHaveBeenCalledWith(`docker`, ['compose', 'version'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
});
|
||||
it('standalone', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'exec');
|
||||
const compose = new Compose({
|
||||
standalone: true
|
||||
});
|
||||
await compose.printVersion();
|
||||
expect(execSpy).toHaveBeenCalledWith(`compose`, ['version'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('version', () => {
|
||||
it('valid', async () => {
|
||||
const compose = new Compose();
|
||||
expect(semver.valid(await compose.version())).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseVersion', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['Docker Compose version v2.31.0', '2.31.0'],
|
||||
])('given %p', async (stdout, expected) => {
|
||||
expect(Compose.parseVersion(stdout)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
42
__tests__/compose/install.test.itg.ts
Normal file
42
__tests__/compose/install.test.itg.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
|
||||
import {Install} from '../../src/compose/install';
|
||||
|
||||
const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) ? describe : describe.skip;
|
||||
|
||||
maybe('download', () => {
|
||||
// prettier-ignore
|
||||
test.each(['latest'])(
|
||||
'install compose %s', async (version) => {
|
||||
await expect((async () => {
|
||||
const install = new Install({
|
||||
standalone: true
|
||||
});
|
||||
const toolPath = await install.download(version);
|
||||
if (!fs.existsSync(toolPath)) {
|
||||
throw new Error('toolPath does not exist');
|
||||
}
|
||||
const binPath = await install.installStandalone(toolPath);
|
||||
if (!fs.existsSync(binPath)) {
|
||||
throw new Error('binPath does not exist');
|
||||
}
|
||||
})()).resolves.not.toThrow();
|
||||
}, 60000);
|
||||
});
|
||||
177
__tests__/compose/install.test.ts
Normal file
177
__tests__/compose/install.test.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, jest, test, afterEach} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import osm = require('os');
|
||||
|
||||
import {Install} from '../../src/compose/install';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'compose-install-'));
|
||||
|
||||
afterEach(function () {
|
||||
rimraf.sync(tmpDir);
|
||||
});
|
||||
|
||||
describe('download', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['v2.31.0', false],
|
||||
['v2.32.4', true],
|
||||
['latest', true]
|
||||
])(
|
||||
'acquires %p of compose (standalone: %p)', async (version, standalone) => {
|
||||
const install = new Install({standalone: standalone});
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
let composeBin: string;
|
||||
if (standalone) {
|
||||
composeBin = await install.installStandalone(toolPath, tmpDir);
|
||||
} else {
|
||||
composeBin = await install.installPlugin(toolPath, tmpDir);
|
||||
}
|
||||
expect(fs.existsSync(composeBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
// following versions are already cached to htc from previous test cases
|
||||
['v2.31.0'],
|
||||
['v2.32.4'],
|
||||
])(
|
||||
'acquires %p of compose with cache', async (version) => {
|
||||
const install = new Install({standalone: false});
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['v2.27.1'],
|
||||
['v2.28.0'],
|
||||
])(
|
||||
'acquires %p of compose without cache', async (version) => {
|
||||
const install = new Install({standalone: false});
|
||||
const toolPath = await install.download(version, true);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// TODO: add tests for arm
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['win32', 'x64'],
|
||||
['win32', 'arm64'],
|
||||
['darwin', 'x64'],
|
||||
['darwin', 'arm64'],
|
||||
['linux', 'x64'],
|
||||
['linux', 'arm64'],
|
||||
['linux', 'ppc64'],
|
||||
['linux', 's390x'],
|
||||
])(
|
||||
'acquires compose for %s/%s', async (os, arch) => {
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const composeBin = await install.download('latest');
|
||||
expect(fs.existsSync(composeBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('getDownloadVersion', () => {
|
||||
it('returns official latest download version', async () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
expect(version.key).toEqual('official');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/compose/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/compose-releases.json'
|
||||
});
|
||||
});
|
||||
it('returns official v2.24.3 download version', async () => {
|
||||
const version = await Install.getDownloadVersion('v2.24.3');
|
||||
expect(version.key).toEqual('official');
|
||||
expect(version.version).toEqual('v2.24.3');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/compose/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/compose-releases.json'
|
||||
});
|
||||
});
|
||||
it('returns cloud latest download version', async () => {
|
||||
const version = await Install.getDownloadVersion('cloud:latest');
|
||||
expect(version.key).toEqual('cloud');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/compose-desktop/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/compose-lab-releases.json'
|
||||
});
|
||||
});
|
||||
it('returns cloud v2.27.1-desktop.1 download version', async () => {
|
||||
const version = await Install.getDownloadVersion('cloud:v2.27.1-desktop.1');
|
||||
expect(version.key).toEqual('cloud');
|
||||
expect(version.version).toEqual('v2.27.1-desktop.1');
|
||||
expect(version.downloadURL).toEqual('https://github.com/docker/compose-desktop/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/compose-lab-releases.json'
|
||||
});
|
||||
});
|
||||
it('unknown repo', async () => {
|
||||
await expect(Install.getDownloadVersion('foo:bar')).rejects.toThrow(new Error('Cannot find compose version for foo:bar'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRelease', () => {
|
||||
it('returns latest official GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.tag_name).not.toEqual('');
|
||||
});
|
||||
it('returns v2.24.3 official GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('v2.24.3');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.id).toEqual(138380726);
|
||||
expect(release?.tag_name).toEqual('v2.24.3');
|
||||
expect(release?.html_url).toEqual('https://github.com/docker/compose/releases/tag/v2.24.3');
|
||||
});
|
||||
it('returns v2.27.1-desktop.1 cloud GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('cloud:v2.27.1-desktop.1');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.id).toEqual(157591108);
|
||||
expect(release?.tag_name).toEqual('v2.27.1-desktop.1');
|
||||
expect(release?.html_url).toEqual('https://github.com/docker/compose-desktop/releases/tag/v2.27.1-desktop.1');
|
||||
});
|
||||
it('unknown release', async () => {
|
||||
const version = await Install.getDownloadVersion('foo');
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Compose release foo in releases JSON'));
|
||||
});
|
||||
});
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, jest, it, afterEach} from '@jest/globals';
|
||||
import {describe, expect, jest, it, afterEach, beforeEach, test} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
@@ -44,6 +44,34 @@ describe('gitRef', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseGitRef', () => {
|
||||
const originalEnv = process.env;
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
DOCKER_GIT_CONTEXT_PR_HEAD_REF: ''
|
||||
};
|
||||
});
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['refs/heads/master', '860c1904a1ce19322e91ac35af1ab07466440c37', false, '860c1904a1ce19322e91ac35af1ab07466440c37'],
|
||||
['master', '860c1904a1ce19322e91ac35af1ab07466440c37', false, '860c1904a1ce19322e91ac35af1ab07466440c37'],
|
||||
['refs/pull/15/merge', '860c1904a1ce19322e91ac35af1ab07466440c37', false, 'refs/pull/15/merge'],
|
||||
['refs/heads/master', '', false, 'refs/heads/master'],
|
||||
['master', '', false, 'master'],
|
||||
['refs/tags/v1.0.0', '', false, 'refs/tags/v1.0.0'],
|
||||
['refs/pull/15/merge', '', false, 'refs/pull/15/merge'],
|
||||
['refs/pull/15/merge', '', true, 'refs/pull/15/head'],
|
||||
])('given %p and %p, should return %p', async (ref: string, sha: string, prHeadRef: boolean, expected: string) => {
|
||||
process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF = prHeadRef ? 'true' : '';
|
||||
expect(Context.parseGitRef(ref, sha)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('gitContext', () => {
|
||||
it('returns refs/heads/master', async () => {
|
||||
expect(Context.gitContext()).toEqual('https://github.com/docker/actions-toolkit.git#refs/heads/master');
|
||||
|
||||
89
__tests__/cosign/cosign.test.ts
Normal file
89
__tests__/cosign/cosign.test.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, jest, test} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import {Exec} from '../../src/exec';
|
||||
import {Cosign} from '../../src/cosign/cosign';
|
||||
|
||||
const fixturesDir = path.join(__dirname, '..', '.fixtures');
|
||||
|
||||
describe('isAvailable', () => {
|
||||
it('checks Cosign is available', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
const cosign = new Cosign();
|
||||
await cosign.isAvailable();
|
||||
expect(execSpy).toHaveBeenCalledWith(`cosign`, [], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('printVersion', () => {
|
||||
it('prints Cosign version', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'exec');
|
||||
const cosign = new Cosign();
|
||||
await cosign.printVersion();
|
||||
expect(execSpy).toHaveBeenCalledWith(`cosign`, ['version', '--json'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('version', () => {
|
||||
it('valid', async () => {
|
||||
const cosign = new Cosign();
|
||||
expect(semver.valid(await cosign.version())).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('versionSatisfies', () => {
|
||||
test.each([
|
||||
['v0.4.1', '>=0.3.2', true],
|
||||
['v0.8.0', '>0.6.0', true],
|
||||
['v0.8.0', '<0.3.0', false]
|
||||
])('given %p', async (version, range, expected) => {
|
||||
const cosign = new Cosign();
|
||||
expect(await cosign.versionSatisfies(range, version)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseCommandOutput', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[path.join(fixturesDir, 'cosign', 'sign-output1.txt')],
|
||||
[path.join(fixturesDir, 'cosign', 'sign-output2.txt')],
|
||||
[path.join(fixturesDir, 'cosign', 'sign-output3.txt')],
|
||||
])('parsing %p', async (fixturePath: string) => {
|
||||
const signResult = Cosign.parseCommandOutput(fs.readFileSync(fixturePath, 'utf-8'));
|
||||
expect(signResult).toBeDefined();
|
||||
expect(signResult.bundle).toBeDefined();
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[path.join(fixturesDir, 'cosign', 'verify-output-err1.txt')],
|
||||
])('parsing %p', async (fixturePath: string) => {
|
||||
const signResult = Cosign.parseCommandOutput(fs.readFileSync(fixturePath, 'utf-8'));
|
||||
expect(signResult).toBeDefined();
|
||||
expect(signResult.bundle).toBeUndefined();
|
||||
expect(signResult.errors).toBeDefined();
|
||||
});
|
||||
});
|
||||
53
__tests__/cosign/install.test.itg.ts
Normal file
53
__tests__/cosign/install.test.itg.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
|
||||
import {Install} from '../../src/cosign/install';
|
||||
|
||||
const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu')) ? describe : describe.skip;
|
||||
|
||||
describe('download', () => {
|
||||
// prettier-ignore
|
||||
test.each(['latest'])(
|
||||
'install cosign %s', async (version) => {
|
||||
await expect((async () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download({
|
||||
version: version,
|
||||
verifySignature: true
|
||||
});
|
||||
if (!fs.existsSync(toolPath)) {
|
||||
throw new Error('toolPath does not exist');
|
||||
}
|
||||
const binPath = await install.install(toolPath);
|
||||
if (!fs.existsSync(binPath)) {
|
||||
throw new Error('binPath does not exist');
|
||||
}
|
||||
})()).resolves.not.toThrow();
|
||||
}, 60000);
|
||||
});
|
||||
|
||||
maybe('build', () => {
|
||||
it.skip('builds refs/pull/4492/head', async () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.build('https://github.com/sigstore/cosign.git#refs/pull/4492/head');
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
const buildxBin = await install.install(toolPath);
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
}, 500000);
|
||||
});
|
||||
137
__tests__/cosign/install.test.ts
Normal file
137
__tests__/cosign/install.test.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, jest, test, afterEach} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import osm = require('os');
|
||||
|
||||
import {Install} from '../../src/cosign/install';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'cosign-install-'));
|
||||
|
||||
afterEach(function () {
|
||||
rimraf.sync(tmpDir);
|
||||
});
|
||||
|
||||
describe('download', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['v2.6.1'],
|
||||
['v3.0.1'],
|
||||
['latest']
|
||||
])(
|
||||
'acquires %p of cosign', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download({version});
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
const cosignBin = await install.install(toolPath, tmpDir);
|
||||
expect(fs.existsSync(cosignBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
// following versions are already cached to htc from previous test cases
|
||||
['v2.6.1'],
|
||||
['v3.0.1'],
|
||||
])(
|
||||
'acquires %p of cosign with cache', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download({version});
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['v2.5.3'],
|
||||
['v2.6.0'],
|
||||
])(
|
||||
'acquires %p of cosign without cache', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download({
|
||||
version: version,
|
||||
ghaNoCache: true
|
||||
});
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// TODO: add tests for arm
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['win32', 'x64'],
|
||||
['darwin', 'x64'],
|
||||
['darwin', 'arm64'],
|
||||
['linux', 'x64'],
|
||||
['linux', 'arm64']
|
||||
])(
|
||||
'acquires undock for %s/%s', async (os, arch) => {
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const cosignBin = await install.download({
|
||||
version: 'latest'
|
||||
});
|
||||
expect(fs.existsSync(cosignBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('getDownloadVersion', () => {
|
||||
it('returns latest download version', async () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/sigstore/cosign/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/cosign-releases.json'
|
||||
});
|
||||
});
|
||||
it('returns v3.0.2 download version', async () => {
|
||||
const version = await Install.getDownloadVersion('v3.0.2');
|
||||
expect(version.version).toEqual('v3.0.2');
|
||||
expect(version.downloadURL).toEqual('https://github.com/sigstore/cosign/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/cosign-releases.json'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRelease', () => {
|
||||
it('returns latest GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.tag_name).not.toEqual('');
|
||||
});
|
||||
it('returns v3.0.2 GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('v3.0.2');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.id).toEqual(253720294);
|
||||
expect(release?.tag_name).toEqual('v3.0.2');
|
||||
expect(release?.html_url).toEqual('https://github.com/sigstore/cosign/releases/tag/v3.0.2');
|
||||
});
|
||||
it('unknown release', async () => {
|
||||
const version = await Install.getDownloadVersion('foo');
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Cosign release foo in releases JSON'));
|
||||
});
|
||||
});
|
||||
@@ -14,17 +14,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, test, expect} from '@jest/globals';
|
||||
import {beforeAll, describe, test, expect} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import {Install, InstallSource, InstallSourceArchive, InstallSourceImage} from '../../src/docker/install';
|
||||
import {Docker} from '../../src/docker/docker';
|
||||
import {Install as RegclientInstall} from '../../src/regclient/install';
|
||||
import {Install as UndockInstall} from '../../src/undock/install';
|
||||
import {Exec} from '../../src/exec';
|
||||
|
||||
const tmpDir = () => fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'docker-install-itg-'));
|
||||
|
||||
beforeAll(async () => {
|
||||
const undockInstall = new UndockInstall();
|
||||
const undockBinPath = await undockInstall.download('v0.10.0', true);
|
||||
await undockInstall.install(undockBinPath);
|
||||
|
||||
const regclientInstall = new RegclientInstall();
|
||||
const regclientBinPath = await regclientInstall.download('v0.8.2', true);
|
||||
await regclientInstall.install(regclientBinPath);
|
||||
}, 100000);
|
||||
|
||||
describe('root', () => {
|
||||
// prettier-ignore
|
||||
test.each(getSources(true))(
|
||||
@@ -133,11 +145,12 @@ async function ensureNoSystemContainerd() {
|
||||
function getSources(root: boolean): Array<InstallSource> {
|
||||
const dockerInstallType = process.env.DOCKER_INSTALL_TYPE;
|
||||
const dockerInstallVersion = process.env.DOCKER_INSTALL_VERSION;
|
||||
const dockerInstallChannel = process.env.DOCKER_INSTALL_CHANNEL || 'stable';
|
||||
if (dockerInstallType && dockerInstallVersion) {
|
||||
if (dockerInstallType === 'archive') {
|
||||
// prettier-ignore
|
||||
return [
|
||||
{ type: dockerInstallType, version: dockerInstallVersion, channel: 'stable'} as InstallSourceArchive
|
||||
{ type: dockerInstallType, version: dockerInstallVersion, channel: dockerInstallChannel} as InstallSourceArchive
|
||||
];
|
||||
} else {
|
||||
// prettier-ignore
|
||||
@@ -153,7 +166,8 @@ function getSources(root: boolean): Array<InstallSource> {
|
||||
{type: 'image', tag: 'master'} as InstallSourceImage,
|
||||
{type: 'image', tag: 'latest'} as InstallSourceImage,
|
||||
{type: 'archive', version: 'v26.1.4', channel: 'stable'} as InstallSourceArchive,
|
||||
{type: 'archive', version: 'latest', channel: 'stable'} as InstallSourceArchive
|
||||
{type: 'archive', version: 'latest', channel: 'stable'} as InstallSourceArchive,
|
||||
{type: 'archive', version: 'v29.0.0-rc.1', channel: 'test'} as InstallSourceArchive
|
||||
];
|
||||
} else {
|
||||
// prettier-ignore
|
||||
|
||||
@@ -51,6 +51,7 @@ describe('download', () => {
|
||||
[archive('v20.10.22', 'stable'), 'linux'],
|
||||
[archive('v20.10.22', 'stable'), 'darwin'],
|
||||
[archive('v20.10.22', 'stable'), 'win32'],
|
||||
[archive('v29.0.0-rc.1', 'test'), 'linux'],
|
||||
|
||||
[image('master'), 'linux'],
|
||||
[image('master'), 'win32'],
|
||||
@@ -60,9 +61,10 @@ describe('download', () => {
|
||||
])(
|
||||
'acquires %p of docker (%s)', async (source, platformOS) => {
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => platformOS as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => 'x64');
|
||||
const install = new Install({
|
||||
source: source,
|
||||
runDir: tmpDir,
|
||||
runDir: tmpDir
|
||||
});
|
||||
const toolPath = await install.download();
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
@@ -76,7 +78,7 @@ describe('getRelease', () => {
|
||||
expect(release?.tag_name).not.toEqual('');
|
||||
});
|
||||
|
||||
it('returns v23.0.0 buildx GitHub release', async () => {
|
||||
it('returns v23.0.0 docker GitHub release', async () => {
|
||||
const release = await Install.getRelease('v23.0.0');
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.id).toEqual(91109643);
|
||||
@@ -84,8 +86,16 @@ describe('getRelease', () => {
|
||||
expect(release?.html_url).toEqual('https://github.com/moby/moby/releases/tag/v23.0.0');
|
||||
});
|
||||
|
||||
it('returns v29.0.0-rc.1 docker GitHub release', async () => {
|
||||
const release = await Install.getRelease('v29.0.0-rc.1');
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.id).toEqual(252020476);
|
||||
expect(release?.tag_name).toEqual('docker-v29.0.0-rc.1');
|
||||
expect(release?.html_url).toEqual('https://github.com/moby/moby/releases/tag/docker-v29.0.0-rc.1');
|
||||
});
|
||||
|
||||
it('unknown release', async () => {
|
||||
await expect(Install.getRelease('foo')).rejects.toThrow(new Error('Cannot find Docker release foo in https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/docker-releases.json'));
|
||||
await expect(Install.getRelease('foo')).rejects.toThrow(new Error('Cannot find Docker release foo in releases JSON'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('isInsideWorkTree', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
try {
|
||||
await Git.isInsideWorkTree();
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
expect(execSpy).toHaveBeenCalledWith(`git`, ['rev-parse', '--is-inside-work-tree'], {
|
||||
@@ -81,7 +81,7 @@ describe('remoteURL', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
try {
|
||||
await Git.remoteURL();
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
expect(execSpy).toHaveBeenCalledWith(`git`, ['remote', 'get-url', 'origin'], {
|
||||
@@ -233,6 +233,208 @@ describe('ref', () => {
|
||||
|
||||
expect(ref).toEqual('refs/heads/test');
|
||||
});
|
||||
|
||||
it('returns mocked detached branch ref checked out by SHA', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'HEAD, origin/feature-branch';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
const ref = await Git.ref();
|
||||
|
||||
expect(ref).toEqual('refs/heads/feature-branch');
|
||||
});
|
||||
|
||||
it('infers ref from local branch when detached HEAD returns only "HEAD"', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'HEAD';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/heads/':
|
||||
result = 'refs/heads/main\nrefs/heads/develop';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
const ref = await Git.ref();
|
||||
|
||||
expect(ref).toEqual('refs/heads/main');
|
||||
});
|
||||
|
||||
it('infers ref from local branch when detached HEAD returns only "grafted, HEAD"', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'grafted, HEAD';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/heads/':
|
||||
result = 'refs/heads/main\nrefs/heads/develop';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
const ref = await Git.ref();
|
||||
|
||||
expect(ref).toEqual('refs/heads/main');
|
||||
});
|
||||
|
||||
it('infers ref from remote branch when no local branch contains HEAD', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'HEAD';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/heads/':
|
||||
result = '';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/remotes/':
|
||||
result = 'refs/remotes/origin/feature';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
const ref = await Git.ref();
|
||||
|
||||
expect(ref).toEqual('refs/heads/feature');
|
||||
});
|
||||
|
||||
it('infers ref from tag when no branch contains HEAD', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'HEAD';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/heads/':
|
||||
result = '';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/remotes/':
|
||||
result = '';
|
||||
break;
|
||||
case 'git tag --contains HEAD':
|
||||
result = 'v1.0.0\nv0.9.0';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
const ref = await Git.ref();
|
||||
|
||||
expect(ref).toEqual('refs/tags/v1.0.0');
|
||||
});
|
||||
|
||||
it('throws error when cannot infer ref from detached HEAD', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'HEAD';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/heads/':
|
||||
result = '';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/remotes/':
|
||||
result = '';
|
||||
break;
|
||||
case 'git tag --contains HEAD':
|
||||
result = '';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
await expect(Git.ref()).rejects.toThrow('Cannot infer ref from detached HEAD');
|
||||
});
|
||||
|
||||
it('handles remote ref without branch pattern when inferring from remote', async () => {
|
||||
jest.spyOn(Exec, 'getExecOutput').mockImplementation((cmd, args): Promise<ExecOutput> => {
|
||||
const fullCmd = `${cmd} ${args?.join(' ')}`;
|
||||
let result = '';
|
||||
switch (fullCmd) {
|
||||
case 'git branch --show-current':
|
||||
result = '';
|
||||
break;
|
||||
case 'git show -s --pretty=%D':
|
||||
result = 'HEAD';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/heads/':
|
||||
result = '';
|
||||
break;
|
||||
case 'git for-each-ref --format=%(refname) --contains HEAD --sort=-committerdate refs/remotes/':
|
||||
result = 'refs/remotes/unusual-format';
|
||||
break;
|
||||
}
|
||||
return Promise.resolve({
|
||||
stdout: result,
|
||||
stderr: '',
|
||||
exitCode: 0
|
||||
});
|
||||
});
|
||||
|
||||
const ref = await Git.ref();
|
||||
|
||||
expect(ref).toEqual('refs/remotes/unusual-format');
|
||||
});
|
||||
});
|
||||
|
||||
describe('fullCommit', () => {
|
||||
@@ -240,7 +442,7 @@ describe('fullCommit', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
try {
|
||||
await Git.fullCommit();
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
expect(execSpy).toHaveBeenCalledWith(`git`, ['show', '--format=%H', 'HEAD', '--quiet', '--'], {
|
||||
@@ -255,7 +457,7 @@ describe('shortCommit', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
try {
|
||||
await Git.shortCommit();
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
expect(execSpy).toHaveBeenCalledWith(`git`, ['show', '--format=%h', 'HEAD', '--quiet', '--'], {
|
||||
@@ -270,7 +472,7 @@ describe('tag', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
try {
|
||||
await Git.tag();
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
expect(execSpy).toHaveBeenCalledWith(`git`, ['tag', '--points-at', 'HEAD', '--sort', '-version:creatordate'], {
|
||||
|
||||
@@ -25,6 +25,7 @@ import {Build} from '../src/buildx/build';
|
||||
import {Exec} from '../src/exec';
|
||||
import {GitHub} from '../src/github';
|
||||
import {History} from '../src/buildx/history';
|
||||
import {Util} from '../src/util';
|
||||
|
||||
const fixturesDir = path.join(__dirname, '.fixtures');
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'github-itg-'));
|
||||
@@ -33,8 +34,10 @@ const maybe = !process.env.GITHUB_ACTIONS || (process.env.GITHUB_ACTIONS === 'tr
|
||||
|
||||
maybe('uploadArtifact', () => {
|
||||
it('uploads an artifact', async () => {
|
||||
const filename = path.join(tmpDir, `github-repo-${Util.generateRandomString()}.json`);
|
||||
fs.copyFileSync(path.join(fixturesDir, `github-repo.json`), filename);
|
||||
const res = await GitHub.uploadArtifact({
|
||||
filename: path.join(fixturesDir, 'github-repo.json'),
|
||||
filename: filename,
|
||||
mimeType: 'application/json',
|
||||
retentionDays: 1
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, jest, it, beforeEach, afterEach} from '@jest/globals';
|
||||
import {describe, expect, jest, it, beforeEach, afterEach, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
@@ -43,6 +43,29 @@ describe('context', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('releases', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['.github/buildx-lab-releases.json'],
|
||||
['.github/buildx-releases.json'],
|
||||
['.github/compose-lab-releases.json'],
|
||||
['.github/compose-releases.json'],
|
||||
['.github/docker-releases.json'],
|
||||
['.github/regclient-releases.json'],
|
||||
['.github/undock-releases.json'],
|
||||
])('returns %p', async (path: string) => {
|
||||
const github = new GitHub();
|
||||
const releases = await github.releases('App', {
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: path
|
||||
});
|
||||
expect(releases).toBeDefined();
|
||||
expect(Object.keys(releases).length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('serverURL', () => {
|
||||
const originalEnv = process.env;
|
||||
beforeEach(() => {
|
||||
@@ -118,6 +141,7 @@ describe('actionsRuntimeToken', () => {
|
||||
it('malformed', async () => {
|
||||
process.env.ACTIONS_RUNTIME_TOKEN = 'foo';
|
||||
expect(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
GitHub.actionsRuntimeToken;
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
38
__tests__/regclient/install.test.itg.ts
Normal file
38
__tests__/regclient/install.test.itg.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
|
||||
import {Install} from '../../src/regclient/install';
|
||||
|
||||
describe('download', () => {
|
||||
// prettier-ignore
|
||||
test.each(['latest'])(
|
||||
'install regclient %s', async (version) => {
|
||||
await expect((async () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version);
|
||||
if (!fs.existsSync(toolPath)) {
|
||||
throw new Error('toolPath does not exist');
|
||||
}
|
||||
const binPath = await install.install(toolPath);
|
||||
if (!fs.existsSync(binPath)) {
|
||||
throw new Error('binPath does not exist');
|
||||
}
|
||||
})()).resolves.not.toThrow();
|
||||
}, 60000);
|
||||
});
|
||||
130
__tests__/regclient/install.test.ts
Normal file
130
__tests__/regclient/install.test.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, jest, test, afterEach} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import * as rimraf from 'rimraf';
|
||||
import osm = require('os');
|
||||
|
||||
import {Install} from '../../src/regclient/install';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(process.env.TEMP || os.tmpdir(), 'regclient-install-'));
|
||||
|
||||
afterEach(function () {
|
||||
rimraf.sync(tmpDir);
|
||||
});
|
||||
|
||||
describe('download', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['v0.8.2'],
|
||||
['latest']
|
||||
])(
|
||||
'acquires %p of regclient', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
const regclientBin = await install.install(toolPath, tmpDir);
|
||||
expect(fs.existsSync(regclientBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
// following versions are already cached to htc from previous test cases
|
||||
['v0.8.2'],
|
||||
])(
|
||||
'acquires %p of regclient with cache', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['v0.8.1'],
|
||||
])(
|
||||
'acquires %p of regclient without cache', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version, true);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['win32', 'x64'],
|
||||
['darwin', 'x64'],
|
||||
['darwin', 'arm64'],
|
||||
['linux', 'x64'],
|
||||
['linux', 'arm64'],
|
||||
['linux', 'ppc64'],
|
||||
['linux', 's390x'],
|
||||
])(
|
||||
'acquires regclient for %s/%s', async (os, arch) => {
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const regclientBin = await install.download('latest');
|
||||
expect(fs.existsSync(regclientBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('getDownloadVersion', () => {
|
||||
it('returns latest download version', async () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/regclient/regclient/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/regclient-releases.json'
|
||||
});
|
||||
});
|
||||
it('returns v0.8.1 download version', async () => {
|
||||
const version = await Install.getDownloadVersion('v0.8.1');
|
||||
expect(version.version).toEqual('v0.8.1');
|
||||
expect(version.downloadURL).toEqual('https://github.com/regclient/regclient/releases/download/v%s/%s');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/regclient-releases.json'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRelease', () => {
|
||||
it('returns latest GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.tag_name).not.toEqual('');
|
||||
});
|
||||
it('returns v0.8.1 GitHub release', async () => {
|
||||
const version = await Install.getDownloadVersion('v0.8.1');
|
||||
const release = await Install.getRelease(version);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.id).toEqual(199719231);
|
||||
expect(release?.tag_name).toEqual('v0.8.1');
|
||||
expect(release?.html_url).toEqual('https://github.com/regclient/regclient/releases/tag/v0.8.1');
|
||||
});
|
||||
it('unknown release', async () => {
|
||||
const version = await Install.getDownloadVersion('foo');
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find regclient release foo in releases JSON'));
|
||||
});
|
||||
});
|
||||
122
__tests__/regclient/regctl.test.ts
Normal file
122
__tests__/regclient/regctl.test.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it, jest, test} from '@jest/globals';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import {Exec} from '../../src/exec';
|
||||
import {Regctl} from '../../src/regclient/regctl';
|
||||
|
||||
import {Image} from '../../src/types/oci/config';
|
||||
|
||||
describe('manifestGet', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['moby/moby-bin:28.1.0-rc.2'],
|
||||
['crazymax/diun:4.17.0'],
|
||||
])('given %p', async image => {
|
||||
const regctl = new Regctl();
|
||||
const manifest = await regctl.manifestGet({
|
||||
image: image,
|
||||
});
|
||||
expect(manifest).not.toBeNull();
|
||||
expect(manifest?.config).toBeDefined();
|
||||
expect(manifest?.config.digest).not.toEqual('');
|
||||
expect(manifest?.layers).toBeDefined();
|
||||
expect(manifest?.layers.length).toBeGreaterThan(0);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('blobGet', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['moby/moby-bin', 'sha256:234fccbd13fde0ba978a19f728cbdc67e29bc76247ac560822bb6ae5236c0bf0'],
|
||||
['crazymax/diun', 'sha256:1e4881f66e0ec0f1710b837002107050bbbc0a231d8a42d7f422b56a139900bb'],
|
||||
])('given %p', async (repo, digest) => {
|
||||
const regctl = new Regctl();
|
||||
const blob = await regctl.blobGet({
|
||||
repository: repo,
|
||||
digest: digest
|
||||
});
|
||||
expect(blob).toBeDefined();
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('image config', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
['moby/moby-bin:28.1.0-rc.2'],
|
||||
['crazymax/diun:4.17.0'],
|
||||
])('given %p', async image => {
|
||||
const regctl = new Regctl();
|
||||
const manifest = await regctl.manifestGet({
|
||||
image: image,
|
||||
});
|
||||
expect(manifest).not.toBeNull();
|
||||
expect(manifest?.config).toBeDefined();
|
||||
expect(manifest?.config.digest).not.toEqual('');
|
||||
const blob = await regctl.blobGet({
|
||||
repository: image, // image works as well
|
||||
digest: manifest?.config.digest
|
||||
});
|
||||
const imageConfig = <Image>JSON.parse(blob);
|
||||
expect(imageConfig).not.toBeNull();
|
||||
expect(imageConfig.config).toBeDefined();
|
||||
expect(imageConfig?.config?.Labels).toBeDefined();
|
||||
expect(Object.keys(imageConfig?.config?.Labels || {}).length).toBeGreaterThan(0);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('isAvailable', () => {
|
||||
it('checks regctl is available', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
const regctl = new Regctl();
|
||||
await regctl.isAvailable();
|
||||
expect(execSpy).toHaveBeenCalledWith(`regctl`, [], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('printVersion', () => {
|
||||
it('prints regctl version', async () => {
|
||||
const execSpy = jest.spyOn(Exec, 'exec');
|
||||
const regctl = new Regctl();
|
||||
await regctl.printVersion();
|
||||
expect(execSpy).toHaveBeenCalledWith(`regctl`, ['version'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('version', () => {
|
||||
it('valid', async () => {
|
||||
const regctl = new Regctl();
|
||||
expect(semver.valid(await regctl.version())).not.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('versionSatisfies', () => {
|
||||
test.each([
|
||||
['v0.8.2', '>=0.6.0', true],
|
||||
['v0.8.0', '>0.6.0', true],
|
||||
['v0.8.0', '<0.3.0', false]
|
||||
])('given %p', async (version, range, expected) => {
|
||||
const regctl = new Regctl();
|
||||
expect(await regctl.versionSatisfies(range, version)).toBe(expected);
|
||||
});
|
||||
});
|
||||
169
__tests__/sigstore/sigstore.test.itg.ts
Normal file
169
__tests__/sigstore/sigstore.test.itg.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {beforeAll, describe, expect, jest, it, test} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import {Buildx} from '../../src/buildx/buildx';
|
||||
import {Build} from '../../src/buildx/build';
|
||||
import {Install as CosignInstall} from '../../src/cosign/install';
|
||||
import {Docker} from '../../src/docker/docker';
|
||||
import {Exec} from '../../src/exec';
|
||||
import {Sigstore} from '../../src/sigstore/sigstore';
|
||||
|
||||
const fixturesDir = path.join(__dirname, '..', '.fixtures');
|
||||
|
||||
const runTest = process.env.GITHUB_ACTIONS && process.env.GITHUB_ACTIONS === 'true' && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu');
|
||||
|
||||
const maybe = runTest ? describe : describe.skip;
|
||||
const maybeIdToken = runTest && process.env.ACTIONS_ID_TOKEN_REQUEST_URL ? describe : describe.skip;
|
||||
|
||||
// needs current GitHub repo info
|
||||
jest.unmock('@actions/github');
|
||||
|
||||
beforeAll(async () => {
|
||||
const cosignInstall = new CosignInstall();
|
||||
const cosignBinPath = await cosignInstall.download({
|
||||
version: 'v3.0.2'
|
||||
});
|
||||
await cosignInstall.install(cosignBinPath);
|
||||
}, 100000);
|
||||
|
||||
maybeIdToken('signAttestationManifests', () => {
|
||||
it('build, sign and verify', async () => {
|
||||
const buildx = new Buildx();
|
||||
const build = new Build({buildx: buildx});
|
||||
const imageName = 'ghcr.io/docker/actions-toolkit/test';
|
||||
|
||||
await expect(
|
||||
(async () => {
|
||||
await Docker.getExecOutput(['login', '--password-stdin', '--username', process.env.GITHUB_REPOSITORY_OWNER || 'docker', 'ghcr.io'], {
|
||||
input: Buffer.from(process.env.GITHUB_TOKEN || '')
|
||||
});
|
||||
})()
|
||||
).resolves.not.toThrow();
|
||||
|
||||
await expect(
|
||||
(async () => {
|
||||
// prettier-ignore
|
||||
const buildCmd = await buildx.getCommand([
|
||||
'--builder', process.env.CTN_BUILDER_NAME ?? 'default',
|
||||
'build',
|
||||
'-f', path.join(fixturesDir, 'hello.Dockerfile'),
|
||||
'--provenance=mode=max',
|
||||
'--tag', `${imageName}:sigstore-itg`,
|
||||
'--platform', 'linux/amd64,linux/arm64',
|
||||
'--push',
|
||||
'--metadata-file', build.getMetadataFilePath(),
|
||||
fixturesDir
|
||||
]);
|
||||
await Exec.exec(buildCmd.command, buildCmd.args);
|
||||
})()
|
||||
).resolves.not.toThrow();
|
||||
|
||||
const metadata = build.resolveMetadata();
|
||||
expect(metadata).toBeDefined();
|
||||
const buildDigest = build.resolveDigest(metadata);
|
||||
expect(buildDigest).toBeDefined();
|
||||
|
||||
const sigstore = new Sigstore();
|
||||
const signResults = await sigstore.signAttestationManifests({
|
||||
imageNames: [imageName],
|
||||
imageDigest: buildDigest!
|
||||
});
|
||||
expect(Object.keys(signResults).length).toEqual(2);
|
||||
|
||||
const verifyResults = await sigstore.verifySignedManifests(signResults, {
|
||||
certificateIdentityRegexp: `^https://github.com/docker/actions-toolkit/.github/workflows/test.yml.*$`
|
||||
});
|
||||
expect(Object.keys(verifyResults).length).toEqual(2);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
maybe('verifyImageAttestations', () => {
|
||||
test.each([
|
||||
['moby/buildkit:master@sha256:84014da3581b2ff2c14cb4f60029cf9caa272b79e58f2e89c651ea6966d7a505', `^https://github.com/docker/github-builder-experimental/.github/workflows/bake.yml.*$`],
|
||||
['docker/dockerfile-upstream:master@sha256:3e8cd5ebf48acd1a1939649ad1c62ca44c029852b22493c16a9307b654334958', `^https://github.com/docker/github-builder-experimental/.github/workflows/bake.yml.*$`]
|
||||
])(
|
||||
'given %p',
|
||||
async (image, certificateIdentityRegexp) => {
|
||||
const sigstore = new Sigstore();
|
||||
const verifyResults = await sigstore.verifyImageAttestations(image, {
|
||||
certificateIdentityRegexp: certificateIdentityRegexp
|
||||
});
|
||||
expect(Object.keys(verifyResults).length).toBeGreaterThan(0);
|
||||
for (const [attestationRef, res] of Object.entries(verifyResults)) {
|
||||
expect(attestationRef).toBeDefined();
|
||||
expect(res.cosignArgs).toBeDefined();
|
||||
expect(res.signatureManifestDigest).toBeDefined();
|
||||
}
|
||||
},
|
||||
60000
|
||||
);
|
||||
});
|
||||
|
||||
maybeIdToken('signProvenanceBlobs', () => {
|
||||
it('single platform', async () => {
|
||||
const sigstore = new Sigstore();
|
||||
const results = await sigstore.signProvenanceBlobs({
|
||||
localExportDir: path.join(fixturesDir, 'sigstore', 'single')
|
||||
});
|
||||
expect(Object.keys(results).length).toEqual(1);
|
||||
const provenancePath = Object.keys(results)[0];
|
||||
expect(provenancePath).toEqual(path.join(fixturesDir, 'sigstore', 'single', 'provenance.json'));
|
||||
expect(fs.existsSync(results[provenancePath].bundlePath)).toBe(true);
|
||||
expect(results[provenancePath].payload).toBeDefined();
|
||||
expect(results[provenancePath].certificate).toBeDefined();
|
||||
expect(results[provenancePath].tlogID).toBeDefined();
|
||||
console.log(provenancePath, JSON.stringify(results[provenancePath].payload, null, 2));
|
||||
});
|
||||
it('multi-platform', async () => {
|
||||
const sigstore = new Sigstore();
|
||||
const results = await sigstore.signProvenanceBlobs({
|
||||
localExportDir: path.join(fixturesDir, 'sigstore', 'multi')
|
||||
});
|
||||
expect(Object.keys(results).length).toEqual(2);
|
||||
for (const [provenancePath, res] of Object.entries(results)) {
|
||||
expect(provenancePath).toMatch(/linux_(amd64|arm64)\/provenance.json/);
|
||||
expect(fs.existsSync(res.bundlePath)).toBe(true);
|
||||
expect(res.payload).toBeDefined();
|
||||
expect(res.certificate).toBeDefined();
|
||||
expect(res.tlogID).toBeDefined();
|
||||
console.log(provenancePath, JSON.stringify(res.payload, null, 2));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
maybeIdToken('verifySignedArtifacts', () => {
|
||||
it('sign and verify', async () => {
|
||||
const sigstore = new Sigstore();
|
||||
const signResults = await sigstore.signProvenanceBlobs({
|
||||
localExportDir: path.join(fixturesDir, 'sigstore', 'multi')
|
||||
});
|
||||
expect(Object.keys(signResults).length).toEqual(2);
|
||||
|
||||
const verifyResults = await sigstore.verifySignedArtifacts(signResults, {
|
||||
certificateIdentityRegexp: `^https://github.com/docker/actions-toolkit/.github/workflows/test.yml.*$`
|
||||
});
|
||||
expect(Object.keys(verifyResults).length).toEqual(2);
|
||||
for (const [artifactPath, res] of Object.entries(verifyResults)) {
|
||||
expect(fs.existsSync(artifactPath)).toBe(true);
|
||||
expect(res.bundlePath).toBeDefined();
|
||||
expect(res.cosignArgs).toBeDefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -14,16 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = results => {
|
||||
const allSkipped = results.testResults.every(result => {
|
||||
return result.skipped;
|
||||
});
|
||||
const allSkipped = results.testResults.every(result => result.skipped);
|
||||
if (allSkipped) {
|
||||
console.log('All tests were skipped!');
|
||||
// create an empty file to signal that all tests were skipped for CI
|
||||
fs.mkdirSync('./coverage', {recursive: true});
|
||||
fs.closeSync(fs.openSync('./coverage/allSkipped.txt', 'w'));
|
||||
}
|
||||
return results;
|
||||
@@ -36,15 +36,13 @@ describe('download', () => {
|
||||
['v0.7.0'],
|
||||
['latest']
|
||||
])(
|
||||
'acquires %p of undock (standalone: %p)', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
const undockBin = await install.install(toolPath, tmpDir);
|
||||
expect(fs.existsSync(undockBin)).toBe(true);
|
||||
},
|
||||
100000
|
||||
);
|
||||
'acquires %p of undock', async (version) => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
const undockBin = await install.install(toolPath, tmpDir);
|
||||
expect(fs.existsSync(undockBin)).toBe(true);
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
@@ -56,7 +54,7 @@ describe('download', () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
});
|
||||
}, 100000);
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
@@ -67,7 +65,7 @@ describe('download', () => {
|
||||
const install = new Install();
|
||||
const toolPath = await install.download(version, true);
|
||||
expect(fs.existsSync(toolPath)).toBe(true);
|
||||
});
|
||||
}, 100000);
|
||||
|
||||
// TODO: add tests for arm
|
||||
// prettier-ignore
|
||||
@@ -82,14 +80,12 @@ describe('download', () => {
|
||||
['linux', 's390x'],
|
||||
])(
|
||||
'acquires undock for %s/%s', async (os, arch) => {
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const undockBin = await install.download('latest');
|
||||
expect(fs.existsSync(undockBin)).toBe(true);
|
||||
},
|
||||
100000
|
||||
);
|
||||
jest.spyOn(osm, 'platform').mockImplementation(() => os as NodeJS.Platform);
|
||||
jest.spyOn(osm, 'arch').mockImplementation(() => arch);
|
||||
const install = new Install();
|
||||
const undockBin = await install.download('latest');
|
||||
expect(fs.existsSync(undockBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('getDownloadVersion', () => {
|
||||
@@ -97,13 +93,23 @@ describe('getDownloadVersion', () => {
|
||||
const version = await Install.getDownloadVersion('latest');
|
||||
expect(version.version).toEqual('latest');
|
||||
expect(version.downloadURL).toEqual('https://github.com/crazy-max/undock/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/undock-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/undock-releases.json'
|
||||
});
|
||||
});
|
||||
it('returns v0.6.0 download version', async () => {
|
||||
const version = await Install.getDownloadVersion('v0.6.0');
|
||||
expect(version.version).toEqual('v0.6.0');
|
||||
expect(version.downloadURL).toEqual('https://github.com/crazy-max/undock/releases/download/v%s/%s');
|
||||
expect(version.releasesURL).toEqual('https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/undock-releases.json');
|
||||
expect(version.contentOpts).toEqual({
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/undock-releases.json'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -124,6 +130,6 @@ describe('getRelease', () => {
|
||||
});
|
||||
it('unknown release', async () => {
|
||||
const version = await Install.getDownloadVersion('foo');
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Undock release foo in https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/undock-releases.json'));
|
||||
await expect(Install.getRelease(version)).rejects.toThrow(new Error('Cannot find Undock release foo in releases JSON'));
|
||||
});
|
||||
});
|
||||
|
||||
47
__tests__/undock/undock.test.itg.ts
Normal file
47
__tests__/undock/undock.test.itg.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {describe, expect, it} from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
|
||||
import {Undock} from '../../src/undock/undock';
|
||||
import {Install as UndockInstall} from '../../src/undock/install';
|
||||
|
||||
describe('run', () => {
|
||||
it('extracts moby/moby-bin:26.1.5', async () => {
|
||||
const install = new UndockInstall();
|
||||
const toolPath = await install.download('latest');
|
||||
if (!fs.existsSync(toolPath)) {
|
||||
throw new Error('toolPath does not exist');
|
||||
}
|
||||
const binPath = await install.install(toolPath);
|
||||
if (!fs.existsSync(binPath)) {
|
||||
throw new Error('binPath does not exist');
|
||||
}
|
||||
|
||||
const undock = new Undock();
|
||||
await expect(
|
||||
(async () => {
|
||||
// prettier-ignore
|
||||
await undock.run({
|
||||
source: 'docker/buildx-bin:0.23.0',
|
||||
dist: os.tmpdir()
|
||||
});
|
||||
})()
|
||||
).resolves.not.toThrow();
|
||||
}, 500000);
|
||||
});
|
||||
@@ -38,7 +38,7 @@ describe('run', () => {
|
||||
});
|
||||
})()
|
||||
).resolves.not.toThrow();
|
||||
}, 100000);
|
||||
}, 500000);
|
||||
});
|
||||
|
||||
describe('isAvailable', () => {
|
||||
@@ -46,7 +46,6 @@ describe('isAvailable', () => {
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput');
|
||||
const undock = new Undock();
|
||||
await undock.isAvailable();
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(execSpy).toHaveBeenCalledWith(`undock`, [], {
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
|
||||
@@ -469,6 +469,36 @@ describe('isPathRelativeTo', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatDuration', () => {
|
||||
it('formats 0 nanoseconds as "0s"', () => {
|
||||
expect(Util.formatDuration(0)).toBe('0s');
|
||||
});
|
||||
it('formats only seconds', () => {
|
||||
expect(Util.formatDuration(5e9)).toBe('5s');
|
||||
expect(Util.formatDuration(59e9)).toBe('59s');
|
||||
});
|
||||
it('formats minutes and seconds', () => {
|
||||
expect(Util.formatDuration(65e9)).toBe('1m5s');
|
||||
expect(Util.formatDuration(600e9)).toBe('10m');
|
||||
});
|
||||
it('formats hours, minutes, and seconds', () => {
|
||||
expect(Util.formatDuration(3661e9)).toBe('1h1m1s');
|
||||
expect(Util.formatDuration(7322e9)).toBe('2h2m2s');
|
||||
});
|
||||
it('formats hours only', () => {
|
||||
expect(Util.formatDuration(3 * 3600e9)).toBe('3h');
|
||||
});
|
||||
it('formats hours and minutes', () => {
|
||||
expect(Util.formatDuration(3900e9)).toBe('1h5m');
|
||||
});
|
||||
it('formats minutes only', () => {
|
||||
expect(Util.formatDuration(120e9)).toBe('2m');
|
||||
});
|
||||
it('rounds down partial seconds', () => {
|
||||
expect(Util.formatDuration(1799999999)).toBe('1s');
|
||||
});
|
||||
});
|
||||
|
||||
// See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89
|
||||
function getInputName(name: string): string {
|
||||
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
ARG NODE_VERSION=20
|
||||
ARG DOCKER_VERSION=27.2.1
|
||||
ARG BUILDX_VERSION=0.19.1
|
||||
ARG UNDOCK_VERSION=0.8.0
|
||||
ARG DOCKER_VERSION=28.3
|
||||
ARG BUILDX_VERSION=0.30.1
|
||||
ARG COMPOSE_VERSION=2.39.1
|
||||
ARG UNDOCK_VERSION=0.10.0
|
||||
ARG REGCTL_VERSION=v0.8.2
|
||||
ARG COSIGN_VERSION=v3.0.3
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
@@ -74,41 +77,27 @@ RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run lint
|
||||
|
||||
FROM docker:${DOCKER_VERSION} AS docker
|
||||
FROM dockereng/cli-bin:${DOCKER_VERSION} AS docker
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
FROM docker/compose-bin:v${COMPOSE_VERSION} AS compose
|
||||
FROM crazymax/undock:${UNDOCK_VERSION} AS undock
|
||||
FROM ghcr.io/regclient/regctl:${REGCTL_VERSION} AS regctl
|
||||
FROM ghcr.io/sigstore/cosign/cosign:${COSIGN_VERSION} AS cosign
|
||||
|
||||
FROM deps AS test
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
|
||||
--mount=type=bind,from=docker,source=/docker,target=/usr/bin/docker \
|
||||
--mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
|
||||
--mount=type=bind,from=buildx,source=/buildx,target=/usr/bin/buildx \
|
||||
--mount=type=bind,from=compose,source=/docker-compose,target=/usr/libexec/docker/cli-plugins/docker-compose \
|
||||
--mount=type=bind,from=compose,source=/docker-compose,target=/usr/bin/compose \
|
||||
--mount=type=bind,from=undock,source=/usr/local/bin/undock,target=/usr/bin/undock \
|
||||
--mount=type=bind,from=regctl,source=/regctl,target=/usr/bin/regctl \
|
||||
--mount=type=bind,from=cosign,source=/ko-app/cosign,target=/usr/bin/cosign \
|
||||
--mount=type=secret,id=GITHUB_TOKEN \
|
||||
GITHUB_TOKEN=$(cat /run/secrets/GITHUB_TOKEN) yarn run test:coverage --coverageDirectory=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage /
|
||||
|
||||
FROM base AS publish
|
||||
ARG GITHUB_REF
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
--mount=type=secret,id=NODE_AUTH_TOKEN <<EOT
|
||||
set -e
|
||||
if ! [[ $GITHUB_REF =~ ^refs/tags/v ]]; then
|
||||
echo "GITHUB_REF is not a tag"
|
||||
exit 1
|
||||
fi
|
||||
yarn install
|
||||
yarn run build
|
||||
npm config set //registry.npmjs.org/:_authToken $(cat /run/secrets/NODE_AUTH_TOKEN)
|
||||
npm version --no-git-tag-version ${GITHUB_REF#refs/tags/v}
|
||||
npm publish --access public
|
||||
|
||||
# FIXME: Can't publish with yarn berry atm: https://github.com/changesets/changesets/pull/674
|
||||
#NODE_AUTH_TOKEN=$(cat /run/secrets/NODE_AUTH_TOKEN) yarn publish --no-git-tag-version --new-version ${GITHUB_REF#refs/tags/v}
|
||||
EOT
|
||||
|
||||
@@ -30,6 +30,7 @@ group "validate" {
|
||||
|
||||
target "_common" {
|
||||
args = {
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
|
||||
NODE_VERSION = NODE_VERSION
|
||||
}
|
||||
}
|
||||
@@ -76,6 +77,7 @@ target "dockerfile-validate" {
|
||||
"./hack/dockerfiles/license.Dockerfile"
|
||||
]
|
||||
}
|
||||
inherits = ["_common"]
|
||||
name = "dockerfile-validate-${md5(dockerfile)}"
|
||||
dockerfile = dockerfile
|
||||
call = "check"
|
||||
@@ -97,30 +99,15 @@ target "test-coverage" {
|
||||
secret = ["id=GITHUB_TOKEN,env=GITHUB_TOKEN"]
|
||||
}
|
||||
|
||||
# GITHUB_REF is the actual ref that triggers the workflow and used as version
|
||||
# when a tag is pushed: https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
|
||||
variable "GITHUB_REF" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
target "publish" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
args = {
|
||||
GITHUB_REF = GITHUB_REF
|
||||
}
|
||||
target = "publish"
|
||||
output = ["type=cacheonly"]
|
||||
secret = ["id=NODE_AUTH_TOKEN,env=NODE_AUTH_TOKEN"]
|
||||
}
|
||||
|
||||
target "license-validate" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "./hack/dockerfiles/license.Dockerfile"
|
||||
target = "validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "license-update" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "./hack/dockerfiles/license.Dockerfile"
|
||||
target = "update"
|
||||
output = ["."]
|
||||
|
||||
84
eslint.config.js
Normal file
84
eslint.config.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const {defineConfig, globalIgnores} = require('eslint/config');
|
||||
const {fixupConfigRules, fixupPluginRules} = require('@eslint/compat');
|
||||
const typescriptEslint = require('@typescript-eslint/eslint-plugin');
|
||||
const jestPlugin = require('eslint-plugin-jest');
|
||||
const prettier = require('eslint-plugin-prettier');
|
||||
const globals = require('globals');
|
||||
const tsParser = require('@typescript-eslint/parser');
|
||||
const js = require('@eslint/js');
|
||||
const {FlatCompat} = require('@eslint/eslintrc');
|
||||
|
||||
// __dirname and __filename exist natively in CommonJS
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
});
|
||||
|
||||
module.exports = defineConfig([
|
||||
globalIgnores(['.yarn/**/*', 'lib/**/*', 'coverage/**/*', 'node_modules/**/*']),
|
||||
{
|
||||
extends: fixupConfigRules(
|
||||
compat.extends(
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/typescript',
|
||||
'plugin:import/warnings',
|
||||
'plugin:jest/recommended',
|
||||
'plugin:prettier/recommended'
|
||||
)
|
||||
),
|
||||
|
||||
plugins: {
|
||||
'@typescript-eslint': fixupPluginRules(typescriptEslint),
|
||||
jest: fixupPluginRules(jestPlugin),
|
||||
prettier: fixupPluginRules(prettier)
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.mocha,
|
||||
...globals.jest
|
||||
},
|
||||
parser: tsParser,
|
||||
ecmaVersion: 2023,
|
||||
sourceType: 'commonjs'
|
||||
},
|
||||
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': [
|
||||
'error',
|
||||
{
|
||||
allowAsImport: true
|
||||
}
|
||||
],
|
||||
'import/no-unresolved': [
|
||||
'error',
|
||||
{
|
||||
ignore: ['csv-parse/sync', '@octokit/openapi-types']
|
||||
}
|
||||
],
|
||||
'jest/no-disabled-tests': 0
|
||||
}
|
||||
}
|
||||
]);
|
||||
@@ -14,23 +14,44 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ARG ADDLICENSE_VERSION="v1.1.1"
|
||||
ARG ALPINE_VERSION="3.21"
|
||||
ARG GO_VERSION="1.23"
|
||||
ARG XX_VERSION="1.6.1"
|
||||
|
||||
ARG LICENSE_HOLDER="actions-toolkit authors"
|
||||
ARG LICENSE_TYPE="apache"
|
||||
ARG LICENSE_FILES=".*\(Dockerfile\|Makefile\|\.js\|\.ts\|\.hcl\|\.sh|\.ps1\)"
|
||||
ARG ADDLICENSE_VERSION="v1.0.0"
|
||||
|
||||
FROM ghcr.io/google/addlicense:${ADDLICENSE_VERSION} AS addlicense
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
FROM alpine:3.17 AS base
|
||||
WORKDIR /src
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
ENV CGO_ENABLED=0
|
||||
WORKDIR /src
|
||||
COPY --link --from=xx / /
|
||||
|
||||
FROM base AS addlicense
|
||||
ARG ADDLICENSE_VERSION
|
||||
ARG TARGETPLATFORM
|
||||
RUN --mount=target=/root/.cache,type=cache \
|
||||
--mount=type=cache,target=/go/pkg/mod <<EOT
|
||||
set -ex
|
||||
xx-go install "github.com/google/addlicense@${ADDLICENSE_VERSION}"
|
||||
mkdir /out
|
||||
if ! xx-info is-cross; then
|
||||
mv /go/bin/addlicense /out
|
||||
else
|
||||
mv /go/bin/*/addlicense* /out
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM base AS set
|
||||
ARG LICENSE_HOLDER
|
||||
ARG LICENSE_TYPE
|
||||
ARG LICENSE_FILES
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \
|
||||
--mount=from=addlicense,source=/out/addlicense,target=/usr/bin/addlicense \
|
||||
find . -regex "${LICENSE_FILES}" -not -path "./.yarn/*" -not -path "./node_modules/*" | xargs addlicense -c "$LICENSE_HOLDER" -l "$LICENSE_TYPE" && \
|
||||
mkdir /out && \
|
||||
find . -regex "${LICENSE_FILES}" -not -path "./.yarn/*" -not -path "./node_modules/*" | cpio -pdm /out
|
||||
@@ -43,5 +64,5 @@ ARG LICENSE_HOLDER
|
||||
ARG LICENSE_TYPE
|
||||
ARG LICENSE_FILES
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \
|
||||
--mount=from=addlicense,source=/out/addlicense,target=/usr/bin/addlicense \
|
||||
find . -regex "${LICENSE_FILES}" -not -path "./.yarn/*" -not -path "./node_modules/*" | xargs addlicense -check -c "$LICENSE_HOLDER" -l "$LICENSE_TYPE"
|
||||
|
||||
@@ -14,20 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-actions-toolkit-'));
|
||||
|
||||
process.env = Object.assign({}, process.env, {
|
||||
TEMP: tmpDir,
|
||||
RUNNER_TEMP: path.join(tmpDir, 'runner-temp'),
|
||||
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache')
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
@@ -40,6 +26,6 @@ module.exports = {
|
||||
moduleNameMapper: {
|
||||
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
||||
},
|
||||
testResultsProcessor: './__tests__/testResultsProcessor.ts',
|
||||
testResultsProcessor: '<rootDir>/__tests__/testResultsProcessor.js',
|
||||
verbose: false
|
||||
};
|
||||
@@ -14,9 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-actions-toolkit-'));
|
||||
|
||||
@@ -28,9 +29,7 @@ process.env = Object.assign({}, process.env, {
|
||||
GITHUB_RUN_NUMBER: 15,
|
||||
RUNNER_TEMP: path.join(tmpDir, 'runner-temp'),
|
||||
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache')
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
@@ -46,6 +45,6 @@ module.exports = {
|
||||
},
|
||||
collectCoverageFrom: ['src/**/{!(index.ts),}.ts'],
|
||||
coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__mocks__/', '__tests__/'],
|
||||
testResultsProcessor: './__tests__/testResultsProcessor.ts',
|
||||
testResultsProcessor: '<rootDir>/__tests__/testResultsProcessor.js',
|
||||
verbose: true
|
||||
};
|
||||
81
package.json
81
package.json
@@ -12,9 +12,9 @@
|
||||
"prettier:fix": "prettier --write \"./**/*.ts\"",
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --coverage",
|
||||
"test:itg": "jest -c jest.config.itg.ts --runInBand --detectOpenHandles",
|
||||
"test:itg-list": "jest -c jest.config.itg.ts --listTests",
|
||||
"test:itg-coverage": "jest --coverage -c jest.config.itg.ts --runInBand --detectOpenHandles"
|
||||
"test:itg": "jest -c jest.config.itg.js --runInBand",
|
||||
"test:itg-list": "jest -c jest.config.itg.js --listTests",
|
||||
"test:itg-coverage": "jest -c jest.config.itg.js --coverage --runInBand"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -30,7 +30,7 @@
|
||||
],
|
||||
"author": "Docker Inc.",
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@3.6.3",
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"directories": {
|
||||
@@ -45,50 +45,57 @@
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^2.1.11",
|
||||
"@actions/cache": "^3.3.0",
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@actions/http-client": "^2.2.3",
|
||||
"@actions/io": "^1.1.3",
|
||||
"@actions/tool-cache": "^2.0.1",
|
||||
"@azure/storage-blob": "^12.15.0",
|
||||
"@octokit/core": "^5.1.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.4.0",
|
||||
"@actions/artifact": "^5.0.2",
|
||||
"@actions/cache": "^5.0.2",
|
||||
"@actions/core": "^2.0.2",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/github": "^7.0.0",
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@actions/tool-cache": "^3.0.0",
|
||||
"@azure/storage-blob": "^12.29.1",
|
||||
"@octokit/core": "^5.2.2",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.4.1",
|
||||
"@sigstore/bundle": "^4.0.0",
|
||||
"@sigstore/sign": "^4.1.0",
|
||||
"@sigstore/tuf": "^4.0.1",
|
||||
"@sigstore/verify": "^3.1.0",
|
||||
"async-retry": "^1.3.3",
|
||||
"csv-parse": "^5.6.0",
|
||||
"csv-parse": "^6.1.0",
|
||||
"gunzip-maybe": "^1.4.2",
|
||||
"handlebars": "^4.7.8",
|
||||
"he": "^1.2.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"semver": "^7.6.3",
|
||||
"semver": "^7.7.3",
|
||||
"tar-stream": "^3.1.7",
|
||||
"tmp": "^0.2.3"
|
||||
"tmp": "^0.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/csv-parse": "^1.2.2",
|
||||
"@types/gunzip-maybe": "^1.4.2",
|
||||
"@eslint/compat": "^2.0.0",
|
||||
"@eslint/eslintrc": "^3.3.3",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@sigstore/rekor-types": "^4.0.0",
|
||||
"@types/gunzip-maybe": "^1.4.3",
|
||||
"@types/he": "^1.2.3",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^20.12.10",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/tar-stream": "^3.1.3",
|
||||
"@types/node": "^20.19.27",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/tar-stream": "^3.1.4",
|
||||
"@types/tmp": "^0.2.6",
|
||||
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
||||
"@typescript-eslint/parser": "^7.8.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jest": "^28.5.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"rimraf": "^5.0.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.50.0",
|
||||
"@typescript-eslint/parser": "^8.50.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-jest": "^29.5.0",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"jest": "^30.2.0",
|
||||
"prettier": "^3.7.4",
|
||||
"rimraf": "^6.1.2",
|
||||
"ts-jest": "^29.4.6",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ export class BuildKit {
|
||||
if (!bkversion) {
|
||||
try {
|
||||
bkversion = await this.getVersionWithinImage(node.name || '');
|
||||
} catch (e) {
|
||||
} catch {
|
||||
core.debug(`BuildKit.versionSatisfies ${node.name}: can't get version`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {parse} from 'csv-parse/sync';
|
||||
|
||||
import {Build} from './build';
|
||||
import {Buildx} from './buildx';
|
||||
import {Context} from '../context';
|
||||
import {Exec} from '../exec';
|
||||
import {Util} from '../util';
|
||||
|
||||
import {ExecOptions} from '@actions/exec';
|
||||
import {BakeDefinition} from '../types/buildx/bake';
|
||||
import {AttestEntry, BakeDefinition, CacheEntry, ExportEntry, SecretEntry, SSHEntry} from '../types/buildx/bake';
|
||||
import {BuildMetadata} from '../types/buildx/build';
|
||||
import {VertexWarning} from '../types/buildkit/client';
|
||||
|
||||
@@ -178,29 +178,280 @@ export class Bake {
|
||||
}
|
||||
|
||||
public static parseDefinition(dt: string): BakeDefinition {
|
||||
return <BakeDefinition>JSON.parse(dt);
|
||||
const definition = <BakeDefinition>JSON.parse(dt);
|
||||
|
||||
// convert to composable attributes: https://github.com/docker/buildx/pull/2758
|
||||
for (const name in definition.target) {
|
||||
const target = definition.target[name];
|
||||
if (target['attest'] && Array.isArray(target['attest'])) {
|
||||
target['attest'] = target['attest'].map((item: string | AttestEntry): AttestEntry => {
|
||||
return Bake.parseAttestEntry(item);
|
||||
});
|
||||
}
|
||||
if (target['cache-from'] && Array.isArray(target['cache-from'])) {
|
||||
target['cache-from'] = target['cache-from'].map((item: string | CacheEntry): CacheEntry => {
|
||||
return Bake.parseCacheEntry(item);
|
||||
});
|
||||
}
|
||||
if (target['cache-to'] && Array.isArray(target['cache-to'])) {
|
||||
target['cache-to'] = target['cache-to'].map((item: string | CacheEntry): CacheEntry => {
|
||||
return Bake.parseCacheEntry(item);
|
||||
});
|
||||
}
|
||||
if (target['output'] && Array.isArray(target['output'])) {
|
||||
target['output'] = target['output'].map((item: string | ExportEntry): ExportEntry => {
|
||||
return Bake.parseExportEntry(item);
|
||||
});
|
||||
}
|
||||
if (target['secret'] && Array.isArray(target['secret'])) {
|
||||
target['secret'] = target['secret'].map((item: string | SecretEntry): SecretEntry => {
|
||||
return Bake.parseSecretEntry(item);
|
||||
});
|
||||
}
|
||||
if (target['ssh'] && Array.isArray(target['ssh'])) {
|
||||
target['ssh'] = target['ssh'].map((item: string | SSHEntry): SSHEntry => {
|
||||
return Bake.parseSSHEntry(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
private static parseAttestEntry(item: AttestEntry | string): AttestEntry {
|
||||
if (typeof item !== 'string') {
|
||||
return item;
|
||||
}
|
||||
|
||||
const attestEntry: AttestEntry = {type: ''};
|
||||
const fields = parse(item, {
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
|
||||
for (const field of fields) {
|
||||
const [key, value] = field
|
||||
.toString()
|
||||
.split(/(?<=^[^=]+?)=/)
|
||||
.map((item: string) => item.trim());
|
||||
switch (key) {
|
||||
case 'type':
|
||||
attestEntry.type = value;
|
||||
break;
|
||||
case 'disabled':
|
||||
attestEntry.disabled = Util.parseBool(value);
|
||||
break;
|
||||
default:
|
||||
attestEntry[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return attestEntry;
|
||||
}
|
||||
|
||||
private static parseCacheEntry(item: CacheEntry | string): CacheEntry {
|
||||
if (typeof item !== 'string') {
|
||||
return item;
|
||||
}
|
||||
|
||||
const cacheEntry: CacheEntry = {type: ''};
|
||||
const fields = parse(item, {
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
|
||||
if (fields.length === 1 && !fields[0].includes('=')) {
|
||||
cacheEntry.type = 'registry';
|
||||
cacheEntry.ref = fields[0];
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
for (const field of fields) {
|
||||
const [key, value] = field
|
||||
.toString()
|
||||
.split(/(?<=^[^=]+?)=/)
|
||||
.map((item: string) => item.trim());
|
||||
switch (key) {
|
||||
case 'type':
|
||||
cacheEntry.type = value;
|
||||
break;
|
||||
default:
|
||||
cacheEntry[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
private static parseExportEntry(item: ExportEntry | string): ExportEntry {
|
||||
if (typeof item !== 'string') {
|
||||
return item;
|
||||
}
|
||||
|
||||
const exportEntry: ExportEntry = {type: ''};
|
||||
const fields = parse(item, {
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
|
||||
if (fields.length === 1 && fields[0] === item && !item.startsWith('type=')) {
|
||||
if (item !== '-') {
|
||||
exportEntry.type = 'local';
|
||||
exportEntry.dest = item;
|
||||
return exportEntry;
|
||||
}
|
||||
exportEntry.type = 'tar';
|
||||
exportEntry.dest = item;
|
||||
return exportEntry;
|
||||
}
|
||||
|
||||
for (const field of fields) {
|
||||
const [key, value] = field
|
||||
.toString()
|
||||
.split(/(?<=^[^=]+?)=/)
|
||||
.map((item: string) => item.trim());
|
||||
switch (key) {
|
||||
case 'type':
|
||||
exportEntry.type = value;
|
||||
break;
|
||||
default:
|
||||
exportEntry[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return exportEntry;
|
||||
}
|
||||
|
||||
private static parseSecretEntry(item: SecretEntry | string): SecretEntry {
|
||||
if (typeof item !== 'string') {
|
||||
return item;
|
||||
}
|
||||
|
||||
const secretEntry: SecretEntry = {};
|
||||
const fields = parse(item, {
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
|
||||
let typ = '';
|
||||
for (const field of fields) {
|
||||
const [key, value] = field
|
||||
.toString()
|
||||
.split(/(?<=^[^=]+?)=/)
|
||||
.map((item: string) => item.trim());
|
||||
switch (key) {
|
||||
case 'type':
|
||||
typ = value;
|
||||
break;
|
||||
case 'id':
|
||||
secretEntry.id = value;
|
||||
break;
|
||||
case 'source':
|
||||
case 'src':
|
||||
secretEntry.src = value;
|
||||
break;
|
||||
case 'env':
|
||||
secretEntry.env = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typ === 'env' && !secretEntry.env) {
|
||||
secretEntry.env = secretEntry.src;
|
||||
secretEntry.src = undefined;
|
||||
}
|
||||
return secretEntry;
|
||||
}
|
||||
|
||||
private static parseSSHEntry(item: SSHEntry | string): SSHEntry {
|
||||
if (typeof item !== 'string') {
|
||||
return item;
|
||||
}
|
||||
|
||||
const sshEntry: SSHEntry = {};
|
||||
const [key, value] = item.split('=', 2);
|
||||
sshEntry.id = key;
|
||||
if (value) {
|
||||
sshEntry.paths = value.split(',');
|
||||
}
|
||||
|
||||
return sshEntry;
|
||||
}
|
||||
|
||||
public static hasLocalExporter(def: BakeDefinition): boolean {
|
||||
return Build.hasExporterType('local', Bake.exporters(def));
|
||||
return Bake.hasExporterType('local', Bake.exporters(def));
|
||||
}
|
||||
|
||||
public static hasTarExporter(def: BakeDefinition): boolean {
|
||||
return Build.hasExporterType('tar', Bake.exporters(def));
|
||||
return Bake.hasExporterType('tar', Bake.exporters(def));
|
||||
}
|
||||
|
||||
public static hasDockerExporter(def: BakeDefinition, load?: boolean): boolean {
|
||||
return load || Build.hasExporterType('docker', Bake.exporters(def));
|
||||
return load || Bake.hasExporterType('docker', Bake.exporters(def));
|
||||
}
|
||||
|
||||
private static exporters(def: BakeDefinition): Array<string> {
|
||||
const exporters = new Array<string>();
|
||||
public static hasExporterType(name: string, exporters: Array<ExportEntry>): boolean {
|
||||
for (const exporter of exporters) {
|
||||
if (exporter.type == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static exporters(def: BakeDefinition): Array<ExportEntry> {
|
||||
const exporters = new Array<ExportEntry>();
|
||||
for (const key in def.target) {
|
||||
const target = def.target[key];
|
||||
if (target.output) {
|
||||
exporters.push(...target.output);
|
||||
for (const output of target.output) {
|
||||
exporters.push(Bake.parseExportEntry(output));
|
||||
}
|
||||
}
|
||||
}
|
||||
return exporters;
|
||||
}
|
||||
|
||||
public static hasGitAuthTokenSecret(def: BakeDefinition): boolean {
|
||||
for (const key in def.target) {
|
||||
const target = def.target[key];
|
||||
if (target.secret) {
|
||||
for (const secret of target.secret) {
|
||||
if (Bake.parseSecretEntry(secret).id === 'GIT_AUTH_TOKEN') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static hasProvenanceAttestation(def: BakeDefinition): boolean {
|
||||
return Bake.hasAttestationType('provenance', Bake.attestations(def));
|
||||
}
|
||||
|
||||
public static hasSBOMAttestation(def: BakeDefinition): boolean {
|
||||
return Bake.hasAttestationType('sbom', Bake.attestations(def));
|
||||
}
|
||||
|
||||
public static hasAttestationType(name: string, attestations: Array<AttestEntry>): boolean {
|
||||
for (const attestation of attestations) {
|
||||
if (attestation.type == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static attestations(def: BakeDefinition): Array<AttestEntry> {
|
||||
const attestations = new Array<AttestEntry>();
|
||||
for (const key in def.target) {
|
||||
const target = def.target[key];
|
||||
if (target.attest) {
|
||||
for (const attest of target.attest) {
|
||||
attestations.push(Bake.parseAttestEntry(attest));
|
||||
}
|
||||
}
|
||||
}
|
||||
return attestations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@ export interface BuildOpts {
|
||||
buildx?: Buildx;
|
||||
}
|
||||
|
||||
export interface ResolveSecretsOpts {
|
||||
asFile?: boolean;
|
||||
redact?: boolean;
|
||||
}
|
||||
|
||||
export class Build {
|
||||
private readonly buildx: Buildx;
|
||||
private readonly iidFilename: string;
|
||||
@@ -124,12 +129,16 @@ export class Build {
|
||||
}
|
||||
|
||||
public static resolveSecretString(kvp: string): string {
|
||||
const [key, file] = Build.resolveSecret(kvp, false);
|
||||
const [key, file] = Build.resolveSecret(kvp, {
|
||||
redact: true
|
||||
});
|
||||
return `id=${key},src=${file}`;
|
||||
}
|
||||
|
||||
public static resolveSecretFile(kvp: string): string {
|
||||
const [key, file] = Build.resolveSecret(kvp, true);
|
||||
const [key, file] = Build.resolveSecret(kvp, {
|
||||
asFile: true
|
||||
});
|
||||
return `id=${key},src=${file}`;
|
||||
}
|
||||
|
||||
@@ -138,17 +147,17 @@ export class Build {
|
||||
return `id=${key},env=${value}`;
|
||||
}
|
||||
|
||||
public static resolveSecret(kvp: string, file: boolean): [string, string] {
|
||||
const [key, _value] = Build.parseSecretKvp(kvp);
|
||||
let value = _value;
|
||||
if (file) {
|
||||
public static resolveSecret(kvp: string, opts?: ResolveSecretsOpts): [string, string] {
|
||||
const [key, value] = Build.parseSecretKvp(kvp, opts?.redact);
|
||||
const secretFile = Context.tmpName({tmpdir: Context.tmpDir()});
|
||||
if (opts?.asFile) {
|
||||
if (!fs.existsSync(value)) {
|
||||
throw new Error(`secret file ${value} not found`);
|
||||
}
|
||||
value = fs.readFileSync(value, {encoding: 'utf-8'});
|
||||
fs.copyFileSync(value, secretFile);
|
||||
} else {
|
||||
fs.writeFileSync(secretFile, value);
|
||||
}
|
||||
const secretFile = Context.tmpName({tmpdir: Context.tmpDir()});
|
||||
fs.writeFileSync(secretFile, value);
|
||||
return [key, secretFile];
|
||||
}
|
||||
|
||||
@@ -160,7 +169,7 @@ export class Build {
|
||||
}
|
||||
try {
|
||||
return core.getBooleanInput(name) ? `builder-id=${GitHub.workflowRunURL(true)}` : 'false';
|
||||
} catch (err) {
|
||||
} catch {
|
||||
// not a valid boolean, so we assume it's a string
|
||||
return Build.resolveProvenanceAttrs(input);
|
||||
}
|
||||
@@ -293,7 +302,7 @@ export class Build {
|
||||
// https://github.com/docker/buildx/blob/8abef5908705e49f7ba88ef8c957e1127b597a2a/util/buildflags/attests.go#L13-L21
|
||||
const v = Util.parseBool(attr);
|
||||
res.push(`disabled=${!v}`);
|
||||
} catch (err) {
|
||||
} catch {
|
||||
res.push(attr);
|
||||
}
|
||||
}
|
||||
@@ -310,13 +319,16 @@ export class Build {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static parseSecretKvp(kvp: string): [string, string] {
|
||||
public static parseSecretKvp(kvp: string, redact?: boolean): [string, string] {
|
||||
const delimiterIndex = kvp.indexOf('=');
|
||||
const key = kvp.substring(0, delimiterIndex);
|
||||
const value = kvp.substring(delimiterIndex + 1);
|
||||
if (key.length == 0 || value.length == 0) {
|
||||
throw new Error(`${kvp} is not a valid secret`);
|
||||
}
|
||||
if (redact) {
|
||||
core.setSecret(value);
|
||||
}
|
||||
return [key, value];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import * as core from '@actions/core';
|
||||
import {Buildx} from './buildx';
|
||||
import {Exec} from '../exec';
|
||||
|
||||
import {BuilderInfo, GCPolicy, NodeInfo} from '../types/buildx/builder';
|
||||
import {BuilderInfo, Device, GCPolicy, NodeInfo} from '../types/buildx/builder';
|
||||
|
||||
export interface BuilderOpts {
|
||||
buildx?: Buildx;
|
||||
@@ -89,6 +89,8 @@ export class Builder {
|
||||
let parsingType: string | undefined;
|
||||
let currentNode: NodeInfo = {};
|
||||
let currentGCPolicy: GCPolicy | undefined;
|
||||
let currentDevice: Device | undefined;
|
||||
let currentFile: string | undefined;
|
||||
for (const line of data.trim().split(`\n`)) {
|
||||
const [key, ...rest] = line.split(':');
|
||||
const lkey = key.toLowerCase();
|
||||
@@ -171,6 +173,10 @@ export class Builder {
|
||||
parsingType = 'label';
|
||||
currentNode.labels = {};
|
||||
break;
|
||||
case lkey == 'devices':
|
||||
parsingType = 'devices';
|
||||
currentNode.devices = currentNode.devices || [];
|
||||
break;
|
||||
case lkey.startsWith('gc policy rule#'):
|
||||
parsingType = 'gcpolicy';
|
||||
if (currentNode.gcPolicy && currentGCPolicy) {
|
||||
@@ -178,7 +184,17 @@ export class Builder {
|
||||
currentGCPolicy = undefined;
|
||||
}
|
||||
break;
|
||||
case lkey.startsWith('file#'):
|
||||
parsingType = 'file';
|
||||
currentFile = key.split('#')[1];
|
||||
currentNode.files = currentNode.files || {};
|
||||
currentNode.files[currentFile] = '';
|
||||
break;
|
||||
default: {
|
||||
if (parsingType && parsingType !== 'devices' && currentNode.devices && currentDevice) {
|
||||
currentNode.devices.push(currentDevice);
|
||||
currentDevice = undefined;
|
||||
}
|
||||
switch (parsingType || '') {
|
||||
case 'features': {
|
||||
currentNode.features = currentNode.features || {};
|
||||
@@ -190,6 +206,42 @@ export class Builder {
|
||||
currentNode.labels[key.trim()] = value;
|
||||
break;
|
||||
}
|
||||
case 'devices': {
|
||||
switch (lkey.trim()) {
|
||||
case 'name': {
|
||||
if (currentNode.devices && currentDevice) {
|
||||
currentNode.devices.push(currentDevice);
|
||||
}
|
||||
currentDevice = {};
|
||||
currentDevice.name = value;
|
||||
break;
|
||||
}
|
||||
case 'on-demand': {
|
||||
if (currentDevice && value) {
|
||||
currentDevice.onDemand = value == 'true';
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'automatically allowed': {
|
||||
if (currentDevice && value) {
|
||||
currentDevice.autoAllow = value == 'true';
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'annotations': {
|
||||
if (currentDevice) {
|
||||
currentDevice.annotations = currentDevice.annotations || {};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (currentDevice && currentDevice.annotations) {
|
||||
currentDevice.annotations[key.trim()] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'gcpolicy': {
|
||||
currentNode.gcPolicy = currentNode.gcPolicy || [];
|
||||
currentGCPolicy = currentGCPolicy || {};
|
||||
@@ -212,6 +264,27 @@ export class Builder {
|
||||
currentGCPolicy.keepBytes = value;
|
||||
break;
|
||||
}
|
||||
case 'reserved space': {
|
||||
currentGCPolicy.reservedSpace = value;
|
||||
break;
|
||||
}
|
||||
case 'max used space': {
|
||||
currentGCPolicy.maxUsedSpace = value;
|
||||
break;
|
||||
}
|
||||
case 'min free space': {
|
||||
currentGCPolicy.minFreeSpace = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'file': {
|
||||
if (currentFile && currentNode.files) {
|
||||
if (currentNode.files[currentFile].length > 0) {
|
||||
currentNode.files[currentFile] += '\n';
|
||||
}
|
||||
currentNode.files[currentFile] += line.replace(/^\s>\s?/, '');
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -219,6 +292,9 @@ export class Builder {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentDevice && currentNode.devices) {
|
||||
currentNode.devices.push(currentDevice);
|
||||
}
|
||||
if (currentGCPolicy && currentNode.gcPolicy) {
|
||||
currentNode.gcPolicy.push(currentGCPolicy);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ export class Buildx {
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(endpoint);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
if (url.protocol != 'tcp:') {
|
||||
@@ -280,7 +280,7 @@ export class Buildx {
|
||||
const fnGitURL = function (inp: string): GitURL | undefined {
|
||||
try {
|
||||
return Git.parseURL(inp);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ import {Exec} from '../exec';
|
||||
import {GitHub} from '../github';
|
||||
import {Util} from '../util';
|
||||
|
||||
import {ExportRecordOpts, ExportRecordResponse, Summaries} from '../types/buildx/history';
|
||||
import {ExportOpts, ExportResponse, InspectOpts, InspectResponse, Summaries} from '../types/buildx/history';
|
||||
|
||||
export interface HistoryOpts {
|
||||
buildx?: Buildx;
|
||||
@@ -37,27 +37,43 @@ export interface HistoryOpts {
|
||||
export class History {
|
||||
private readonly buildx: Buildx;
|
||||
|
||||
private static readonly EXPORT_BUILD_IMAGE_DEFAULT: string = 'docker.io/dockereng/export-build:latest';
|
||||
private static readonly EXPORT_BUILD_IMAGE_ENV: string = 'DOCKER_BUILD_EXPORT_BUILD_IMAGE';
|
||||
|
||||
constructor(opts?: HistoryOpts) {
|
||||
this.buildx = opts?.buildx || new Buildx();
|
||||
}
|
||||
|
||||
public async export(opts: ExportRecordOpts): Promise<ExportRecordResponse> {
|
||||
if (os.platform() === 'win32') {
|
||||
throw new Error('Exporting a build record is currently not supported on Windows');
|
||||
}
|
||||
if (!(await Docker.isAvailable())) {
|
||||
throw new Error('Docker is required to export a build record');
|
||||
}
|
||||
if (!(await Docker.isDaemonRunning())) {
|
||||
throw new Error('Docker daemon needs to be running to export a build record');
|
||||
}
|
||||
if (!(await this.buildx.versionSatisfies('>=0.13.0'))) {
|
||||
throw new Error('Buildx >= 0.13.0 is required to export a build record');
|
||||
}
|
||||
public async getCommand(args: Array<string>) {
|
||||
return await this.buildx.getCommand(['history', ...args]);
|
||||
}
|
||||
|
||||
public async getInspectCommand(args: Array<string>) {
|
||||
return await this.getCommand(['inspect', ...args]);
|
||||
}
|
||||
|
||||
public async getExportCommand(args: Array<string>) {
|
||||
return await this.getCommand(['export', ...args]);
|
||||
}
|
||||
|
||||
public async inspect(opts: InspectOpts): Promise<InspectResponse> {
|
||||
const args: Array<string> = ['--format', 'json'];
|
||||
if (opts.builder) {
|
||||
args.push('--builder', opts.builder);
|
||||
}
|
||||
if (opts.ref) {
|
||||
args.push(opts.ref);
|
||||
}
|
||||
const cmd = await this.getInspectCommand(args);
|
||||
return await Exec.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
return <InspectResponse>JSON.parse(res.stdout);
|
||||
});
|
||||
}
|
||||
|
||||
public async export(opts: ExportOpts): Promise<ExportResponse> {
|
||||
let builderName: string = '';
|
||||
let nodeName: string = '';
|
||||
const refs: Array<string> = [];
|
||||
@@ -85,6 +101,81 @@ export class History {
|
||||
core.info(`exporting build record to ${outDir}`);
|
||||
fs.mkdirSync(outDir, {recursive: true});
|
||||
|
||||
if (opts.useContainer || (await this.buildx.versionSatisfies('<0.23.0'))) {
|
||||
return await this.exportLegacy(builderName, nodeName, refs, outDir, opts.image);
|
||||
}
|
||||
|
||||
if (await this.buildx.versionSatisfies('<0.24.0')) {
|
||||
// wait 3 seconds to ensure build records are finalized: https://github.com/moby/buildkit/pull/5109
|
||||
// not necessary since buildx 0.24.0: https://github.com/docker/buildx/pull/3152
|
||||
await Util.sleep(3);
|
||||
}
|
||||
|
||||
const summaries: Summaries = {};
|
||||
if (!opts.noSummaries) {
|
||||
for (const ref of refs) {
|
||||
await this.inspect({
|
||||
ref: ref,
|
||||
builder: builderName
|
||||
}).then(res => {
|
||||
let errorLogs = '';
|
||||
if (res.Error && res.Status !== 'canceled') {
|
||||
if (res.Error.Message) {
|
||||
errorLogs = res.Error.Message;
|
||||
} else if (res.Error.Name && res.Error.Logs) {
|
||||
errorLogs = `=> ${res.Error.Name}\n${res.Error.Logs}`;
|
||||
}
|
||||
}
|
||||
summaries[ref] = {
|
||||
name: res.Name,
|
||||
status: res.Status,
|
||||
duration: Util.formatDuration(res.Duration),
|
||||
numCachedSteps: res.NumCachedSteps,
|
||||
numTotalSteps: res.NumTotalSteps,
|
||||
numCompletedSteps: res.NumCompletedSteps,
|
||||
defaultPlatform: res.Platform?.[0],
|
||||
error: errorLogs
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const dockerbuildPath = path.join(outDir, `${History.exportFilename(refs)}.dockerbuild`);
|
||||
|
||||
const exportArgs = ['--builder', builderName, '--output', dockerbuildPath, ...refs];
|
||||
if (await this.buildx.versionSatisfies('>=0.24.0')) {
|
||||
exportArgs.push('--finalize');
|
||||
}
|
||||
|
||||
const cmd = await this.getExportCommand(exportArgs);
|
||||
await Exec.getExecOutput(cmd.command, cmd.args);
|
||||
|
||||
const dockerbuildStats = fs.statSync(dockerbuildPath);
|
||||
|
||||
return {
|
||||
dockerbuildFilename: dockerbuildPath,
|
||||
dockerbuildSize: dockerbuildStats.size,
|
||||
builderName: builderName,
|
||||
nodeName: nodeName,
|
||||
refs: refs,
|
||||
summaries: summaries
|
||||
};
|
||||
}
|
||||
|
||||
private async exportLegacy(builderName: string, nodeName: string, refs: Array<string>, outDir: string, image?: string): Promise<ExportResponse> {
|
||||
if (os.platform() === 'win32') {
|
||||
throw new Error('Exporting a build record is currently not supported on Windows');
|
||||
}
|
||||
if (!(await Docker.isAvailable())) {
|
||||
throw new Error('Docker is required to export a build record');
|
||||
}
|
||||
if (!(await Docker.isDaemonRunning())) {
|
||||
throw new Error('Docker daemon needs to be running to export a build record');
|
||||
}
|
||||
if (!(await this.buildx.versionSatisfies('>=0.13.0'))) {
|
||||
throw new Error('Buildx >= 0.13.0 is required to export a build record');
|
||||
}
|
||||
|
||||
// wait 3 seconds to ensure build records are finalized: https://github.com/moby/buildkit/pull/5109
|
||||
await Util.sleep(3);
|
||||
|
||||
@@ -139,7 +230,7 @@ export class History {
|
||||
'run', '--rm', '-i',
|
||||
'-v', `${Buildx.refsDir}:/buildx-refs`,
|
||||
'-v', `${outDir}:/out`,
|
||||
opts.image || process.env[History.EXPORT_BUILD_IMAGE_ENV] || History.EXPORT_BUILD_IMAGE_DEFAULT,
|
||||
image || process.env['DOCKER_BUILD_EXPORT_BUILD_IMAGE'] || 'docker.io/dockereng/export-build:latest',
|
||||
...ebargs
|
||||
]
|
||||
core.info(`[command]docker ${dockerRunArgs.join(' ')}`);
|
||||
@@ -190,12 +281,7 @@ export class History {
|
||||
}
|
||||
});
|
||||
|
||||
let dockerbuildFilename = `${GitHub.context.repo.owner}~${GitHub.context.repo.repo}~${refs[0].substring(0, 6).toUpperCase()}`;
|
||||
if (refs.length > 1) {
|
||||
dockerbuildFilename += `+${refs.length - 1}`;
|
||||
}
|
||||
|
||||
const dockerbuildPath = path.join(outDir, `${dockerbuildFilename}.dockerbuild`);
|
||||
const dockerbuildPath = path.join(outDir, `${History.exportFilename(refs)}.dockerbuild`);
|
||||
fs.renameSync(tmpDockerbuildFilename, dockerbuildPath);
|
||||
const dockerbuildStats = fs.statSync(dockerbuildPath);
|
||||
|
||||
@@ -206,10 +292,18 @@ export class History {
|
||||
return {
|
||||
dockerbuildFilename: dockerbuildPath,
|
||||
dockerbuildSize: dockerbuildStats.size,
|
||||
summaries: summaries,
|
||||
builderName: builderName,
|
||||
nodeName: nodeName,
|
||||
refs: refs
|
||||
refs: refs,
|
||||
summaries: summaries
|
||||
};
|
||||
}
|
||||
|
||||
private static exportFilename(refs: Array<string>): string {
|
||||
let name = `${GitHub.context.repo.owner}~${GitHub.context.repo.repo}~${refs[0].substring(0, 6).toUpperCase()}`;
|
||||
if (refs.length > 1) {
|
||||
name += `+${refs.length - 1}`;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
97
src/buildx/imagetools.ts
Normal file
97
src/buildx/imagetools.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {Buildx} from './buildx';
|
||||
import {Exec} from '../exec';
|
||||
|
||||
import {Manifest as ImageToolsManifest} from '../types/buildx/imagetools';
|
||||
import {Image} from '../types/oci/config';
|
||||
import {Descriptor} from '../types/oci/descriptor';
|
||||
import {Digest} from '../types/oci/digest';
|
||||
|
||||
export interface ImageToolsOpts {
|
||||
buildx?: Buildx;
|
||||
}
|
||||
|
||||
export class ImageTools {
|
||||
private readonly buildx: Buildx;
|
||||
|
||||
constructor(opts?: ImageToolsOpts) {
|
||||
this.buildx = opts?.buildx || new Buildx();
|
||||
}
|
||||
|
||||
public async getCommand(args: Array<string>) {
|
||||
return await this.buildx.getCommand(['imagetools', ...args]);
|
||||
}
|
||||
|
||||
public async getInspectCommand(args: Array<string>) {
|
||||
return await this.getCommand(['inspect', ...args]);
|
||||
}
|
||||
|
||||
public async inspectImage(name: string): Promise<Record<string, Image> | Image> {
|
||||
const cmd = await this.getInspectCommand([name, '--format', '{{json .Image}}']);
|
||||
return await Exec.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
const parsedOutput = JSON.parse(res.stdout);
|
||||
if (typeof parsedOutput === 'object' && !Array.isArray(parsedOutput) && parsedOutput !== null) {
|
||||
if (Object.prototype.hasOwnProperty.call(parsedOutput, 'config')) {
|
||||
return <Image>parsedOutput;
|
||||
} else {
|
||||
return <Record<string, Image>>parsedOutput;
|
||||
}
|
||||
}
|
||||
throw new Error('Unexpected output format');
|
||||
});
|
||||
}
|
||||
|
||||
public async inspectManifest(name: string): Promise<ImageToolsManifest | Descriptor> {
|
||||
const cmd = await this.getInspectCommand([name, '--format', '{{json .Manifest}}']);
|
||||
return await Exec.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
const parsedOutput = JSON.parse(res.stdout);
|
||||
if (typeof parsedOutput === 'object' && !Array.isArray(parsedOutput) && parsedOutput !== null) {
|
||||
if (Object.prototype.hasOwnProperty.call(parsedOutput, 'manifests')) {
|
||||
return <ImageToolsManifest>parsedOutput;
|
||||
} else {
|
||||
return <Descriptor>parsedOutput;
|
||||
}
|
||||
}
|
||||
throw new Error('Unexpected output format');
|
||||
});
|
||||
}
|
||||
|
||||
public async attestationDescriptors(name: string): Promise<Array<Descriptor>> {
|
||||
const manifest = await this.inspectManifest(name);
|
||||
if (typeof manifest === 'object' && manifest !== null && 'manifests' in manifest && Array.isArray(manifest.manifests)) {
|
||||
return manifest.manifests.filter(m => m.annotations && m.annotations['vnd.docker.reference.type'] === 'attestation-manifest');
|
||||
}
|
||||
throw new Error(`No attestation descriptors found for ${name}`);
|
||||
}
|
||||
|
||||
public async attestationDigests(name: string): Promise<Array<Digest>> {
|
||||
return (await this.attestationDescriptors(name)).map(attestation => attestation.digest);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as httpm from '@actions/http-client';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as semver from 'semver';
|
||||
import * as util from 'util';
|
||||
@@ -29,6 +28,7 @@ import {Context} from '../context';
|
||||
import {Exec} from '../exec';
|
||||
import {Docker} from '../docker/docker';
|
||||
import {Git} from '../git';
|
||||
import {GitHub} from '../github';
|
||||
import {Util} from '../util';
|
||||
|
||||
import {DownloadVersion} from '../types/buildx/buildx';
|
||||
@@ -36,13 +36,16 @@ import {GitHubRelease} from '../types/github';
|
||||
|
||||
export interface InstallOpts {
|
||||
standalone?: boolean;
|
||||
githubToken?: string;
|
||||
}
|
||||
|
||||
export class Install {
|
||||
private readonly _standalone: boolean | undefined;
|
||||
private readonly standalone: boolean | undefined;
|
||||
private readonly githubToken: string | undefined;
|
||||
|
||||
constructor(opts?: InstallOpts) {
|
||||
this._standalone = opts?.standalone;
|
||||
this.standalone = opts?.standalone;
|
||||
this.githubToken = opts?.githubToken || process.env.GITHUB_TOKEN;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -55,7 +58,7 @@ export class Install {
|
||||
const version: DownloadVersion = await Install.getDownloadVersion(v);
|
||||
core.debug(`Install.download version: ${version.version}`);
|
||||
|
||||
const release: GitHubRelease = await Install.getRelease(version);
|
||||
const release: GitHubRelease = await Install.getRelease(version, this.githubToken);
|
||||
core.debug(`Install.download release tag name: ${release.tag_name}`);
|
||||
|
||||
const vspec = await this.vspec(release.tag_name);
|
||||
@@ -83,7 +86,7 @@ export class Install {
|
||||
const downloadURL = util.format(version.downloadURL, vspec, this.filename(vspec));
|
||||
core.info(`Downloading ${downloadURL}`);
|
||||
|
||||
const htcDownloadPath = await tc.downloadTool(downloadURL);
|
||||
const htcDownloadPath = await tc.downloadTool(downloadURL, undefined, this.githubToken);
|
||||
core.debug(`Install.download htcDownloadPath: ${htcDownloadPath}`);
|
||||
|
||||
const cacheSavePath = await installCache.save(htcDownloadPath);
|
||||
@@ -205,7 +208,7 @@ export class Install {
|
||||
}
|
||||
|
||||
private async isStandalone(): Promise<boolean> {
|
||||
const standalone = this._standalone ?? !(await Docker.isAvailable());
|
||||
const standalone = this.standalone ?? !(await Docker.isAvailable());
|
||||
core.debug(`Install.isStandalone: ${standalone}`);
|
||||
return standalone;
|
||||
}
|
||||
@@ -285,7 +288,12 @@ export class Install {
|
||||
key: repoKey,
|
||||
version: version,
|
||||
downloadURL: 'https://github.com/docker/buildx/releases/download/v%s/%s',
|
||||
releasesURL: 'https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-releases.json'
|
||||
contentOpts: {
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-releases.json'
|
||||
}
|
||||
};
|
||||
}
|
||||
case 'cloud': {
|
||||
@@ -293,7 +301,12 @@ export class Install {
|
||||
key: repoKey,
|
||||
version: version,
|
||||
downloadURL: 'https://github.com/docker/buildx-desktop/releases/download/v%s/%s',
|
||||
releasesURL: 'https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/buildx-lab-releases.json'
|
||||
contentOpts: {
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/buildx-lab-releases.json'
|
||||
}
|
||||
};
|
||||
}
|
||||
default: {
|
||||
@@ -302,17 +315,11 @@ export class Install {
|
||||
}
|
||||
}
|
||||
|
||||
public static async getRelease(version: DownloadVersion): Promise<GitHubRelease> {
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('docker-actions-toolkit');
|
||||
const resp: httpm.HttpClientResponse = await http.get(version.releasesURL);
|
||||
const body = await resp.readBody();
|
||||
const statusCode = resp.message.statusCode || 500;
|
||||
if (statusCode >= 400) {
|
||||
throw new Error(`Failed to get Buildx releases from ${version.releasesURL} with status code ${statusCode}: ${body}`);
|
||||
}
|
||||
const releases = <Record<string, GitHubRelease>>JSON.parse(body);
|
||||
public static async getRelease(version: DownloadVersion, githubToken?: string): Promise<GitHubRelease> {
|
||||
const github = new GitHub({token: githubToken});
|
||||
const releases = await github.releases('Buildx', version.contentOpts);
|
||||
if (!releases[version.version]) {
|
||||
throw new Error(`Cannot find Buildx release ${version.version} in ${version.releasesURL}`);
|
||||
throw new Error(`Cannot find Buildx release ${version.version} in releases JSON`);
|
||||
}
|
||||
return releases[version.version];
|
||||
}
|
||||
|
||||
73
src/cache.ts
73
src/cache.ts
@@ -55,7 +55,7 @@ export class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
public async save(file: string): Promise<string> {
|
||||
public async save(file: string, skipState?: boolean): Promise<string> {
|
||||
core.debug(`Cache.save ${file}`);
|
||||
const cachePath = this.copyToCache(file);
|
||||
|
||||
@@ -63,40 +63,51 @@ export class Cache {
|
||||
core.debug(`Cache.save cached to hosted tool cache ${htcPath}`);
|
||||
|
||||
if (!this.ghaNoCache && cache.isFeatureAvailable()) {
|
||||
core.debug(`Cache.save sending ${this.ghaCacheKey} to post state`);
|
||||
core.saveState(
|
||||
Cache.POST_CACHE_KEY,
|
||||
JSON.stringify({
|
||||
dir: this.cacheDir,
|
||||
key: this.ghaCacheKey
|
||||
} as CachePostState)
|
||||
);
|
||||
if (skipState) {
|
||||
try {
|
||||
core.debug(`Cache.save caching ${this.ghaCacheKey} to GitHub Actions cache`);
|
||||
await cache.saveCache([this.cacheDir], this.ghaCacheKey);
|
||||
} catch (e) {
|
||||
core.warning(`Failed to save cache: ${e}`);
|
||||
}
|
||||
} else {
|
||||
core.debug(`Cache.save sending ${this.ghaCacheKey} to post state`);
|
||||
core.saveState(
|
||||
Cache.POST_CACHE_KEY,
|
||||
JSON.stringify({
|
||||
dir: this.cacheDir,
|
||||
key: this.ghaCacheKey
|
||||
} as CachePostState)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
public async find(): Promise<string> {
|
||||
let htcPath = tc.find(this.opts.htcName, this.opts.htcVersion, this.platform());
|
||||
if (htcPath) {
|
||||
core.info(`Restored from hosted tool cache ${htcPath}`);
|
||||
return this.copyToCache(`${htcPath}/${this.opts.cacheFile}`);
|
||||
}
|
||||
|
||||
if (!this.ghaNoCache && cache.isFeatureAvailable()) {
|
||||
core.debug(`GitHub Actions cache feature available`);
|
||||
if (await cache.restoreCache([this.cacheDir], this.ghaCacheKey)) {
|
||||
core.info(`Restored ${this.ghaCacheKey} from GitHub Actions cache`);
|
||||
htcPath = await tc.cacheDir(this.cacheDir, this.opts.htcName, this.opts.htcVersion, this.platform());
|
||||
core.info(`Cached to hosted tool cache ${htcPath}`);
|
||||
try {
|
||||
let htcPath = tc.find(this.opts.htcName, this.opts.htcVersion, this.platform());
|
||||
if (htcPath) {
|
||||
core.info(`Restored from hosted tool cache ${htcPath}`);
|
||||
return this.copyToCache(`${htcPath}/${this.opts.cacheFile}`);
|
||||
}
|
||||
} else if (this.ghaNoCache) {
|
||||
core.info(`GitHub Actions cache disabled`);
|
||||
} else {
|
||||
core.info(`GitHub Actions cache feature not available`);
|
||||
if (!this.ghaNoCache && cache.isFeatureAvailable()) {
|
||||
core.debug(`GitHub Actions cache feature available`);
|
||||
if (await cache.restoreCache([this.cacheDir], this.ghaCacheKey)) {
|
||||
core.info(`Restored ${this.ghaCacheKey} from GitHub Actions cache`);
|
||||
htcPath = await tc.cacheDir(this.cacheDir, this.opts.htcName, this.opts.htcVersion, this.platform());
|
||||
core.info(`Cached to hosted tool cache ${htcPath}`);
|
||||
return this.copyToCache(`${htcPath}/${this.opts.cacheFile}`);
|
||||
}
|
||||
} else if (this.ghaNoCache) {
|
||||
core.info(`GitHub Actions cache disabled`);
|
||||
} else {
|
||||
core.info(`GitHub Actions cache feature not available`);
|
||||
}
|
||||
} catch (e) {
|
||||
core.warning(`Failed to restore cache: ${e}`);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -115,13 +126,17 @@ export class Cache {
|
||||
if (!cacheState.dir || !cacheState.key) {
|
||||
throw new Error(`Invalid cache post state: ${state}`);
|
||||
}
|
||||
core.info(`Caching ${cacheState.key} to GitHub Actions cache`);
|
||||
await cache.saveCache([cacheState.dir], cacheState.key);
|
||||
try {
|
||||
core.info(`Caching ${cacheState.key} to GitHub Actions cache`);
|
||||
await cache.saveCache([cacheState.dir], cacheState.key);
|
||||
} catch (e) {
|
||||
core.warning(`Failed to save cache: ${e}`);
|
||||
}
|
||||
return cacheState;
|
||||
}
|
||||
|
||||
private copyToCache(file: string): string {
|
||||
core.debug(`Copying ${file} to ${this.cachePath}`);
|
||||
core.info(`Copying ${file} to ${this.cachePath}`);
|
||||
fs.copyFileSync(file, this.cachePath);
|
||||
return this.cachePath;
|
||||
}
|
||||
|
||||
106
src/compose/compose.ts
Normal file
106
src/compose/compose.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import {Docker} from '../docker/docker';
|
||||
import {Exec} from '../exec';
|
||||
|
||||
export interface ComposeOpts {
|
||||
standalone?: boolean;
|
||||
}
|
||||
|
||||
export class Compose {
|
||||
private _version: string;
|
||||
private _versionOnce: boolean;
|
||||
private readonly _standalone: boolean | undefined;
|
||||
|
||||
constructor(opts?: ComposeOpts) {
|
||||
this._standalone = opts?.standalone;
|
||||
this._version = '';
|
||||
this._versionOnce = false;
|
||||
}
|
||||
|
||||
public async isStandalone(): Promise<boolean> {
|
||||
const standalone = this._standalone ?? !(await Docker.isAvailable());
|
||||
core.debug(`Compose.isStandalone: ${standalone}`);
|
||||
return standalone;
|
||||
}
|
||||
|
||||
public async getCommand(args: Array<string>) {
|
||||
const standalone = await this.isStandalone();
|
||||
return {
|
||||
command: standalone ? 'compose' : 'docker',
|
||||
args: standalone ? args : ['compose', ...args]
|
||||
};
|
||||
}
|
||||
|
||||
public async isAvailable(): Promise<boolean> {
|
||||
const cmd = await this.getCommand([]);
|
||||
|
||||
const ok: boolean = await Exec.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.debug(`Compose.isAvailable cmd err: ${res.stderr.trim()}`);
|
||||
return false;
|
||||
}
|
||||
return res.exitCode == 0;
|
||||
})
|
||||
.catch(error => {
|
||||
core.debug(`Compose.isAvailable error: ${error}`);
|
||||
return false;
|
||||
});
|
||||
|
||||
core.debug(`Compose.isAvailable: ${ok}`);
|
||||
return ok;
|
||||
}
|
||||
|
||||
public async version(): Promise<string> {
|
||||
if (this._versionOnce) {
|
||||
return this._version;
|
||||
}
|
||||
this._versionOnce = true;
|
||||
const cmd = await this.getCommand(['version']);
|
||||
this._version = await Exec.getExecOutput(cmd.command, cmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
return Compose.parseVersion(res.stdout.trim());
|
||||
});
|
||||
return this._version;
|
||||
}
|
||||
|
||||
public async printVersion() {
|
||||
const cmd = await this.getCommand(['version']);
|
||||
await Exec.exec(cmd.command, cmd.args, {
|
||||
failOnStdErr: false
|
||||
});
|
||||
}
|
||||
|
||||
public static parseVersion(stdout: string): string {
|
||||
const matches = /\sv?([0-9a-f]{7}|[0-9.]+)/.exec(stdout);
|
||||
if (!matches) {
|
||||
throw new Error(`Cannot parse compose version`);
|
||||
}
|
||||
return matches[1];
|
||||
}
|
||||
}
|
||||
224
src/compose/install.ts
Normal file
224
src/compose/install.ts
Normal file
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as semver from 'semver';
|
||||
import * as util from 'util';
|
||||
|
||||
import {Cache} from '../cache';
|
||||
import {Context} from '../context';
|
||||
import {Docker} from '../docker/docker';
|
||||
import {GitHub} from '../github';
|
||||
|
||||
import {DownloadVersion} from '../types/compose/compose';
|
||||
import {GitHubRelease} from '../types/github';
|
||||
|
||||
export interface InstallOpts {
|
||||
standalone?: boolean;
|
||||
githubToken?: string;
|
||||
}
|
||||
|
||||
export class Install {
|
||||
private readonly standalone: boolean | undefined;
|
||||
private readonly githubToken: string | undefined;
|
||||
|
||||
constructor(opts?: InstallOpts) {
|
||||
this.standalone = opts?.standalone;
|
||||
this.githubToken = opts?.githubToken || process.env.GITHUB_TOKEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Download compose binary from GitHub release
|
||||
* @param v: version semver version or latest
|
||||
* @param ghaNoCache: disable binary caching in GitHub Actions cache backend
|
||||
* @returns path to the compose binary
|
||||
*/
|
||||
public async download(v: string, ghaNoCache?: boolean): Promise<string> {
|
||||
const version: DownloadVersion = await Install.getDownloadVersion(v);
|
||||
core.debug(`Install.download version: ${version.version}`);
|
||||
|
||||
const release: GitHubRelease = await Install.getRelease(version, this.githubToken);
|
||||
core.debug(`Install.download release tag name: ${release.tag_name}`);
|
||||
|
||||
const vspec = await this.vspec(release.tag_name);
|
||||
core.debug(`Install.download vspec: ${vspec}`);
|
||||
|
||||
const c = semver.clean(vspec) || '';
|
||||
if (!semver.valid(c)) {
|
||||
throw new Error(`Invalid Compose version "${vspec}".`);
|
||||
}
|
||||
|
||||
const installCache = new Cache({
|
||||
htcName: version.key != 'official' ? `compose-dl-bin-${version.key}` : 'compose-dl-bin',
|
||||
htcVersion: vspec,
|
||||
baseCacheDir: path.join(os.homedir(), '.bin', 'docker-compose'),
|
||||
cacheFile: os.platform() == 'win32' ? 'docker-compose.exe' : 'docker-compose',
|
||||
ghaNoCache: ghaNoCache
|
||||
});
|
||||
|
||||
const cacheFoundPath = await installCache.find();
|
||||
if (cacheFoundPath) {
|
||||
core.info(`Compose binary found in ${cacheFoundPath}`);
|
||||
return cacheFoundPath;
|
||||
}
|
||||
|
||||
const downloadURL = util.format(version.downloadURL, vspec, this.filename());
|
||||
core.info(`Downloading ${downloadURL}`);
|
||||
|
||||
const htcDownloadPath = await tc.downloadTool(downloadURL, undefined, this.githubToken);
|
||||
core.debug(`Install.download htcDownloadPath: ${htcDownloadPath}`);
|
||||
|
||||
const cacheSavePath = await installCache.save(htcDownloadPath);
|
||||
core.info(`Cached to ${cacheSavePath}`);
|
||||
return cacheSavePath;
|
||||
}
|
||||
|
||||
public async installStandalone(binPath: string, dest?: string): Promise<string> {
|
||||
core.info('Standalone mode');
|
||||
dest = dest || Context.tmpDir();
|
||||
|
||||
const binDir = path.join(dest, 'compose-bin-standalone');
|
||||
if (!fs.existsSync(binDir)) {
|
||||
fs.mkdirSync(binDir, {recursive: true});
|
||||
}
|
||||
const binName: string = os.platform() == 'win32' ? 'compose.exe' : 'compose';
|
||||
const composePath: string = path.join(binDir, binName);
|
||||
fs.copyFileSync(binPath, composePath);
|
||||
|
||||
core.info('Fixing perms');
|
||||
fs.chmodSync(composePath, '0755');
|
||||
|
||||
core.addPath(binDir);
|
||||
core.info('Added Compose to PATH');
|
||||
|
||||
core.info(`Binary path: ${composePath}`);
|
||||
return composePath;
|
||||
}
|
||||
|
||||
public async installPlugin(binPath: string, dest?: string): Promise<string> {
|
||||
core.info('Docker plugin mode');
|
||||
dest = dest || Docker.configDir;
|
||||
|
||||
const pluginsDir: string = path.join(dest, 'cli-plugins');
|
||||
if (!fs.existsSync(pluginsDir)) {
|
||||
fs.mkdirSync(pluginsDir, {recursive: true});
|
||||
}
|
||||
const binName: string = os.platform() == 'win32' ? 'docker-compose.exe' : 'docker-compose';
|
||||
const pluginPath: string = path.join(pluginsDir, binName);
|
||||
fs.copyFileSync(binPath, pluginPath);
|
||||
|
||||
core.info('Fixing perms');
|
||||
fs.chmodSync(pluginPath, '0755');
|
||||
|
||||
core.info(`Plugin path: ${pluginPath}`);
|
||||
return pluginPath;
|
||||
}
|
||||
|
||||
private async isStandalone(): Promise<boolean> {
|
||||
const standalone = this.standalone ?? !(await Docker.isAvailable());
|
||||
core.debug(`Install.isStandalone: ${standalone}`);
|
||||
return standalone;
|
||||
}
|
||||
|
||||
private filename(): string {
|
||||
let arch: string;
|
||||
switch (os.arch()) {
|
||||
case 'x64': {
|
||||
arch = 'x86_64';
|
||||
break;
|
||||
}
|
||||
case 'ppc64': {
|
||||
arch = 'ppc64le';
|
||||
break;
|
||||
}
|
||||
case 'arm': {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const arm_version = (process.config.variables as any).arm_version;
|
||||
arch = arm_version ? 'armv' + arm_version : 'arm';
|
||||
break;
|
||||
}
|
||||
case 'arm64': {
|
||||
arch = 'aarch64';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
arch = os.arch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
const platform: string = os.platform() == 'win32' ? 'windows' : os.platform();
|
||||
const ext: string = os.platform() == 'win32' ? '.exe' : '';
|
||||
return util.format('docker-compose-%s-%s%s', platform, arch, ext);
|
||||
}
|
||||
|
||||
private async vspec(version: string): Promise<string> {
|
||||
const v = version.replace(/^v+|v+$/g, '');
|
||||
core.info(`Use ${v} version spec cache key for ${version}`);
|
||||
return v;
|
||||
}
|
||||
|
||||
public static async getDownloadVersion(v: string): Promise<DownloadVersion> {
|
||||
let [repoKey, version] = v.split(':');
|
||||
if (!version) {
|
||||
version = repoKey;
|
||||
repoKey = 'official';
|
||||
}
|
||||
switch (repoKey) {
|
||||
case 'official': {
|
||||
return {
|
||||
key: repoKey,
|
||||
version: version,
|
||||
downloadURL: 'https://github.com/docker/compose/releases/download/v%s/%s',
|
||||
contentOpts: {
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/compose-releases.json'
|
||||
}
|
||||
};
|
||||
}
|
||||
case 'cloud': {
|
||||
return {
|
||||
key: repoKey,
|
||||
version: version,
|
||||
downloadURL: 'https://github.com/docker/compose-desktop/releases/download/v%s/%s',
|
||||
contentOpts: {
|
||||
owner: 'docker',
|
||||
repo: 'actions-toolkit',
|
||||
ref: 'main',
|
||||
path: '.github/compose-lab-releases.json'
|
||||
}
|
||||
};
|
||||
}
|
||||
default: {
|
||||
throw new Error(`Cannot find compose version for ${v}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async getRelease(version: DownloadVersion, githubToken?: string): Promise<GitHubRelease> {
|
||||
const github = new GitHub({token: githubToken});
|
||||
const releases = await github.releases('Compose', version.contentOpts);
|
||||
if (!releases[version.version]) {
|
||||
throw new Error(`Cannot find Compose release ${version.version} in releases JSON`);
|
||||
}
|
||||
return releases[version.version];
|
||||
}
|
||||
}
|
||||
@@ -39,23 +39,23 @@ export class Context {
|
||||
}
|
||||
|
||||
public static gitRef(): string {
|
||||
let gitRef = github.context.ref;
|
||||
if (github.context.sha && gitRef && !gitRef.startsWith('refs/')) {
|
||||
gitRef = `refs/heads/${github.context.ref}`;
|
||||
return Context.parseGitRef(github.context.ref, github.context.sha);
|
||||
}
|
||||
|
||||
public static parseGitRef(ref: string, sha: string): string {
|
||||
const setPullRequestHeadRef: boolean = !!(process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF && process.env.DOCKER_DEFAULT_GIT_CONTEXT_PR_HEAD_REF === 'true');
|
||||
if (sha && ref && !ref.startsWith('refs/')) {
|
||||
ref = `refs/heads/${ref}`;
|
||||
}
|
||||
if (github.context.sha && !gitRef.startsWith(`refs/pull/`)) {
|
||||
gitRef = github.context.sha;
|
||||
} else if (gitRef.startsWith(`refs/pull/`)) {
|
||||
gitRef = gitRef.replace(/\/merge$/g, '/head');
|
||||
if (sha && !ref.startsWith(`refs/pull/`)) {
|
||||
ref = sha;
|
||||
} else if (ref.startsWith(`refs/pull/`) && setPullRequestHeadRef) {
|
||||
ref = ref.replace(/\/merge$/g, '/head');
|
||||
}
|
||||
return gitRef;
|
||||
return ref;
|
||||
}
|
||||
|
||||
public static gitContext(): string {
|
||||
return `${GitHub.serverURL}/${github.context.repo.owner}/${github.context.repo.repo}.git#${Context.gitRef()}`;
|
||||
}
|
||||
|
||||
public static provenanceBuilderID(): string {
|
||||
return `${GitHub.serverURL}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`;
|
||||
}
|
||||
}
|
||||
|
||||
157
src/cosign/cosign.ts
Normal file
157
src/cosign/cosign.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Copyright 2025 actions-toolkit authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as core from '@actions/core';
|
||||
import {BUNDLE_V03_MEDIA_TYPE, SerializedBundle} from '@sigstore/bundle';
|
||||
|
||||
import {Exec} from '../exec';
|
||||
import * as semver from 'semver';
|
||||
import {MEDIATYPE_EMPTY_JSON_V1} from '../types/oci/mediatype';
|
||||
|
||||
export interface CosignOpts {
|
||||
binPath?: string;
|
||||
}
|
||||
|
||||
export interface CosignCommandResult {
|
||||
bundle?: SerializedBundle;
|
||||
signatureManifestDigest?: string;
|
||||
errors?: Array<CosignCommandError>;
|
||||
}
|
||||
|
||||
export interface CosignCommandError {
|
||||
code: string;
|
||||
message: string;
|
||||
detail: string;
|
||||
}
|
||||
|
||||
export class Cosign {
|
||||
private readonly binPath: string;
|
||||
private _version: string;
|
||||
private _versionOnce: boolean;
|
||||
|
||||
constructor(opts?: CosignOpts) {
|
||||
this.binPath = opts?.binPath || 'cosign';
|
||||
this._version = '';
|
||||
this._versionOnce = false;
|
||||
}
|
||||
|
||||
public async isAvailable(): Promise<boolean> {
|
||||
const ok: boolean = await Exec.getExecOutput(this.binPath, [], {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.debug(`Cosign.isAvailable cmd err: ${res.stderr.trim()}`);
|
||||
return false;
|
||||
}
|
||||
return res.exitCode == 0;
|
||||
})
|
||||
.catch(error => {
|
||||
core.debug(`Cosign.isAvailable error: ${error}`);
|
||||
return false;
|
||||
});
|
||||
|
||||
core.debug(`Cosign.isAvailable: ${ok}`);
|
||||
return ok;
|
||||
}
|
||||
|
||||
public async version(): Promise<string> {
|
||||
if (this._versionOnce) {
|
||||
return this._version;
|
||||
}
|
||||
this._versionOnce = true;
|
||||
this._version = await Exec.getExecOutput(this.binPath, ['version', '--json'], {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
return JSON.parse(res.stdout.trim()).gitVersion;
|
||||
});
|
||||
return this._version;
|
||||
}
|
||||
|
||||
public async printVersion() {
|
||||
await Exec.exec(this.binPath, ['version', '--json'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
}
|
||||
|
||||
public async versionSatisfies(range: string, version?: string): Promise<boolean> {
|
||||
const ver = version ?? (await this.version());
|
||||
if (!ver) {
|
||||
core.debug(`Cosign.versionSatisfies false: undefined version`);
|
||||
return false;
|
||||
}
|
||||
const res = semver.satisfies(ver, range) || /^[0-9a-f]{7}$/.exec(ver) !== null;
|
||||
core.debug(`Cosign.versionSatisfies ${ver} statisfies ${range}: ${res}`);
|
||||
return res;
|
||||
}
|
||||
|
||||
public static parseCommandOutput(logs: string): CosignCommandResult {
|
||||
let signatureManifestDigest: string | undefined;
|
||||
let signatureManifestFallbackDigest: string | undefined;
|
||||
let bundlePayload: SerializedBundle | undefined;
|
||||
let errors: Array<CosignCommandError> | undefined;
|
||||
|
||||
for (const rawLine of logs.split(/\r?\n/)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line.startsWith('{') || !line.endsWith('}')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let obj: any;
|
||||
try {
|
||||
obj = JSON.parse(line);
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj && Array.isArray(obj.errors) && obj.errors.length > 0) {
|
||||
errors = obj.errors;
|
||||
}
|
||||
|
||||
// signature manifest digest
|
||||
if (!signatureManifestDigest && obj && Array.isArray(obj.manifests) && obj.manifests.length > 0) {
|
||||
const m0 = obj.manifests[0];
|
||||
if (m0?.artifactType === BUNDLE_V03_MEDIA_TYPE && typeof m0.digest === 'string') {
|
||||
signatureManifestDigest = m0.digest;
|
||||
} else if (m0?.artifactType === MEDIATYPE_EMPTY_JSON_V1 && typeof m0.digest === 'string') {
|
||||
signatureManifestFallbackDigest = m0.digest;
|
||||
}
|
||||
}
|
||||
|
||||
// signature payload
|
||||
if (!bundlePayload && obj && obj.mediaType === BUNDLE_V03_MEDIA_TYPE) {
|
||||
bundlePayload = obj as SerializedBundle;
|
||||
}
|
||||
|
||||
if (bundlePayload && (signatureManifestDigest || signatureManifestFallbackDigest)) {
|
||||
errors = undefined; // clear errors if we have both payload and manifest digest
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
bundle: bundlePayload,
|
||||
signatureManifestDigest: signatureManifestDigest || signatureManifestFallbackDigest,
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user