Compare commits
673 Commits
Author | SHA1 | Date |
---|---|---|
|
c08cd7bcfb | |
|
243fc424c6 | |
|
8203df0b7a | |
|
1b3b149dbb | |
|
e7822a0290 | |
|
45a5e35df2 | |
|
bc04fbfd78 | |
|
ea2852dd9a | |
|
18140f827a | |
|
d8b50c36e4 | |
|
5d720bb8a0 | |
|
d110e07917 | |
|
751bc8a075 | |
|
c502bcff68 | |
|
38f5d4b793 | |
|
528961a836 | |
|
5e5a81ddb5 | |
|
76d851afc5 | |
|
d82294e03f | |
|
4178e0a07b | |
|
9953a03bda | |
|
0f05ba41fb | |
|
c570d57aa4 | |
|
8df5264704 | |
|
780a56ed93 | |
|
1dfea72f46 | |
|
4a9e235d68 | |
|
f1c4c5766b | |
|
a8acb3f9a7 | |
|
f94abf303b | |
|
32b8c63071 | |
|
b048033711 | |
|
7de8e24e0d | |
|
29954e5d00 | |
|
9aa7522028 | |
|
8748b2e7ad | |
|
911913c80c | |
|
44dbd3c265 | |
|
77442414b8 | |
|
7b41d858fb | |
|
f4251b23f9 | |
|
f6258a2636 | |
|
c9202732af | |
|
bfce5a9547 | |
|
aee15ce0ad | |
|
cfd0824279 | |
|
02e0944151 | |
|
d9acce14c7 | |
|
fa46dd6bc5 | |
|
22e7e9902e | |
|
4356ef99f2 | |
|
c8707aff90 | |
|
0091b94408 | |
|
eae69c59ed | |
|
ed1ae4e868 | |
|
de1b30f66e | |
|
06f47c8204 | |
|
bd8aab272a | |
|
42bd82e6d2 | |
|
fb8eeacdca | |
|
33d9f0028e | |
|
f4c7058406 | |
|
412f8cac6c | |
|
f0c0434f01 | |
|
69d265b0e7 | |
|
ada713fa6c | |
|
6a3cf8beea | |
|
3013147563 | |
|
0c52a76701 | |
|
373252b3c0 | |
|
097ae026e0 | |
|
16f7df2e0c | |
|
7ce42707ac | |
|
ad67679608 | |
|
4a3edac4d4 | |
|
c07956ac9f | |
|
ccae3d1f71 | |
|
7c45a59720 | |
|
08462f4d3d | |
|
814dd1ca07 | |
|
f7c510438b | |
|
727ec51a93 | |
|
3377e89ad9 | |
|
d2bc2a3b9a | |
|
98717b3e4c | |
|
f4737bbcae | |
|
c904f3fc18 | |
|
3dd4637ca5 | |
|
5ffd31d938 | |
|
498ce12916 | |
|
488216c4bc | |
|
c4e0853d16 | |
|
72a4939265 | |
|
29c8c5e587 | |
|
d62dbaa71f | |
|
84bd2d709e | |
|
b1a1235d45 | |
|
74fb89f782 | |
|
9216587f3d | |
|
139f21560b | |
|
608e0af98f | |
|
0791744e95 | |
|
d42c1e350b | |
|
d1a7091db2 | |
|
d8ae516bc8 | |
|
5d0c5afb0e | |
|
795bdb6c80 | |
|
531163eca4 | |
|
3a207733aa | |
|
a01e6f57f5 | |
|
bec357e41d | |
|
4d3df7200a | |
|
a7fcb59b41 | |
|
66ea4c697f | |
|
957699bcc5 | |
|
c04c0d8332 | |
|
43e7572538 | |
|
526a12ef9f | |
|
c9c23f93e9 | |
|
5bb083d020 | |
|
0bf0db866e | |
|
49b6dd589d | |
|
afda559a08 | |
|
9499ff5f45 | |
|
6b72400de6 | |
|
d53a160a25 | |
|
dd74456400 | |
|
cecfc0d579 | |
|
c9cc53fefe | |
|
d62c862a48 | |
|
58dbbf8c3c | |
|
ecfa32a416 | |
|
6301ff0522 | |
|
a8586c106b | |
|
42e607fba9 | |
|
a57c6a326d | |
|
b9e901e235 | |
|
b1ae9b1ee4 | |
|
1669934db9 | |
|
a9e9b62a82 | |
|
10385e72f3 | |
|
9ecdacfa25 | |
|
84fcbcb3cc | |
|
7e9450d314 | |
|
262231455d | |
|
e5edff9946 | |
|
203f9fe12a | |
|
a2a89fdef0 | |
|
07eee611a5 | |
|
3ff70d149e | |
|
3ce6c725e4 | |
|
1517ec3795 | |
|
110012fecc | |
|
f7ac69ddc7 | |
|
325b286d0b | |
|
735e1008ff | |
|
fa2cb5db71 | |
|
b852fbd67b | |
|
5a1ffe9e4a | |
|
4367699d97 | |
|
91e821cb5c | |
|
c405b72492 | |
|
968cf0a6ac | |
|
809fd39d43 | |
|
bf3f0d85e1 | |
|
56d989612d | |
|
cf7fdbd767 | |
|
47853a20ff | |
|
dbdd81d1a3 | |
|
a36c382fa1 | |
|
5fad9fd396 | |
|
3e5d5f7278 | |
|
5d66d5c4c5 | |
|
3988ba7830 | |
|
b13b637677 | |
|
375e81e6d2 | |
|
8a6ae92e88 | |
|
ac1d744f15 | |
|
67bca7aec6 | |
|
2fa127b631 | |
|
0ad8d0b144 | |
|
1f856ee41f | |
|
5432492968 | |
|
3ee9f786e2 | |
|
a2ad772491 | |
|
f1b96de7fe | |
|
2e68ecd1e9 | |
|
e2c4c41dae | |
|
c8840ede49 | |
|
cd90845687 | |
|
17e011c630 | |
|
48337ef606 | |
|
e9e8320d64 | |
|
62bb92dbda | |
|
242b58607d | |
|
0505884cb5 | |
|
02b377c32c | |
|
0adc94f79b | |
|
adab52b298 | |
|
2ee17661f8 | |
|
1ef294691b | |
|
59d8a0c4bb | |
|
2bd55c17ed | |
|
f0ed5cb36b | |
|
6b6c823302 | |
|
0a62dba4e8 | |
|
d666cfe8e3 | |
|
6074760b89 | |
|
813e7deb4a | |
|
6ab5b4f668 | |
|
56c31d3e9b | |
|
603e9b1207 | |
|
b12f10ff97 | |
|
4235a0ec23 | |
|
3930745bec | |
|
c43a300dc4 | |
|
8c9afb6b8b | |
|
0db80b63b3 | |
|
c22572f3bd | |
|
e178a944d6 | |
|
bfcfc0f13d | |
|
713a9499c3 | |
|
8d52264333 | |
|
45c7b74353 | |
|
ce34472d38 | |
|
958a531928 | |
|
75caac9c42 | |
|
f13d2af1a4 | |
|
e2496a24ce | |
|
7ed47a732b | |
|
0af178c514 | |
|
7d615c63ef | |
|
9ef1a21cc0 | |
|
8616a4ca7a | |
|
7410ece496 | |
|
ce21306f08 | |
|
b77f24140e | |
|
e7b5393963 | |
|
d0280c93df | |
|
f0ecebd037 | |
|
b893858477 | |
|
fd46245b3a | |
|
4ad31e11b0 | |
|
b8b16c1382 | |
|
49a2597c07 | |
|
723a8f4cfe | |
|
dc00d430d3 | |
|
8890c9a913 | |
|
f9e36f63bf | |
|
870e3338a1 | |
|
3f26e5551b | |
|
e8a7eebb19 | |
|
0331efe90e | |
|
5352e7080c | |
|
6ab96ffce9 | |
|
f8fcd0a89a | |
|
83dad353d9 | |
|
13d1f73a61 | |
|
221018fe74 | |
|
4d7abdef22 | |
|
0edbcc48d6 | |
|
2914f8895d | |
|
958abb5438 | |
|
003dd2b9fc | |
|
8954029f18 | |
|
76e48787c9 | |
|
a56d3e21ca | |
|
e557e50e84 | |
|
2c2fe0dad1 | |
|
0fe891e8d7 | |
|
06df285152 | |
|
11f06d671b | |
|
d7ef4dcfba | |
|
6d74d55b52 | |
|
051c0f44e0 | |
|
3b4c6d30be | |
|
987415a6f8 | |
|
64ba9dec19 | |
|
ab354230b5 | |
|
0336572461 | |
|
ae7e4fe587 | |
|
f877c20208 | |
|
531e4c440f | |
|
48685a7c85 | |
|
f25ef35441 | |
|
4088e54c67 | |
|
9a613e9591 | |
|
8280237017 | |
|
584ece3e1f | |
|
80521ef38e | |
|
d1e64386fc | |
|
e1a999cfa9 | |
|
7c4705bcc4 | |
|
6b8fc8add9 | |
|
b6dbbcc476 | |
|
5ece0e5027 | |
|
a7e6edbe66 | |
|
96b251e209 | |
|
d9e9ee5f00 | |
|
6c325fd3d1 | |
|
0378f2c134 | |
|
ba5071b500 | |
|
e3074c181f | |
|
6986499806 | |
|
1d954434fe | |
|
6116ed1d9e | |
|
8fe4b4d9ab | |
|
f3e4a55bb3 | |
|
da8c69a2c4 | |
|
0d48762de2 | |
|
d9912ec330 | |
|
fdcf34e13e | |
|
15c49d2a13 | |
|
3fd840ae31 | |
|
3180a33ac2 | |
|
0dec7acff7 | |
|
52cffce497 | |
|
1e0b1351d3 | |
|
45ef326653 | |
|
bec37d2923 | |
|
91a581e0c0 | |
|
4de19906ea | |
|
04db01b558 | |
|
66ec13f929 | |
|
cf150c8802 | |
|
a75ba27081 | |
|
48a6c34c23 | |
|
7fc3d67335 | |
|
03188e3daf | |
|
ef6e4f6dc7 | |
|
ada1ea6581 | |
|
0a008043cb | |
|
5b5e38b2e4 | |
|
1e8287a7e7 | |
|
e292f96d2d | |
|
493d9881b2 | |
|
ef7a248644 | |
|
232f802cd7 | |
|
a00a3713c0 | |
|
2018fad17b | |
|
3333d65455 | |
|
1888d97ebb | |
|
9d6fbc241d | |
|
b6d5a26f79 | |
|
804c1b29be | |
|
06777e6a83 | |
|
5f21c573c7 | |
|
55e087252b | |
|
0115938125 | |
|
0b490fd751 | |
|
42a9fee04d | |
|
85dc1eeda9 | |
|
b4a60bb809 | |
|
0ef5f6710d | |
|
e82e0eec54 | |
|
92c7bacb93 | |
|
3325f90e16 | |
|
f25667dd83 | |
|
590008b44f | |
|
a1d97d6734 | |
|
818be7f582 | |
|
6115e5f562 | |
|
5b7389c251 | |
|
c50f6ec4df | |
|
2165a24896 | |
|
0e027d723f | |
|
2de474a5a7 | |
|
684aafe89c | |
|
2d3d7f4f02 | |
|
8eade6c6f4 | |
|
e01886b8ad | |
|
117fba6c30 | |
|
faece5c355 | |
|
741d8fe16a | |
|
7bd8cb5169 | |
|
a0471b6e0a | |
|
6a83d94543 | |
|
2fe8bb1150 | |
|
1d9b5f4515 | |
|
6c0598a11f | |
|
b8357b48cd | |
|
876cd4eb09 | |
|
ddbf51b9ca | |
|
1fe3e4e2bc | |
|
a6098000e6 | |
|
30e281cd66 | |
|
5021db883c | |
|
92aaab5ad3 | |
|
c80affc2e1 | |
|
0dd744c6d2 | |
|
1723cdfce0 | |
|
b6ba64dfa0 | |
|
a44e50bf2b | |
|
b3b424d803 | |
|
1481037283 | |
|
1e1d8b162e | |
|
d464a76c22 | |
|
54398fe256 | |
|
ae36f50354 | |
|
a6cbb654e7 | |
|
1d1f4b2d2a | |
|
c1062b66a5 | |
|
4937ffab4f | |
|
192f6a9def | |
|
b342dd1962 | |
|
15592c1cea | |
|
02abf96234 | |
|
08abd306f2 | |
|
3ee8ef0eac | |
|
bcb62e8f1e | |
|
ea6cf5090a | |
|
3e2c13fe91 | |
|
2e8fdf277d | |
|
2330778519 | |
|
f29aa2068a | |
|
965a57d69c | |
|
c13cb8e5f8 | |
|
1f67dc9658 | |
|
707e59c8f7 | |
|
10356ac4f4 | |
|
e3da59d262 | |
|
600ae44efd | |
|
7dbd60760a | |
|
e361d5e0f5 | |
|
1efedbd7f7 | |
|
bd043fc803 | |
|
e739642b6f | |
|
06cc76f311 | |
|
366946c3e0 | |
|
719b7ff147 | |
|
6bd010cfbd | |
|
e52a1ac580 | |
|
918407dc3e | |
|
2a5af9afaf | |
|
5863adf1ca | |
|
c6b0cfd25b | |
|
3cd1bbc739 | |
|
d17d979ca1 | |
|
052601f0b6 | |
|
6bad575a09 | |
|
0b5cd009ad | |
|
5af8d9200b | |
|
9f21c5698c | |
|
f8d06a6e2d | |
|
785c9f3fa3 | |
|
d0ee780a27 | |
|
98d649ef70 | |
|
8505f7edbc | |
|
5a0e4bf014 | |
|
486f1462e7 | |
|
aae7ef41f4 | |
|
ebe87a09fb | |
|
c0c1b422b5 | |
|
b7bec64067 | |
|
ce93d670b6 | |
|
3e3ba5e3a8 | |
|
38931c8396 | |
|
c3a766d3f9 | |
|
2164b8a452 | |
|
73617d09c1 | |
|
8b87c174e4 | |
|
cafa80a156 | |
|
2d9093c00c | |
|
241a0d4659 | |
|
05bf943d11 | |
|
3324e6a235 | |
|
9c3d8e1313 | |
|
2f0de36377 | |
|
5db30ae1a7 | |
|
2fb528ffd5 | |
|
58e50f2124 | |
|
3643022260 | |
|
f816d7d35e | |
|
81c91ffb7c | |
|
1a778c3b4c | |
|
117bbe7b93 | |
|
e95fa4691c | |
|
90c778f20a | |
|
2cc584c875 | |
|
88b56f06e8 | |
|
d4ea5db099 | |
|
f07d3cd72e | |
|
dafc473811 | |
|
e116980b41 | |
|
7b9c47206f | |
|
5d966ab5eb | |
|
1a1a26a5c4 | |
|
a6914d7162 | |
|
b1aff185cf | |
|
5ab19cf9b6 | |
|
177746ff70 | |
|
77735ff8e6 | |
|
ab6b22ee45 | |
|
7410720785 | |
|
d16cd7e096 | |
|
842e0f9a14 | |
|
1c69bbfe16 | |
|
87f02c268d | |
|
03adb20f05 | |
|
7fe92ab551 | |
|
78c9877514 | |
|
07e3204438 | |
|
21fbcb324f | |
|
353f851f6a | |
|
11c167a7a9 | |
|
9f51b2733d | |
|
c4a4f9b01b | |
|
92f1f32cd6 | |
|
067590dc31 | |
|
c9806eb7f2 | |
|
934b140016 | |
|
81610b7b99 | |
|
4817399e23 | |
|
07bcb80d9e | |
|
4ebefa7918 | |
|
4e59a9b7bd | |
|
fd0c09d01b | |
|
606a0a9f88 | |
|
84d14e5353 | |
|
b3751e34ef | |
|
c74ffc6d13 | |
|
3e78d72888 | |
|
f6b10a16a4 | |
|
dfc703a143 | |
|
6d9c79ee24 | |
|
82f6e1461d | |
|
65570ee59e | |
|
5e3a904d4b | |
|
a9fa7f3f6b | |
|
9594a17faa | |
|
f29800c92b | |
|
81169b5a2a | |
|
918440fb59 | |
|
0cb2854c47 | |
|
4df562b3a4 | |
|
40ded4d610 | |
|
3ff24a4001 | |
|
cd223c591e | |
|
f5251259b0 | |
|
c31f082b73 | |
|
e731f1288d | |
|
a3d82dada9 | |
|
19e9557da1 | |
|
881ae8c6a7 | |
|
611530945e | |
|
d85636b3d5 | |
|
8b9f59e437 | |
|
38ff1abf83 | |
|
8c55a0928f | |
|
2bf4937220 | |
|
8831c9a279 | |
|
0c92605c5c | |
|
36d797af50 | |
|
98fad096ba | |
|
3a44ccff5a | |
|
d14e97ea79 | |
|
3d2249e171 | |
|
264ec7a86d | |
|
f09a33a963 | |
|
92d5e723b8 | |
|
f42a729811 | |
|
d69d9255c6 | |
|
21ef178447 | |
|
207a180c56 | |
|
f1647cb5ec | |
|
b4e144932a | |
|
2533998737 | |
|
5e11309d7c | |
|
8d2c7caf36 | |
|
df85841cb6 | |
|
fbdbb6f7ac | |
|
62a796fb22 | |
|
d22836b392 | |
|
a70a97db54 | |
|
97e59d2845 | |
|
196a8aa2a4 | |
|
8d8ec2ae31 | |
|
f9a86702e6 | |
|
9cdeb5919c | |
|
536fdc26af | |
|
2cc27c7baa | |
|
3c4c882a04 | |
|
cd1bb911ff | |
|
1edce17f54 | |
|
6e3fdebe2b | |
|
25419a8d57 | |
|
85a3c10137 | |
|
0f9ef3068e | |
|
8204dc6ec2 | |
|
397304e2eb | |
|
50d73f2d77 | |
|
68093b0f1a | |
|
5609f7e1d3 | |
|
3db0b1cd58 | |
|
b3038dd2ad | |
|
5e3db79cda | |
|
e7f48371eb | |
|
4cd1cb8639 | |
|
3700568de0 | |
|
da2228a41b | |
|
493b7ff4fa | |
|
1368589930 | |
|
2a7d261e50 | |
|
22b18df5e4 | |
|
a411570c60 | |
|
a5b7b34879 | |
|
b3f574f373 | |
|
4832ee1ce9 | |
|
44dd9d1e55 | |
|
ac5caff5ea | |
|
c80aa72f7f | |
|
8ccf0d66b5 | |
|
f24464c6ed | |
|
456a4b90ac | |
|
94eabf47c4 | |
|
18fab63b02 | |
|
9324c2f4cf | |
|
4be39a64f2 | |
|
7760893ac0 | |
|
e30e95ef4e | |
|
1b19006a0f | |
|
225b568d52 | |
|
7e3dd1425f | |
|
43682e07eb | |
|
b3d523fb36 | |
|
f9e5484fd3 | |
|
42b79c20f2 | |
|
34788522ff | |
|
2b6b6eb112 | |
|
5927873c43 | |
|
c387e186dd | |
|
5e1b3bf7a3 | |
|
f4b3a1168b | |
|
ba34d06f00 | |
|
ec98e4e130 | |
|
3f9a005923 | |
|
4b014f57ab | |
|
ceb5b2dc06 | |
|
fde86f9a0c | |
|
5508e24bfd | |
|
12581efe74 | |
|
e374a143c6 | |
|
4fa58ceeb0 | |
|
118f8c97c1 | |
|
c76f8a57e3 | |
|
d83ac63cd6 | |
|
e3d17fd452 | |
|
b341524091 | |
|
d15f34d58c | |
|
6744251390 | |
|
0cf7fc71e3 | |
|
057ca21411 | |
|
2413df7ae4 | |
|
d6e453fd5c | |
|
d1d9f4a96f | |
|
8cc438174e | |
|
4f50abcaf9 | |
|
9b44e4a6c7 | |
|
1506df5faa | |
|
fef30c4c41 | |
|
95e07e9087 | |
|
5ec7c59578 | |
|
3b60f5377a | |
|
42b18eb9ee | |
|
bef5554ec1 | |
|
0074a5168c | |
|
297671fa71 | |
|
306174c887 | |
|
14ca502dd2 | |
|
e237d57c7c | |
|
3deb138275 | |
|
45fb191928 | |
|
36ca1de577 |
|
@ -1 +1 @@
|
||||||
* @buildpacks/distribution-maintainers
|
* @buildpacks/platform-maintainers @buildpacks/toc @edmorley
|
|
@ -1,16 +1,11 @@
|
||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: github-actions
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
labels:
|
|
||||||
- semver:patch
|
|
||||||
- type:dependency-upgrade
|
|
||||||
- package-ecosystem: gomod
|
- package-ecosystem: gomod
|
||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
|
ignore:
|
||||||
|
- dependency-name: github.com/onsi/gomega
|
||||||
labels:
|
labels:
|
||||||
- semver:patch
|
- semver:patch
|
||||||
- type:dependency-upgrade
|
- type:dependency-upgrade
|
||||||
|
|
|
@ -25,3 +25,18 @@
|
||||||
- name: type:task
|
- name: type:task
|
||||||
description: A general task
|
description: A general task
|
||||||
color: e3d9fc
|
color: e3d9fc
|
||||||
|
- name: type:informational
|
||||||
|
description: Provides information or notice to the community
|
||||||
|
color: e3d9fc
|
||||||
|
- name: type:poll
|
||||||
|
description: Request for feedback from the community
|
||||||
|
color: e3d9fc
|
||||||
|
- name: note:ideal-for-contribution
|
||||||
|
description: An issue that a contributor can help us with
|
||||||
|
color: 54f7a8
|
||||||
|
- name: note:on-hold
|
||||||
|
description: We can't start working on this issue yet
|
||||||
|
color: 54f7a8
|
||||||
|
- name: note:good-first-issue
|
||||||
|
description: A good first issue to get started with
|
||||||
|
color: 54f7a8
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
github:
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
token: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
codeowners:
|
||||||
|
- path: "*"
|
||||||
|
owner: "@buildpacks/platform-maintainers @buildpacks/toc"
|
|
@ -0,0 +1 @@
|
||||||
|
1.41.2
|
|
@ -0,0 +1,76 @@
|
||||||
|
name: Action buildpack-compute-metadata
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- buildpack/compute-metadata/**
|
||||||
|
- internal/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- buildpack/compute-metadata/**
|
||||||
|
- internal/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: buildpack/compute-metadata/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/buildpack/compute-metadata
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,76 @@
|
||||||
|
name: Action buildpackage-verify-metadata
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- buildpackage/verify-metadata/**
|
||||||
|
- internal/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- buildpackage/verify-metadata/**
|
||||||
|
- internal/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: buildpackage/verify-metadata/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/buildpackage/verify-metadata
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,78 @@
|
||||||
|
name: Action registry-add-entry
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/add-entry/**
|
||||||
|
- registry/internal/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/add-entry/**
|
||||||
|
- registry/internal/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: registry/add-entry/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/registry/add-entry
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,78 @@
|
||||||
|
name: Action registry-compute-metadata
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/compute-metadata/**
|
||||||
|
- registry/internal/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/compute-metadata/**
|
||||||
|
- registry/internal/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: registry/compute-metadata/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/registry/compute-metadata
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,14 @@
|
||||||
|
name: Creating the PR to update the version of buildpacks/github-actions on buildpacks/registry-index
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
jobs:
|
||||||
|
myEvent:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Repository Dispatch
|
||||||
|
uses: peter-evans/repository-dispatch@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.DISTRIBUTION_GITHUB_TOKEN }}
|
||||||
|
repository: buildpacks/registry-index
|
||||||
|
event-type: release-event
|
|
@ -0,0 +1,78 @@
|
||||||
|
name: Action registry-request-add-entry
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/internal/**
|
||||||
|
- registry/request-add-entry/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/internal/**
|
||||||
|
- registry/request-add-entry/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: registry/request-add-entry/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/registry/request-add-entry
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,78 @@
|
||||||
|
name: Action registry-request-yank-entry
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/internal/**
|
||||||
|
- registry/request-yank-entry/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/internal/**
|
||||||
|
- registry/request-yank-entry/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: registry/request-yank-entry/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/registry/request-yank-entry
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,78 @@
|
||||||
|
name: Action registry-verify-namespace-owner
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/internal/**
|
||||||
|
- registry/verify-namespace-owner/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/internal/**
|
||||||
|
- registry/verify-namespace-owner/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: registry/verify-namespace-owner/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/registry/verify-namespace-owner
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -0,0 +1,78 @@
|
||||||
|
name: Action registry-yank-entry
|
||||||
|
"on":
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/yank-entry/**
|
||||||
|
- registry/internal/**
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- test
|
||||||
|
paths:
|
||||||
|
- internal/**
|
||||||
|
- registry/yank-entry/**
|
||||||
|
- registry/internal/**
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
jobs:
|
||||||
|
create-action:
|
||||||
|
name: Create Action
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
||||||
|
name: Docker login ghcr.io
|
||||||
|
uses: docker/login-action@v3.0.0
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}
|
||||||
|
- uses: actions/checkout@v2.3.4
|
||||||
|
- id: version
|
||||||
|
name: Compute Version
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
||||||
|
VERSION=${BASH_REMATCH[1]}
|
||||||
|
else
|
||||||
|
VERSION=$(git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "Selected ${VERSION} from
|
||||||
|
* ref: ${GITHUB_REF}
|
||||||
|
* sha: ${GITHUB_SHA}
|
||||||
|
"
|
||||||
|
- name: Create Action
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "::group::Building ${TARGET}:${VERSION}"
|
||||||
|
docker build \
|
||||||
|
--file Dockerfile \
|
||||||
|
--build-arg "SOURCE=${SOURCE}" \
|
||||||
|
--tag "${TARGET}:${VERSION}" \
|
||||||
|
.
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ "${PUSH}" == "true" ]]; then
|
||||||
|
echo "::group::Pushing ${TARGET}:${VERSION}"
|
||||||
|
docker push "${TARGET}:${VERSION}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
else
|
||||||
|
echo "Skipping push"
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
PUSH: ${{ github.event_name != 'pull_request' }}
|
||||||
|
SOURCE: registry/yank-entry/cmd
|
||||||
|
TARGET: ghcr.io/buildpacks/actions/registry/yank-entry
|
||||||
|
VERSION: ${{ steps.version.outputs.version }}
|
|
@ -1,73 +0,0 @@
|
||||||
name: Create Action registry
|
|
||||||
"on":
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- registry/**
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- registry/**
|
|
||||||
release:
|
|
||||||
types:
|
|
||||||
- published
|
|
||||||
jobs:
|
|
||||||
create-action:
|
|
||||||
name: Create Action
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- if: ${{ github.event_name != 'pull_request' || ! github.event.pull_request.head.repo.fork }}
|
|
||||||
name: Docker login ghcr.io
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
password: ${{ secrets.IMPLEMENTATION_GHCR_TOKEN }}
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ secrets.IMPLEMENTATION_GHCR_USERNAME }}
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- id: version
|
|
||||||
name: Compute Version
|
|
||||||
run: |
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [[ ${GITHUB_REF} =~ refs/tags/v([0-9]+\.[0-9]+\.[0-9]+) ]]; then
|
|
||||||
VERSION=${BASH_REMATCH[1]}
|
|
||||||
elif [[ ${GITHUB_REF} =~ refs/heads/(.+) ]]; then
|
|
||||||
VERSION=${BASH_REMATCH[1]}
|
|
||||||
else
|
|
||||||
VERSION=$(git rev-parse --short HEAD)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "::set-output name=version::${VERSION}"
|
|
||||||
echo "Selected ${VERSION} from
|
|
||||||
* ref: ${GITHUB_REF}
|
|
||||||
* sha: ${GITHUB_SHA}
|
|
||||||
"
|
|
||||||
- name: Create Action
|
|
||||||
run: |
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "::group::Building ${TARGET}:${VERSION}"
|
|
||||||
docker build \
|
|
||||||
--file Dockerfile \
|
|
||||||
--build-arg "SOURCE=${SOURCE}" \
|
|
||||||
--tag "${TARGET}:${VERSION}" \
|
|
||||||
.
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
if [[ "${PUSH}" == "true" ]]; then
|
|
||||||
echo "::group::Pushing ${TARGET}:${VERSION}"
|
|
||||||
docker push "${TARGET}:${VERSION}"
|
|
||||||
echo "::endgroup::"
|
|
||||||
else
|
|
||||||
echo "Skipping push"
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
PUSH: ${{ github.event_name != 'pull_request' }}
|
|
||||||
SOURCE: registry/cmd
|
|
||||||
TARGET: ghcr.io/buildpacks/actions/registry
|
|
||||||
VERSION: ${{ steps.version.outputs.version }}
|
|
|
@ -12,7 +12,7 @@ jobs:
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: mheap/github-action-required-labels@v1
|
- uses: mheap/github-action-required-labels@v5
|
||||||
with:
|
with:
|
||||||
count: 1
|
count: 1
|
||||||
labels: semver:major, semver:minor, semver:patch
|
labels: semver:major, semver:minor, semver:patch
|
||||||
|
@ -22,7 +22,7 @@ jobs:
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: mheap/github-action-required-labels@v1
|
- uses: mheap/github-action-required-labels@v5
|
||||||
with:
|
with:
|
||||||
count: 1
|
count: 1
|
||||||
labels: type:bug, type:dependency-upgrade, type:documentation, type:enhancement, type:question, type:task
|
labels: type:bug, type:dependency-upgrade, type:documentation, type:enhancement, type:question, type:task
|
|
@ -11,7 +11,7 @@ jobs:
|
||||||
runs-on:
|
runs-on:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: micnncim/action-label-syncer@v1
|
- uses: micnncim/action-label-syncer@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
|
@ -0,0 +1,54 @@
|
||||||
|
name: Tests
|
||||||
|
"on":
|
||||||
|
merge_group:
|
||||||
|
types:
|
||||||
|
- checks_requested
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request: {}
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
unit:
|
||||||
|
name: Unit Test
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
path: ${{ env.HOME }}/go/pkg/mod
|
||||||
|
restore-keys: ${{ runner.os }}-go-
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.24"
|
||||||
|
- name: Install richgo
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "Installing richgo ${RICHGO_VERSION}"
|
||||||
|
|
||||||
|
mkdir -p "${HOME}"/bin
|
||||||
|
echo "${HOME}/bin" >> "${GITHUB_PATH}"
|
||||||
|
|
||||||
|
curl \
|
||||||
|
--location \
|
||||||
|
--show-error \
|
||||||
|
--silent \
|
||||||
|
"https://github.com/kyoh86/richgo/releases/download/v${RICHGO_VERSION}/richgo_${RICHGO_VERSION}_linux_amd64.tar.gz" \
|
||||||
|
| tar -C "${HOME}"/bin -xz richgo
|
||||||
|
env:
|
||||||
|
RICHGO_VERSION: 0.3.10
|
||||||
|
- name: Run Tests
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
richgo test ./...
|
||||||
|
env:
|
||||||
|
RICHGO_FORCE_COLOR: "1"
|
|
@ -12,4 +12,4 @@ jobs:
|
||||||
- id: release-drafter
|
- id: release-drafter
|
||||||
uses: release-drafter/release-drafter@v5
|
uses: release-drafter/release-drafter@v5
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
|
@ -0,0 +1,72 @@
|
||||||
|
name: Update Go
|
||||||
|
"on":
|
||||||
|
schedule:
|
||||||
|
- cron: 26 2 * * 1
|
||||||
|
workflow_dispatch: {}
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
name: Update Go
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.24"
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Update Go Version & Modules
|
||||||
|
id: update-go
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -z "${GO_VERSION:-}" ]; then
|
||||||
|
echo "No go version set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OLD_GO_VERSION=$(grep -P '^go \d\.\d+' go.mod | cut -d ' ' -f 2 | cut -d '.' -f 1-2)
|
||||||
|
|
||||||
|
go mod edit -go="$GO_VERSION"
|
||||||
|
go mod tidy
|
||||||
|
go get -u -t ./...
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
git add go.mod go.sum
|
||||||
|
git checkout -- .
|
||||||
|
|
||||||
|
if [ "$OLD_GO_VERSION" == "$GO_VERSION" ]; then
|
||||||
|
COMMIT_TITLE="Bump Go Modules"
|
||||||
|
COMMIT_BODY="Bumps Go modules used by the project. See the commit for details on what modules were updated."
|
||||||
|
COMMIT_SEMVER="semver:patch"
|
||||||
|
else
|
||||||
|
COMMIT_TITLE="Bump Go from ${OLD_GO_VERSION} to ${GO_VERSION}"
|
||||||
|
COMMIT_BODY="Bumps Go from ${OLD_GO_VERSION} to ${GO_VERSION} and update Go modules used by the project. See the commit for details on what modules were updated."
|
||||||
|
COMMIT_SEMVER="semver:minor"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "commit-title=${COMMIT_TITLE}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "commit-body=${COMMIT_BODY}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "commit-semver=${COMMIT_SEMVER}" >> "$GITHUB_OUTPUT"
|
||||||
|
env:
|
||||||
|
GO_VERSION: "1.24"
|
||||||
|
- uses: peter-evans/create-pull-request@v6
|
||||||
|
with:
|
||||||
|
author: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }} <${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}@users.noreply.github.com>
|
||||||
|
body: |-
|
||||||
|
${{ steps.update-go.outputs.commit-body }}
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Release Notes</summary>
|
||||||
|
${{ steps.pipeline.outputs.release-notes }}
|
||||||
|
</details>
|
||||||
|
branch: update/go
|
||||||
|
commit-message: |-
|
||||||
|
${{ steps.update-go.outputs.commit-title }}
|
||||||
|
|
||||||
|
${{ steps.update-go.outputs.commit-body }}
|
||||||
|
delete-branch: true
|
||||||
|
labels: ${{ steps.update-go.outputs.commit-semver }}, type:task
|
||||||
|
signoff: true
|
||||||
|
title: ${{ steps.update-go.outputs.commit-title }}
|
||||||
|
token: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
|
@ -0,0 +1,93 @@
|
||||||
|
name: Update Pipeline
|
||||||
|
"on":
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- .github/pipeline-descriptor.yml
|
||||||
|
schedule:
|
||||||
|
- cron: 0 5 * * 1-5
|
||||||
|
workflow_dispatch: {}
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
name: Update Pipeline
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: "1.24"
|
||||||
|
- name: Install octo
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
go install -ldflags="-s -w" github.com/paketo-buildpacks/pipeline-builder/cmd/octo@latest
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Update Pipeline
|
||||||
|
id: pipeline
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ -f .github/pipeline-version ]]; then
|
||||||
|
OLD_VERSION=$(cat .github/pipeline-version)
|
||||||
|
else
|
||||||
|
OLD_VERSION="0.0.0"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm .github/workflows/pb-*.yml || true
|
||||||
|
octo --descriptor "${DESCRIPTOR}"
|
||||||
|
|
||||||
|
PAYLOAD=$(gh api /repos/paketo-buildpacks/pipeline-builder/releases/latest)
|
||||||
|
|
||||||
|
NEW_VERSION=$(jq -n -r --argjson PAYLOAD "${PAYLOAD}" '$PAYLOAD.name')
|
||||||
|
echo "${NEW_VERSION}" > .github/pipeline-version
|
||||||
|
|
||||||
|
RELEASE_NOTES=$(
|
||||||
|
gh api \
|
||||||
|
-F text="$(jq -n -r --argjson PAYLOAD "${PAYLOAD}" '$PAYLOAD.body')" \
|
||||||
|
-F mode="gfm" \
|
||||||
|
-F context="paketo-buildpacks/pipeline-builder" \
|
||||||
|
-X POST /markdown
|
||||||
|
)
|
||||||
|
|
||||||
|
git add .github/
|
||||||
|
git add .gitignore
|
||||||
|
|
||||||
|
if [ -f scripts/build.sh ]; then
|
||||||
|
git add scripts/build.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
git checkout -- .
|
||||||
|
|
||||||
|
echo "old-version=${OLD_VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "new-version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
DELIMITER=$(openssl rand -hex 16) # roughly the same entropy as uuid v4 used in https://github.com/actions/toolkit/blob/b36e70495fbee083eb20f600eafa9091d832577d/packages/core/src/file-command.ts#L28
|
||||||
|
printf "release-notes<<%s\n%s\n%s\n" "${DELIMITER}" "${RELEASE_NOTES}" "${DELIMITER}" >> "${GITHUB_OUTPUT}" # see https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
|
||||||
|
env:
|
||||||
|
DESCRIPTOR: .github/pipeline-descriptor.yml
|
||||||
|
GITHUB_TOKEN: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
||||||
|
- uses: peter-evans/create-pull-request@v6
|
||||||
|
with:
|
||||||
|
author: ${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }} <${{ secrets.IMPLEMENTATION_GITHUB_USERNAME }}@users.noreply.github.com>
|
||||||
|
body: |-
|
||||||
|
Bumps pipeline from `${{ steps.pipeline.outputs.old-version }}` to `${{ steps.pipeline.outputs.new-version }}`.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Release Notes</summary>
|
||||||
|
${{ steps.pipeline.outputs.release-notes }}
|
||||||
|
</details>
|
||||||
|
branch: update/pipeline
|
||||||
|
commit-message: |-
|
||||||
|
Bump pipeline from ${{ steps.pipeline.outputs.old-version }} to ${{ steps.pipeline.outputs.new-version }}
|
||||||
|
|
||||||
|
Bumps pipeline from ${{ steps.pipeline.outputs.old-version }} to ${{ steps.pipeline.outputs.new-version }}.
|
||||||
|
delete-branch: true
|
||||||
|
labels: semver:patch, type:task
|
||||||
|
signoff: true
|
||||||
|
title: Bump pipeline from ${{ steps.pipeline.outputs.old-version }} to ${{ steps.pipeline.outputs.new-version }}
|
||||||
|
token: ${{ secrets.IMPLEMENTATION_GITHUB_TOKEN }}
|
|
@ -1,37 +0,0 @@
|
||||||
name: Tests
|
|
||||||
"on":
|
|
||||||
pull_request: {}
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
jobs:
|
|
||||||
unit:
|
|
||||||
name: Unit Test
|
|
||||||
runs-on:
|
|
||||||
- ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
path: ${{ env.HOME }}/go/pkg/mod
|
|
||||||
restore-keys: ${{ runner.os }}-go-
|
|
||||||
- uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: "1.15"
|
|
||||||
- name: Install richgo
|
|
||||||
run: |
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
GO111MODULE=on go get -u -ldflags="-s -w" github.com/kyoh86/richgo
|
|
||||||
- name: Run Tests
|
|
||||||
run: |
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
richgo test ./...
|
|
||||||
env:
|
|
||||||
RICHGO_FORCE_COLOR: "1"
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
name: update-pack-version
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
repository_dispatch:
|
||||||
|
types:
|
||||||
|
- pack-release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-pack-version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Retrieve latest pack version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
NEW_VERSION=$(curl -s -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/buildpacks/pack/releases/latest | jq .tag_name -r | cut -c 2-)
|
||||||
|
echo "new_version=${NEW_VERSION}" >> ${GITHUB_OUTPUT}
|
||||||
|
- name: Update setup-pack/action.yml with the new Pack version
|
||||||
|
run: |
|
||||||
|
sed -i -z "s/default: '[0-9]\{1,\}.[0-9]\{1,\}.[0-9]\{1,\}'/default: '${{ steps.version.outputs.new_version }}'/" setup-pack/action.yml
|
||||||
|
- name: Create pull request
|
||||||
|
uses: peter-evans/create-pull-request@v5
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.DISTRIBUTION_GITHUB_TOKEN }}
|
||||||
|
commit-message: Update default Pack version to v${{ steps.version.outputs.new_version }}
|
||||||
|
title: Update default Pack version to v${{ steps.version.outputs.new_version }}
|
||||||
|
body: |
|
||||||
|
Updates the `setup-pack` action's default `pack-version` to the latest Pack release.
|
||||||
|
|
||||||
|
Release notes:
|
||||||
|
https://github.com/buildpacks/pack/releases/tag/v${{ steps.version.outputs.new_version }}
|
||||||
|
labels: |
|
||||||
|
semver:patch
|
||||||
|
type:dependency-upgrade
|
||||||
|
branch: update-version
|
||||||
|
base: main
|
||||||
|
signoff: true
|
|
@ -11,3 +11,10 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
bin/
|
||||||
|
linux/
|
||||||
|
dependencies/
|
||||||
|
package/
|
||||||
|
scratch/
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
FROM golang:1.15 as build-stage
|
FROM golang:1.24 as build-stage
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends upx
|
|
||||||
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
ENV GO111MODULE=on CGO_ENABLED=0
|
ENV GO111MODULE=on CGO_ENABLED=0
|
||||||
|
@ -17,9 +15,8 @@ RUN go build \
|
||||||
|
|
||||||
RUN strip /bin/action
|
RUN strip /bin/action
|
||||||
|
|
||||||
RUN upx -q -9 /bin/action
|
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
|
LABEL org.opencontainers.image.source=https://github.com/buildpacks/github-actions
|
||||||
COPY --from=build-stage /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
COPY --from=build-stage /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||||
COPY --from=build-stage /bin/action /bin/action
|
COPY --from=build-stage /bin/action /bin/action
|
||||||
ENTRYPOINT ["/bin/action"]
|
ENTRYPOINT ["/bin/action"]
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -187,7 +187,7 @@
|
||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
Copyright 2020 The Cloud Native Buildpacks Authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|
209
README.md
209
README.md
|
@ -1,23 +1,134 @@
|
||||||
# GitHub Actions
|
# GitHub Actions
|
||||||
|
|
||||||
|
[](https://bestpractices.coreinfrastructure.org/projects/4748)
|
||||||
|
|
||||||
`github-actions` is a collection of end-user [GitHub Actions][gha] that integrate with Cloud Native Buildpacks projects.
|
`github-actions` is a collection of end-user [GitHub Actions][gha] that integrate with Cloud Native Buildpacks projects.
|
||||||
|
|
||||||
[gha]: https://docs.github.com/en/free-pro-team@latest/actions
|
[gha]: https://docs.github.com/en/free-pro-team@latest/actions
|
||||||
|
|
||||||
## Registry Action
|
- [GitHub Actions](#github-actions)
|
||||||
The registry action adds and yanks buildpack releases in the [Buildpack Registry Index][bri].
|
- [Buildpack](#buildpack)
|
||||||
|
- [Compute Metadata Action](#compute-metadata-action)
|
||||||
|
- [Buildpackage](#buildpackage)
|
||||||
|
- [Verify Metadata Action](#verify-metadata-action)
|
||||||
|
- [Registry](#registry)
|
||||||
|
- [Add Entry Action](#add-entry-action)
|
||||||
|
- [Compute Registry Metadata Action](#compute-registry-metadata-action)
|
||||||
|
- [Request Add Entry Action](#request-add-entry-action)
|
||||||
|
- [Request Yank Entry Action](#request-yank-entry-action)
|
||||||
|
- [Verify Namespace Owner Action](#verify-namespace-owner-action)
|
||||||
|
- [Yank Entry Action](#yank-entry-action)
|
||||||
|
- [Setup pack CLI Action](#setup-pack-cli-action)
|
||||||
|
- [Setup Tools Action](#setup-tools-action)
|
||||||
|
- [License](#license)
|
||||||
|
|
||||||
|
## Buildpack
|
||||||
|
|
||||||
|
### Compute Metadata Action
|
||||||
|
The `buildpack/compute-metadata` action parses a `buildpack.toml` and exposes the contents of the `[buildpack]` block as output parameters.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker://ghcr.io/buildpacks/actions/buildpack/compute-metadata
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `path` | Optional path to `buildpack.toml`. Defaults to `<working-dir>/buildpack.toml`
|
||||||
|
|
||||||
|
#### Outputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `id` | The contents of `buildpack.id`
|
||||||
|
| `name` | The contents of `buildpack.name`
|
||||||
|
| `version` | The contents of `buildpack.version`
|
||||||
|
| `homepage` | The contents of `buildpack.homepage`
|
||||||
|
|
||||||
|
## Buildpackage
|
||||||
|
|
||||||
|
### Verify Metadata Action
|
||||||
|
The `buildpackage/verify-metadata` action parses the metadata on a buildpackage and verifies that the `id` and `version` match expected values.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker://ghcr.io/buildpacks/actions/buildpackage/verify-metadata
|
||||||
|
with:
|
||||||
|
id: test-buildpack
|
||||||
|
version: "1.0.0"
|
||||||
|
address: ghcr.io/example/test-buildpack@sha256:04ba2d17480910bd340f0305d846b007148dafd64bc6fc2626870c174b7c7de7
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `id` | The expected `id` for the buildpackage
|
||||||
|
| `version` | The expected `version` for the buildpackage
|
||||||
|
| `address` | The digest-style address of the buildpackage to verify
|
||||||
|
|
||||||
|
## Registry
|
||||||
[bri]: https://github.com/buildpacks/registry-index
|
[bri]: https://github.com/buildpacks/registry-index
|
||||||
|
|
||||||
### Add
|
### Add Entry Action
|
||||||
|
The `registry/add-entry` adds an entry to the [Buildpack Registry Index][bri].
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: docker://ghcr.io/buildpacks/actions/registry
|
uses: docker://ghcr.io/buildpacks/actions/registry/add-entry
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN }}
|
||||||
|
owner: ${{ env.INDEX_OWNER }}
|
||||||
|
repository: ${{ env.INDEX_REPOSITORY }}
|
||||||
|
namespace: ${{ steps.metadata.outputs.namespace }}
|
||||||
|
name: ${{ steps.metadata.outputs.name }}
|
||||||
|
version: ${{ steps.metadata.outputs.version }}
|
||||||
|
address: ${{ steps.metadata.outputs.address }}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `token` | A GitHub token with permissions to commit to the registry index repository.
|
||||||
|
| `owner` | The owner name of the registry index repository.
|
||||||
|
| `repository` | The repository name of the registry index repository.
|
||||||
|
| `namespace` | The namespace of the buildpack to register.
|
||||||
|
| `name` | The name of the buildpack to register.
|
||||||
|
| `version` | The version of the buildpack to register.
|
||||||
|
| `address` | The address of the buildpack to register.
|
||||||
|
|
||||||
|
### Compute Registry Metadata Action
|
||||||
|
The `registry/compute-metadata` action parses a [`buildpacks/registry-index`][bri] issue and exposes the contents as output parameters.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker://ghcr.io/buildpacks/actions/registry/compute-metadata
|
||||||
|
with:
|
||||||
|
issue: ${{ toJSON(github.events.issue) }}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `issue` | The GitHub issue payload.
|
||||||
|
|
||||||
|
#### Outputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `id` | The contents of `id`
|
||||||
|
| `version` | The contents of `version`
|
||||||
|
| `address` | The contents of `addr`
|
||||||
|
| `namespace` | The namespace portion of `id`
|
||||||
|
| `name` | The name portion of `id`
|
||||||
|
|
||||||
|
### Request Add Entry Action
|
||||||
|
The `registry/request-add-entry` action adds an entry to the [Buildpack Registry Index][bri].
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker://ghcr.io/buildpacks/actions/registry/request-add-entry
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.IMPLEMENTATION_PAT }}
|
token: ${{ secrets.IMPLEMENTATION_PAT }}
|
||||||
id: $buildpacksio/test-buildpack
|
id: $buildpacksio/test-buildpack
|
||||||
version: {{ steps.deploy.outputs.version }}
|
version: ${{ steps.deploy.outputs.version }}
|
||||||
address: index.docker.io/buildpacksio/test-buildpack@${{ steps.deploy.outputs.digest }}
|
address: index.docker.io/buildpacksio/test-buildpack@${{ steps.deploy.outputs.digest }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
| Parameter | Description
|
| Parameter | Description
|
||||||
| :-------- | :----------
|
| :-------- | :----------
|
||||||
| `token` | A GitHub token with `public_repo` scope to open an issue against [`buildpacks/registry-index`][bri].
|
| `token` | A GitHub token with `public_repo` scope to open an issue against [`buildpacks/registry-index`][bri].
|
||||||
|
@ -25,25 +136,103 @@ with:
|
||||||
| `version` | The version of the buildpack that is being added to the registry.
|
| `version` | The version of the buildpack that is being added to the registry.
|
||||||
| `address` | The Docker URI of the buildpack artifact. This is must be in `{host}/{repo}@{digest}` form.
|
| `address` | The Docker URI of the buildpack artifact. This is must be in `{host}/{repo}@{digest}` form.
|
||||||
|
|
||||||
### Yank
|
### Request Yank Entry Action
|
||||||
|
The `registry/request-yank-entry` action yanks an entry from the [Buildpack Registry Index][bri].
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
uses: docker://ghcr.io/buildpacks/actions/registry
|
uses: docker://ghcr.io/buildpacks/actions/registry/request-yank-entry
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.IMPLEMENTATION_PAT }}
|
token: ${{ secrets.IMPLEMENTATION_PAT }}
|
||||||
id: buildpacksio/test-buildpack
|
id: buildpacksio/test-buildpack
|
||||||
version: ${{ steps.deploy.outputs.version }}
|
version: ${{ steps.deploy.outputs.version }}
|
||||||
yank: true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
| Parameter | Description
|
| Parameter | Description
|
||||||
| :-------- | :----------
|
| :-------- | :----------
|
||||||
| `token` | A GitHub token with `public_repo` scope to open an issue against [`buildpacks/registry-index`][bri].
|
| `token` | A GitHub token with `public_repo` scope to open an issue against [`buildpacks/registry-index`][bri].
|
||||||
| `id` | A buildpack id that your user is allowed to manage. This is must be in `{namespace}/{name}` format.
|
| `id` | A buildpack id that your user is allowed to manage. This is must be in `{namespace}/{name}` format.
|
||||||
| `version` | The version of the buildpack that is being added to the registry.
|
| `version` | The version of the buildpack that is being added to the registry.
|
||||||
| `yank` | `true` if this version should be yanked.
|
|
||||||
|
### Verify Namespace Owner Action
|
||||||
|
The `registry/verify-namespace-owner` action verifies that a user is an owner of a namespace in the [Buildpack Registry Index][bri].
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker://ghcr.io/buildpacks/actions/registry/verify-namespace-owner
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN }}
|
||||||
|
owner: ${{ env.NAMESPACES_OWNER }}
|
||||||
|
repository: ${{ env.NAMESPACES_REPOSITORY }}
|
||||||
|
namespace: ${{ steps.metadata.outputs.namespace }}
|
||||||
|
user: ${{ toJSON(github.event.issue.user) }}
|
||||||
|
add-if-missing: true
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `token` | A GitHub token with permissions to commit to the registry namespaces repository.
|
||||||
|
| `owner` | The owner name of the registry namespaces repository.
|
||||||
|
| `repository` | The repository name of the registry namespaces repository.
|
||||||
|
| `namespace` | The namespace to check ownership for.
|
||||||
|
| `user` | The Github user payload.
|
||||||
|
| `add-if-missing` | Whether to add the current user as the owner of the namespace if that namespace does not exist. (Optional. Default `false`)
|
||||||
|
|
||||||
|
### Yank Entry Action
|
||||||
|
The `registry/yank-entry` action yanks an entry from the [Buildpack Registry Index][bri].
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker://ghcr.io/buildpacks/actions/registry/yank-entry
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.BOT_TOKEN }}
|
||||||
|
owner: ${{ env.INDEX_OWNER }}
|
||||||
|
repository: ${{ env.INDEX_REPOSITORY }}
|
||||||
|
namespace: ${{ steps.metadata.outputs.namespace }}
|
||||||
|
name: ${{ steps.metadata.outputs.name }}
|
||||||
|
version: ${{ steps.metadata.outputs.version }}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `token` | A GitHub token with permissions to commit to the registry index repository.
|
||||||
|
| `owner` | The owner name of the registry index repository.
|
||||||
|
| `repository` | The repository name of the registry index repository.
|
||||||
|
| `namespace` | The namespace of the buildpack to register.
|
||||||
|
| `name` | The name of the buildpack to register.
|
||||||
|
| `version` | The version of the buildpack to register.
|
||||||
|
|
||||||
|
## Setup pack CLI Action
|
||||||
|
The `setup-pack` action adds [`pack`][pack] to the environment.
|
||||||
|
|
||||||
|
[pack]: https://github.com/buildpacks/pack
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: buildpacks/github-actions/setup-pack@v5.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `pack-version` | Optional version of [`pack`][pack] to install. Defaults to latest release.
|
||||||
|
|
||||||
|
## Setup Tools Action
|
||||||
|
The `setup-tools` action adds [crane][crane] and [`yj`][yj] to the environment.
|
||||||
|
|
||||||
|
[crane]: https://github.com/google/go-containerregistry/tree/master/cmd/crane
|
||||||
|
[yj]: https://github.com/sclevine/yj
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: buildpacks/github-actions/setup-tools@v5.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inputs <!-- omit in toc -->
|
||||||
|
| Parameter | Description
|
||||||
|
| :-------- | :----------
|
||||||
|
| `crane-version` | Optional version of [`crane`][crane] to install. Defaults to `0.12.1`.
|
||||||
|
| `yj-version` | Optional version of [`yj`][yj] to install. Defaults to `5.1.0`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
This library is released under version 2.0 of the [Apache License][a].
|
This library is released under version 2.0 of the [Apache License][a].
|
||||||
|
|
||||||
[a]: https://www.apache.org/licenses/LICENSE-2.0
|
[a]: https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/buildpack/compute-metadata"
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := metadata.ComputeMetadata(&toolkit.DefaultToolkit{}); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/buildpacks/libcnb"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ComputeMetadata(tk toolkit.Toolkit) error {
|
||||||
|
c := parseConfig(tk)
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(c.Path)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to read %s", c.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
var bp libcnb.Buildpack
|
||||||
|
if err := toml.Unmarshal(b, &bp); err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal %s", c.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(`Metadata:
|
||||||
|
ID: %s
|
||||||
|
Name: %s
|
||||||
|
Version: %s
|
||||||
|
Homepage: %s
|
||||||
|
`, bp.Info.ID, bp.Info.Name, bp.Info.Version, bp.Info.Homepage)
|
||||||
|
|
||||||
|
tk.SetOutput("id", bp.Info.ID)
|
||||||
|
tk.SetOutput("name", bp.Info.Name)
|
||||||
|
tk.SetOutput("version", bp.Info.Version)
|
||||||
|
tk.SetOutput("homepage", bp.Info.Homepage)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) config {
|
||||||
|
c := config{Path: "buildpack.toml"}
|
||||||
|
|
||||||
|
if s, ok := tk.GetInput("path"); ok {
|
||||||
|
c.Path = s
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/buildpack/compute-metadata"
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestComputeMetadata(t *testing.T) {
|
||||||
|
spec.Run(t, "compute-metadata", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "path").Return(filepath.Join("testdata", "buildpack.toml"), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("computes metadata", func() {
|
||||||
|
tk.On("SetOutput", "id", "test-id")
|
||||||
|
tk.On("SetOutput", "name", "test-name")
|
||||||
|
tk.On("SetOutput", "version", "test-version")
|
||||||
|
tk.On("SetOutput", "homepage", "test-homepage")
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(Succeed())
|
||||||
|
})
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Copyright 2018-2020 the original author or 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
|
||||||
|
#
|
||||||
|
# https://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.
|
||||||
|
|
||||||
|
[buildpack]
|
||||||
|
id = "test-id"
|
||||||
|
name = "test-name"
|
||||||
|
version = "test-version"
|
||||||
|
homepage = "test-homepage"
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/buildpackage/verify-metadata"
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := metadata.VerifyMetadata(&toolkit.DefaultToolkit{}, remote.Image); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate mockery --all --output=./internal/mocks --case=underscore
|
||||||
|
|
||||||
|
type ImageFunction func(name.Reference, ...remote.Option) (v1.Image, error)
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Code generated by mockery v2.4.0-beta. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
name "github.com/google/go-containerregistry/pkg/name"
|
||||||
|
remote "github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ImageFunction is an autogenerated mock type for the ImageFunction type
|
||||||
|
type ImageFunction struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *ImageFunction) Execute(_a0 name.Reference, _a1 ...remote.Option) (v1.Image, error) {
|
||||||
|
_va := make([]interface{}, len(_a1))
|
||||||
|
for _i := range _a1 {
|
||||||
|
_va[_i] = _a1[_i]
|
||||||
|
}
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, _a0)
|
||||||
|
_ca = append(_ca, _va...)
|
||||||
|
ret := _m.Called(_ca...)
|
||||||
|
|
||||||
|
var r0 v1.Image
|
||||||
|
if rf, ok := ret.Get(0).(func(name.Reference, ...remote.Option) v1.Image); ok {
|
||||||
|
r0 = rf(_a0, _a1...)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(v1.Image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(name.Reference, ...remote.Option) error); ok {
|
||||||
|
r1 = rf(_a0, _a1...)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
const MetadataLabel = "io.buildpacks.buildpackage.metadata"
|
||||||
|
|
||||||
|
func VerifyMetadata(tk toolkit.Toolkit, imageFn ImageFunction) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, err := name.ParseReference(c.Address)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to parse address %s as image reference", c.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ref.(name.Digest); !ok {
|
||||||
|
return toolkit.FailedErrorf("address %s must be in digest form <host>/<repository>@sh256:<digest>", c.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
image, err := imageFn(ref)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to retrieve image %s", c.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
configFile, err := image.ConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to retrieve config file\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, ok := configFile.Config.Labels[MetadataLabel]
|
||||||
|
if !ok {
|
||||||
|
return toolkit.FailedErrorf("unable to retrieve %s label", MetadataLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
var m metadata
|
||||||
|
if err := json.Unmarshal([]byte(raw), &m); err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal %s label", MetadataLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ID != m.ID {
|
||||||
|
return toolkit.FailedErrorf("invalid id in buildpackage: expected %s, found %s", c.ID, m.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Version != m.Version {
|
||||||
|
return toolkit.FailedErrorf("invalid version in buildpackage: expected %s, found %s", c.Version, m.Version)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var stacks []string
|
||||||
|
for _, s := range m.Stacks {
|
||||||
|
stacks = append(stacks, s.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(`Verified %s
|
||||||
|
ID: %s
|
||||||
|
Version: %s
|
||||||
|
Homepage: %s
|
||||||
|
Stacks: %s
|
||||||
|
`, c.Address, m.ID, m.Version, m.Homepage, strings.Join(stacks, ", "))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
ID string
|
||||||
|
Version string
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c config
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.ID, ok = tk.GetInput("id")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("id must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Version, ok = tk.GetInput("version")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("version must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Address, ok = tk.GetInput("address")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("address must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type metadata struct {
|
||||||
|
ID string
|
||||||
|
Version string
|
||||||
|
Homepage string
|
||||||
|
Stacks []stack
|
||||||
|
}
|
||||||
|
|
||||||
|
type stack struct {
|
||||||
|
ID string
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
|
"github.com/google/go-containerregistry/pkg/v1/fake"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/buildpackage/verify-metadata"
|
||||||
|
"github.com/buildpacks/github-actions/buildpackage/verify-metadata/internal/mocks"
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVerifyMetadata(t *testing.T) {
|
||||||
|
spec.Run(t, "verify-metadata", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
|
||||||
|
f = &mocks.ImageFunction{}
|
||||||
|
i = &fake.FakeImage{}
|
||||||
|
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "id").Return("test-id", true)
|
||||||
|
tk.On("GetInput", "version").Return("test-version", true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if address is not a digest image reference", func() {
|
||||||
|
tk.On("GetInput", "address").Return("test-host/test-repository:test-version", true)
|
||||||
|
|
||||||
|
Expect(metadata.VerifyMetadata(tk, f.Execute)).
|
||||||
|
To(MatchError("::error ::address test-host/test-repository:test-version must be in digest form <host>/<repository>@sh256:<digest>"))
|
||||||
|
})
|
||||||
|
|
||||||
|
context("valid address", func() {
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "address").Return("host/repository@sha256:04ba2d17480910bd340f0305d846b007148dafd64bc6fc2626870c174b7c7de7", true)
|
||||||
|
f.On("Execute", mock.Anything).Return(i, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if io.buildpacks.buildpackage.metadata is not on image", func() {
|
||||||
|
i.ConfigFileReturns(&v1.ConfigFile{
|
||||||
|
Config: v1.Config{
|
||||||
|
Labels: map[string]string{},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
Expect(metadata.VerifyMetadata(tk, f.Execute)).
|
||||||
|
To(MatchError("::error ::unable to retrieve io.buildpacks.buildpackage.metadata label"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if id does not match", func() {
|
||||||
|
i.ConfigFileReturns(&v1.ConfigFile{
|
||||||
|
Config: v1.Config{
|
||||||
|
Labels: map[string]string{metadata.MetadataLabel: `{ "id": "another-id", "version": "test-version" }`},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
Expect(metadata.VerifyMetadata(tk, f.Execute)).
|
||||||
|
To(MatchError("::error ::invalid id in buildpackage: expected test-id, found another-id"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if version does not match", func() {
|
||||||
|
i.ConfigFileReturns(&v1.ConfigFile{
|
||||||
|
Config: v1.Config{
|
||||||
|
Labels: map[string]string{metadata.MetadataLabel: `{ "id": "test-id", "version": "another-version" }`},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
Expect(metadata.VerifyMetadata(tk, f.Execute)).
|
||||||
|
To(MatchError("::error ::invalid version in buildpackage: expected test-version, found another-version"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("passes if version and id match", func() {
|
||||||
|
i.ConfigFileReturns(&v1.ConfigFile{
|
||||||
|
Config: v1.Config{
|
||||||
|
Labels: map[string]string{metadata.MetadataLabel: `{ "id": "test-id", "version": "test-version" }`},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
Expect(metadata.VerifyMetadata(tk, f.Execute)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
41
go.mod
41
go.mod
|
@ -1,11 +1,42 @@
|
||||||
module github.com/buildpacks/github-actions
|
module github.com/buildpacks/github-actions
|
||||||
|
|
||||||
go 1.15
|
go 1.24
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/go-github/v32 v32.1.0
|
github.com/buildpacks/libcnb v1.30.4
|
||||||
github.com/onsi/gomega v1.10.3
|
github.com/google/go-containerregistry v0.20.6
|
||||||
github.com/pelletier/go-toml v1.8.1
|
github.com/google/go-github/v39 v39.2.0
|
||||||
|
github.com/onsi/gomega v1.38.0
|
||||||
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/sclevine/spec v1.4.0
|
github.com/sclevine/spec v1.4.0
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
github.com/stretchr/testify v1.10.0
|
||||||
|
golang.org/x/oauth2 v0.30.0
|
||||||
|
gopkg.in/retry.v1 v1.0.3
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
|
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||||
|
github.com/containerd/stargz-snapshotter/estargz v0.17.0 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/docker/cli v28.3.3+incompatible // indirect
|
||||||
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
|
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||||
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
|
github.com/vbatts/tar-split v0.12.1 // indirect
|
||||||
|
golang.org/x/crypto v0.41.0 // indirect
|
||||||
|
golang.org/x/net v0.43.0 // indirect
|
||||||
|
golang.org/x/sync v0.16.0 // indirect
|
||||||
|
golang.org/x/sys v0.35.0 // indirect
|
||||||
|
golang.org/x/text v0.28.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
474
go.sum
474
go.sum
|
@ -1,408 +1,116 @@
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
github.com/buildpacks/libcnb v1.30.4 h1:Jp6cJxYsZQgqix+lpRdSpjHt5bv5yCJqgkw9zWmS6xU=
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
github.com/buildpacks/libcnb v1.30.4/go.mod h1:vjEDAlK3/Rf67AcmBzphXoqIlbdFgBNUK5d8wjreJbY=
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
github.com/containerd/stargz-snapshotter/estargz v0.17.0 h1:+TyQIsR/zSFI1Rm31EQBwpAA1ovYgIKHy7kctL3sLcE=
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
github.com/containerd/stargz-snapshotter/estargz v0.17.0/go.mod h1:s06tWAiJcXQo9/8AReBCIo/QxcXFZ2n4qfsRnpl71SM=
|
||||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
|
||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
|
||||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
|
||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
|
||||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
|
||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
|
||||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
|
||||||
github.com/aws/aws-sdk-go v1.35.17 h1:zhahppAMdPvJ9GP302SMOPW5SNoAbnjdOyaTmxA9WJU=
|
|
||||||
github.com/aws/aws-sdk-go v1.35.17/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/frankban/quicktest v1.2.2 h1:xfmOhhoH5fGPgbEAlhLpJH9p0z/0Qizio9osmvn9IUY=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/google/go-containerregistry v0.20.6 h1:cvWX87UxxLgaH76b4hIvya6Dzz9qHB31qAwjAohdSTU=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/google/go-containerregistry v0.20.6/go.mod h1:T0x8MuoAoKX/873bkeSfLD2FAkwCDf9/HZgsFJ02E2Y=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
|
||||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
|
|
||||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||||
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
|
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
|
||||||
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||||
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a h1:3QH7VyOaaiUHNrA9Se4YQIRkDTCw1EJls9xTUCaCeRM=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a/go.mod h1:4r5QyqhjIWCcK8DO4KMclc5Iknq5qVBAlbYYzAbUScQ=
|
||||||
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||||
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
|
||||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
|
|
||||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
|
||||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
|
||||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
|
||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/retry.v1 v1.0.3 h1:a9CArYczAVv6Qs6VGoLMio99GEs7kY9UzSF9+LD+iGs=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/retry.v1 v1.0.3/go.mod h1:FJkXmWiMaAo7xB+xhvDF59zhfjDWyzmyAxiT4dB688g=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
// Code generated by mockery v2.4.0-beta. DO NOT EDIT.
|
||||||
|
|
||||||
|
package toolkit
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// MockToolkit is an autogenerated mock type for the Toolkit type
|
||||||
|
type MockToolkit struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMask provides a mock function with given fields: mask
|
||||||
|
func (_m *MockToolkit) AddMask(mask string) {
|
||||||
|
_m.Called(mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPath provides a mock function with given fields: paths
|
||||||
|
func (_m *MockToolkit) AddPath(paths ...string) error {
|
||||||
|
_va := make([]interface{}, len(paths))
|
||||||
|
for _i := range paths {
|
||||||
|
_va[_i] = paths[_i]
|
||||||
|
}
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, _va...)
|
||||||
|
ret := _m.Called(_ca...)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(...string) error); ok {
|
||||||
|
r0 = rf(paths...)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug provides a mock function with given fields: a
|
||||||
|
func (_m *MockToolkit) Debug(a ...interface{}) {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, a...)
|
||||||
|
_m.Called(_ca...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf provides a mock function with given fields: format, a
|
||||||
|
func (_m *MockToolkit) Debugf(format string, a ...interface{}) {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, format)
|
||||||
|
_ca = append(_ca, a...)
|
||||||
|
_m.Called(_ca...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndGroup provides a mock function with given fields:
|
||||||
|
func (_m *MockToolkit) EndGroup() {
|
||||||
|
_m.Called()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error provides a mock function with given fields: a
|
||||||
|
func (_m *MockToolkit) Error(a ...interface{}) {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, a...)
|
||||||
|
_m.Called(_ca...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorc provides a mock function with given fields: context
|
||||||
|
func (_m *MockToolkit) Errorc(context MessageContext) {
|
||||||
|
_m.Called(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf provides a mock function with given fields: format, a
|
||||||
|
func (_m *MockToolkit) Errorf(format string, a ...interface{}) {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, format)
|
||||||
|
_ca = append(_ca, a...)
|
||||||
|
_m.Called(_ca...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportVariable provides a mock function with given fields: name, value
|
||||||
|
func (_m *MockToolkit) ExportVariable(name string, value string) error {
|
||||||
|
ret := _m.Called(name, value)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||||
|
r0 = rf(name, value)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInput provides a mock function with given fields: name
|
||||||
|
func (_m *MockToolkit) GetInput(name string) (string, bool) {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func(string) string); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 bool
|
||||||
|
if rf, ok := ret.Get(1).(func(string) bool); ok {
|
||||||
|
r1 = rf(name)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Get(1).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInputList provides a mock function with given fields: name
|
||||||
|
func (_m *MockToolkit) GetInputList(name string) ([]string, bool) {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 []string
|
||||||
|
if rf, ok := ret.Get(0).(func(string) []string); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 bool
|
||||||
|
if rf, ok := ret.Get(1).(func(string) bool); ok {
|
||||||
|
r1 = rf(name)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Get(1).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetState provides a mock function with given fields: name
|
||||||
|
func (_m *MockToolkit) GetState(name string) (string, bool) {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func(string) string); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 bool
|
||||||
|
if rf, ok := ret.Get(1).(func(string) bool); ok {
|
||||||
|
r1 = rf(name)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Get(1).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDebug provides a mock function with given fields:
|
||||||
|
func (_m *MockToolkit) IsDebug() bool {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOutput provides a mock function with given fields: name, value
|
||||||
|
func (_m *MockToolkit) SetOutput(name string, value string) {
|
||||||
|
_m.Called(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetState provides a mock function with given fields: name, value
|
||||||
|
func (_m *MockToolkit) SetState(name string, value string) {
|
||||||
|
_m.Called(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartGroup provides a mock function with given fields: title
|
||||||
|
func (_m *MockToolkit) StartGroup(title string) {
|
||||||
|
_m.Called(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning provides a mock function with given fields: a
|
||||||
|
func (_m *MockToolkit) Warning(a ...interface{}) {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, a...)
|
||||||
|
_m.Called(_ca...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warningc provides a mock function with given fields: context
|
||||||
|
func (_m *MockToolkit) Warningc(context MessageContext) {
|
||||||
|
_m.Called(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warningf provides a mock function with given fields: format, a
|
||||||
|
func (_m *MockToolkit) Warningf(format string, a ...interface{}) {
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, format)
|
||||||
|
_ca = append(_ca, a...)
|
||||||
|
_m.Called(_ca...)
|
||||||
|
}
|
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package toolkit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate mockery --all --inpackage --case=underscore
|
||||||
|
|
||||||
|
type Toolkit interface {
|
||||||
|
AddPath(paths ...string) error
|
||||||
|
ExportVariable(name string, value string) error
|
||||||
|
|
||||||
|
GetInput(name string) (string, bool)
|
||||||
|
GetInputList(name string) ([]string, bool)
|
||||||
|
SetOutput(name string, value string)
|
||||||
|
GetState(name string) (string, bool)
|
||||||
|
SetState(name string, value string)
|
||||||
|
AddMask(mask string)
|
||||||
|
|
||||||
|
StartGroup(title string)
|
||||||
|
EndGroup()
|
||||||
|
|
||||||
|
IsDebug() bool
|
||||||
|
Debug(a ...interface{})
|
||||||
|
Debugf(format string, a ...interface{})
|
||||||
|
Warning(a ...interface{})
|
||||||
|
Warningc(context MessageContext)
|
||||||
|
Warningf(format string, a ...interface{})
|
||||||
|
Error(a ...interface{})
|
||||||
|
Errorc(context MessageContext)
|
||||||
|
Errorf(format string, a ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageContext struct {
|
||||||
|
File string
|
||||||
|
Line string
|
||||||
|
Column string
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MessageContext) String() string {
|
||||||
|
var s []string
|
||||||
|
if m.File != "" {
|
||||||
|
s = append(s, fmt.Sprintf("file=%s", m.File))
|
||||||
|
}
|
||||||
|
if m.Line != "" {
|
||||||
|
s = append(s, fmt.Sprintf("line=%s", m.Line))
|
||||||
|
}
|
||||||
|
if m.Column != "" {
|
||||||
|
s = append(s, fmt.Sprintf("col=%s", m.Column))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s::%s", strings.Join(s, ","), escape(m.Message))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FailedError(a ...interface{}) error {
|
||||||
|
return errors.New(errorString(a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FailedErrorc(context MessageContext) error {
|
||||||
|
return errors.New(errorStringc(context))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FailedErrorf(format string, a ...interface{}) error {
|
||||||
|
return errors.New(errorStringf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultToolkit struct {
|
||||||
|
once sync.Once
|
||||||
|
|
||||||
|
Environment map[string]string
|
||||||
|
Writer io.Writer
|
||||||
|
Delemiter string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) AddPath(paths ...string) error {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
|
||||||
|
path, ok := d.Environment["GITHUB_PATH"]
|
||||||
|
if !ok {
|
||||||
|
return FailedError("$GITHUB_PATH must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return FailedErrorf("unable to open %s\n%w", path, err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
for _, p := range paths {
|
||||||
|
_, _ = fmt.Fprintln(f, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) ExportVariable(name string, value string) error {
|
||||||
|
return d.export("GITHUB_ENV", name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) export(env string, name string, value string) error {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
|
||||||
|
path, ok := d.Environment[env]
|
||||||
|
if !ok {
|
||||||
|
return FailedErrorf("$%s must be set", env)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return FailedErrorf("unable to open %s\n%w", path, err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if strings.ContainsRune(value, '\n') {
|
||||||
|
if _, err := fmt.Fprintln(f, fmt.Sprintf("%s<<%s\n%s\n%s", name, d.Delemiter, value, d.Delemiter)); err != nil {
|
||||||
|
return FailedError("unable to write variable")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, _ = fmt.Fprintln(f, fmt.Sprintf("%s=%s", name, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) GetInput(name string) (string, bool) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
s, ok := d.Environment[fmt.Sprintf("INPUT_%s", strings.ToUpper(name))]
|
||||||
|
return s, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) GetInputList(name string) ([]string, bool) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
s, ok := d.Environment[fmt.Sprintf("INPUT_%s", strings.ToUpper(name))]
|
||||||
|
ss := strings.Split(s, ",")
|
||||||
|
return ss, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) SetOutput(name string, value string) {
|
||||||
|
err := d.export("GITHUB_OUTPUT", name, value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) GetState(name string) (string, bool) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
s, ok := d.Environment[fmt.Sprintf("STATE_%s", strings.ToUpper(name))]
|
||||||
|
return s, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) SetState(name string, value string) {
|
||||||
|
err := d.export("GITHUB_STATE", name, value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) AddMask(mask string) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintf(d.Writer, "::add-mask::%s\n", escape(mask))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) StartGroup(title string) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintf(d.Writer, "::group::%s\n", title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) EndGroup() {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintln(d.Writer, "::endgroup::")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) IsDebug() bool {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
|
||||||
|
t, err := strconv.ParseBool(d.Environment["RUNNER_DEBUG"])
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Debug(a ...interface{}) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintf(d.Writer, "::debug::%s\n", escape(fmt.Sprint(a...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Debugf(format string, a ...interface{}) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintf(d.Writer, "::debug::%s\n", escape(fmt.Sprintf(format, a...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Error(a ...interface{}) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintln(d.Writer, errorString(a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Errorc(context MessageContext) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintln(d.Writer, errorStringc(context))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Errorf(format string, a ...interface{}) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintln(d.Writer, errorStringf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Warning(a ...interface{}) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintf(d.Writer, "::warning ::%s\n", escape(fmt.Sprint(a...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Warningc(context MessageContext) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintln(d.Writer, "::warning", escape(context.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) Warningf(format string, a ...interface{}) {
|
||||||
|
d.once.Do(d.init)
|
||||||
|
_, _ = fmt.Fprintf(d.Writer, "::warning ::%s\n", escape(fmt.Sprintf(format, a...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DefaultToolkit) init() {
|
||||||
|
if d.Environment == nil {
|
||||||
|
d.Environment = make(map[string]string)
|
||||||
|
|
||||||
|
for _, s := range os.Environ() {
|
||||||
|
t := strings.SplitN(s, "=", 2)
|
||||||
|
d.Environment[t[0]] = t[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Writer == nil {
|
||||||
|
d.Writer = os.Stdout
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Delemiter == "" {
|
||||||
|
data := make([]byte, 16) // roughly the same entropy as uuid v4 used in https://github.com/actions/toolkit/blob/b36e70495fbee083eb20f600eafa9091d832577d/packages/core/src/file-command.ts#L28
|
||||||
|
_, err := rand.Read(data)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not generate random delimiter: %w", err))
|
||||||
|
}
|
||||||
|
d.Delemiter = hex.EncodeToString(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorString(a ...interface{}) string {
|
||||||
|
return fmt.Sprintf("::error ::%s", escape(fmt.Sprint(a...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorStringc(context MessageContext) string {
|
||||||
|
return fmt.Sprintf("::error %s", context.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorStringf(format string, a ...interface{}) string {
|
||||||
|
return fmt.Sprintf("::error ::%s", escape(fmt.Errorf(format, a...).Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func escape(s string) string {
|
||||||
|
return strings.ReplaceAll(s, "\n", "%0A")
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package toolkit_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToolkit(t *testing.T) {
|
||||||
|
spec.Run(t, "Toolkit", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
)
|
||||||
|
|
||||||
|
context("MessageContext", func() {
|
||||||
|
|
||||||
|
it("renders string", func() {
|
||||||
|
mc := toolkit.MessageContext{Message: "test-message-1\ntest-message-2"}
|
||||||
|
Expect(mc.String()).To(Equal("::test-message-1%0Atest-message-2"))
|
||||||
|
|
||||||
|
mc.File = "test-file"
|
||||||
|
Expect(mc.String()).To(Equal("file=test-file::test-message-1%0Atest-message-2"))
|
||||||
|
|
||||||
|
mc.Line = "test-line"
|
||||||
|
Expect(mc.String()).To(Equal("file=test-file,line=test-line::test-message-1%0Atest-message-2"))
|
||||||
|
|
||||||
|
mc.Column = "test-column"
|
||||||
|
Expect(mc.String()).To(Equal("file=test-file,line=test-line,col=test-column::test-message-1%0Atest-message-2"))
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
context("FailedError", func() {
|
||||||
|
|
||||||
|
it("returns failed error", func() {
|
||||||
|
Expect(toolkit.FailedError("test-message-1", "test-message-2\ntest-message-3")).
|
||||||
|
To(MatchError("::error ::test-message-1test-message-2%0Atest-message-3"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns failed errorc", func() {
|
||||||
|
Expect(toolkit.FailedErrorc(toolkit.MessageContext{
|
||||||
|
File: "test-file",
|
||||||
|
Line: "test-line",
|
||||||
|
Column: "test-column",
|
||||||
|
Message: "test-message-1 test-message-2\ntest-message-3",
|
||||||
|
})).
|
||||||
|
To(MatchError("::error file=test-file,line=test-line,col=test-column::test-message-1 test-message-2%0Atest-message-3"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns failed errorf", func() {
|
||||||
|
Expect(toolkit.FailedErrorf("%s %s\n%s", "test-message-1", "test-message-2", "test-message-3")).
|
||||||
|
To(MatchError("::error ::test-message-1 test-message-2%0Atest-message-3"))
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
context("DefaultToolkit", func() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
b = &bytes.Buffer{}
|
||||||
|
tk = toolkit.DefaultToolkit{Writer: b, Delemiter: "EOF"}
|
||||||
|
)
|
||||||
|
|
||||||
|
it("adds path", func() {
|
||||||
|
f, err := os.CreateTemp("", "github-path")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = fmt.Fprintln(f, "test-value")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(f.Close()).To(Succeed())
|
||||||
|
|
||||||
|
tk.Environment = map[string]string{"GITHUB_PATH": f.Name()}
|
||||||
|
|
||||||
|
Expect(tk.AddPath("test-path-1", "test-path-2")).To(Succeed())
|
||||||
|
|
||||||
|
b, err := os.ReadFile(f.Name())
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(string(b)).To(Equal("test-value\ntest-path-1\ntest-path-2\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("exports variable", func() {
|
||||||
|
f, err := os.CreateTemp("", "github-env")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = fmt.Fprintln(f, "TEST_KEY=test-value")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(f.Close()).To(Succeed())
|
||||||
|
|
||||||
|
tk.Environment = map[string]string{"GITHUB_ENV": f.Name()}
|
||||||
|
|
||||||
|
Expect(tk.ExportVariable("TEST_NAME_1", "test-value-1")).To(Succeed())
|
||||||
|
Expect(tk.ExportVariable("TEST_NAME_2", "test-value-2\ntest-value-3")).To(Succeed())
|
||||||
|
|
||||||
|
b, err := os.ReadFile(f.Name())
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(string(b)).To(Equal("TEST_KEY=test-value\nTEST_NAME_1=test-value-1\nTEST_NAME_2<<EOF\ntest-value-2\ntest-value-3\nEOF\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("gets input", func() {
|
||||||
|
tk.Environment = map[string]string{"INPUT_TEST-1": "test-value"}
|
||||||
|
|
||||||
|
s, ok := tk.GetInput("test-1")
|
||||||
|
Expect(ok).To(BeTrue())
|
||||||
|
Expect(s).To(Equal("test-value"))
|
||||||
|
|
||||||
|
_, ok = tk.GetInput("test-2")
|
||||||
|
Expect(ok).To(BeFalse())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("gets input list", func() {
|
||||||
|
tk.Environment = map[string]string{"INPUT_BLOCKED_NAMESPACES_TEST-1": "test-value-1,test-value-2,test-value-3"}
|
||||||
|
|
||||||
|
s, ok := tk.GetInputList("blocked_namespaces_test-1")
|
||||||
|
Expect(ok).To(BeTrue())
|
||||||
|
Expect(s).To(Equal([]string{"test-value-1", "test-value-2", "test-value-3"}))
|
||||||
|
|
||||||
|
_, ok = tk.GetInputList("test-2")
|
||||||
|
Expect(ok).To(BeFalse())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets output", func() {
|
||||||
|
f, err := os.CreateTemp("", "github-output")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = fmt.Fprintln(f, "TEST_OUTPUT=test-value")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(f.Close()).To(Succeed())
|
||||||
|
tk.Environment = map[string]string{"GITHUB_OUTPUT": f.Name()}
|
||||||
|
|
||||||
|
tk.SetOutput("test-name", "test-value-1\ntest-value-2")
|
||||||
|
|
||||||
|
b, err := os.ReadFile(f.Name())
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(string(b)).To(Equal("TEST_OUTPUT=test-value\ntest-name<<EOF\ntest-value-1\ntest-value-2\nEOF\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("gets state", func() {
|
||||||
|
tk.Environment = map[string]string{"STATE_TEST-1": "test-value"}
|
||||||
|
|
||||||
|
s, ok := tk.GetState("test-1")
|
||||||
|
Expect(ok).To(BeTrue())
|
||||||
|
Expect(s).To(Equal("test-value"))
|
||||||
|
|
||||||
|
_, ok = tk.GetState("test-2")
|
||||||
|
Expect(ok).To(BeFalse())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets state", func() {
|
||||||
|
f, err := os.CreateTemp("", "github-state")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = fmt.Fprintln(f, "TEST_STATE=test-value")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(f.Close()).To(Succeed())
|
||||||
|
tk.Environment = map[string]string{"GITHUB_STATE": f.Name()}
|
||||||
|
|
||||||
|
tk.SetState("test-name", "test-value-1\ntest-value-2")
|
||||||
|
|
||||||
|
b, err := os.ReadFile(f.Name())
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(string(b)).To(Equal("TEST_STATE=test-value\ntest-name<<EOF\ntest-value-1\ntest-value-2\nEOF\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds mask", func() {
|
||||||
|
tk.AddMask("test-mask")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::add-mask::test-mask\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("starts group", func() {
|
||||||
|
tk.StartGroup("test-title")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::group::test-title\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("ends group", func() {
|
||||||
|
tk.EndGroup()
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::endgroup::\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns isDebug", func() {
|
||||||
|
tk.Environment = map[string]string{}
|
||||||
|
|
||||||
|
Expect(tk.IsDebug()).To(BeFalse())
|
||||||
|
|
||||||
|
tk.Environment["RUNNER_DEBUG"] = "true"
|
||||||
|
|
||||||
|
Expect(tk.IsDebug()).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes debug", func() {
|
||||||
|
tk.Debug("test-message-1", "test-message-2\ntest-message-3")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::debug::test-message-1test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes debugf", func() {
|
||||||
|
tk.Debugf("%s %s\n%s", "test-message-1", "test-message-2", "test-message-3")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::debug::test-message-1 test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes warning", func() {
|
||||||
|
tk.Warning("test-message-1", "test-message-2\ntest-message-3")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::warning ::test-message-1test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes warningc", func() {
|
||||||
|
tk.Warningc(toolkit.MessageContext{
|
||||||
|
File: "test-file",
|
||||||
|
Line: "test-line",
|
||||||
|
Column: "test-column",
|
||||||
|
Message: "test-message-1 test-message-2\ntest-message-3",
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::warning file=test-file,line=test-line,col=test-column::test-message-1 test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes warningf", func() {
|
||||||
|
tk.Warningf("%s %s\n%s", "test-message-1", "test-message-2", "test-message-3")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::warning ::test-message-1 test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes error", func() {
|
||||||
|
tk.Error("test-message-1", "test-message-2\ntest-message-3")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::error ::test-message-1test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes errorc", func() {
|
||||||
|
tk.Errorc(toolkit.MessageContext{
|
||||||
|
File: "test-file",
|
||||||
|
Line: "test-line",
|
||||||
|
Column: "test-column",
|
||||||
|
Message: "test-message-1 test-message-2\ntest-message-3",
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::error file=test-file,line=test-line,col=test-column::test-message-1 test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("writes errorf", func() {
|
||||||
|
tk.Errorf("%s %s\n%s", "test-message-1", "test-message-2", "test-message-3")
|
||||||
|
|
||||||
|
Expect(b.String()).To(Equal("::error ::test-message-1 test-message-2%0Atest-message-3\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddEntry(tk toolkit.Toolkit, repositories services.RepositoriesService, strategy retry.Strategy) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file := index.Path(c.Namespace, c.Name)
|
||||||
|
|
||||||
|
for a := retry.Start(strategy, nil); a.Next(); {
|
||||||
|
content, _, resp, err := repositories.GetContents(context.Background(), c.Owner, c.Repository, file, nil)
|
||||||
|
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||||
|
fmt.Printf("New Index: %s\n", c.Name)
|
||||||
|
content = &github.RepositoryContent{}
|
||||||
|
} else if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to read index %s\n%w", c.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := content.GetContent()
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to get index content\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := index.UnmarshalEntries(s)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal entries\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contains(entries, c.Namespace, c.Version) {
|
||||||
|
return toolkit.FailedErrorf("index %s already has namespace %s and version %s", c.Name, c.Namespace, c.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = append(entries, index.Entry{
|
||||||
|
Namespace: c.Namespace,
|
||||||
|
Name: c.Name,
|
||||||
|
Version: c.Version,
|
||||||
|
Address: c.Address,
|
||||||
|
})
|
||||||
|
|
||||||
|
s, err = index.MarshalEntries(entries)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to marshal entries\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, resp, err := repositories.CreateFile(context.Background(), c.Owner, c.Repository, file, &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String(fmt.Sprintf("ADD %s/%s@%s", c.Namespace, c.Name, c.Version)),
|
||||||
|
SHA: content.SHA,
|
||||||
|
Content: []byte(s),
|
||||||
|
}); resp != nil && resp.StatusCode == http.StatusConflict {
|
||||||
|
tk.Warning("retrying index update after conflict")
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to create index\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Added %s/%s@%s\n", c.Namespace, c.Name, c.Version)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolkit.FailedError("timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Owner string
|
||||||
|
Repository string
|
||||||
|
Namespace string
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c config
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.Owner, ok = tk.GetInput("owner")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("owner must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Repository, ok = tk.GetInput("repository")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("repository must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Namespace, ok = tk.GetInput("namespace")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("namespace must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Name, ok = tk.GetInput("name")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("name must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Version, ok = tk.GetInput("version")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("version must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Address, ok = tk.GetInput("address")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("address must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(entries []index.Entry, namespace string, version string) bool {
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.Namespace == namespace && e.Version == version {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
entry "github.com/buildpacks/github-actions/registry/add-entry"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddEntry(t *testing.T) {
|
||||||
|
spec.Run(t, "add-entry", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
ExpectWithOffset = NewWithT(t).ExpectWithOffset
|
||||||
|
|
||||||
|
r = &services.MockRepositoriesService{}
|
||||||
|
rOpts *github.RepositoryContentGetOptions
|
||||||
|
s = retry.LimitCount(2, retry.Regular{Min: 2})
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
asJSONString := func(v interface{}) string {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "owner").Return("test-owner", true)
|
||||||
|
tk.On("GetInput", "repository").Return("test-repository", true)
|
||||||
|
tk.On("GetInput", "namespace").Return("test-namespace", true)
|
||||||
|
tk.On("GetInput", "name").Return("test-name", true)
|
||||||
|
tk.On("GetInput", "version").Return("test-version", true)
|
||||||
|
tk.On("GetInput", "address").Return("test-address", true)
|
||||||
|
})
|
||||||
|
|
||||||
|
context("index does not exist", func() {
|
||||||
|
it.Before(func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), rOpts).
|
||||||
|
Return(nil, nil, &github.Response{Response: &http.Response{StatusCode: http.StatusNotFound}}, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates new index", func() {
|
||||||
|
r.On("CreateFile", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String("ADD test-namespace/test-name@test-version"),
|
||||||
|
Content: []byte(fmt.Sprintf("%s\n", asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
}))),
|
||||||
|
}).
|
||||||
|
Return(nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.AddEntry(tk, r, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
context("index does exist", func() {
|
||||||
|
|
||||||
|
it("fails if version already exists", func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
})),
|
||||||
|
SHA: github.String("test-sha"),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.AddEntry(tk, r, s)).
|
||||||
|
To(MatchError("::error ::index test-name already has namespace test-namespace and version test-version"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds entry to index", func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(index.Entry{
|
||||||
|
Namespace: "another-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
})),
|
||||||
|
SHA: github.String("test-sha"),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
r.On("CreateFile", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String("ADD test-namespace/test-name@test-version"),
|
||||||
|
Content: []byte(fmt.Sprintf("%s\n%s\n",
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "another-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
}),
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
SHA: github.String("test-sha"),
|
||||||
|
}).
|
||||||
|
Return(nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.AddEntry(tk, r, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
entry "github.com/buildpacks/github-actions/registry/add-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tk := &toolkit.DefaultToolkit{}
|
||||||
|
|
||||||
|
t, ok := tk.GetInput("token")
|
||||||
|
if !ok {
|
||||||
|
fmt.Println(toolkit.FailedError("token must be specified"))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gh := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: t})))
|
||||||
|
|
||||||
|
strategy := retry.LimitTime(2*time.Minute,
|
||||||
|
retry.Exponential{
|
||||||
|
Initial: time.Second,
|
||||||
|
Jitter: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := entry.AddEntry(tk, gh.Repositories, strategy); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 the original author or 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
|
|
||||||
*
|
|
||||||
* https://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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/google/go-github/v32/github"
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
|
|
||||||
"github.com/buildpacks/github-actions/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var (
|
|
||||||
r registry.Registry
|
|
||||||
|
|
||||||
err error
|
|
||||||
ok bool
|
|
||||||
)
|
|
||||||
|
|
||||||
var token oauth2.Token
|
|
||||||
if token.AccessToken, ok = os.LookupEnv("INPUT_TOKEN"); !ok {
|
|
||||||
panic(fmt.Errorf("token must be specified"))
|
|
||||||
}
|
|
||||||
r.Issues = github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&token))).Issues
|
|
||||||
|
|
||||||
if r.ID, ok = os.LookupEnv("INPUT_ID"); !ok {
|
|
||||||
panic(fmt.Errorf("id must be specified"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.Version, ok = os.LookupEnv("INPUT_VERSION"); !ok {
|
|
||||||
panic(fmt.Errorf("id must be specified"))
|
|
||||||
}
|
|
||||||
|
|
||||||
yank := false
|
|
||||||
if s, ok := os.LookupEnv("INPUT_YANK"); ok {
|
|
||||||
if yank, err = strconv.ParseBool(s); err != nil {
|
|
||||||
panic(fmt.Errorf("unable to parse INPUT_YANK='%s' as a bool", s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if yank {
|
|
||||||
if err := r.Yank(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
address, ok := os.LookupEnv("INPUT_ADDRESS")
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("address must be specified"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := r.Add(address); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/compute-metadata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := metadata.ComputeMetadata(&toolkit.DefaultToolkit{}); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/namespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ComputeMetadata(tk toolkit.Toolkit) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var issue github.Issue
|
||||||
|
if err := json.Unmarshal([]byte(c.Issue), &issue); err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal issue\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var request index.Request
|
||||||
|
if err := toml.Unmarshal([]byte(strings.ReplaceAll(*issue.Body, "```", "")), &request); err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal body\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ns string
|
||||||
|
name string
|
||||||
|
)
|
||||||
|
if g := index.ValidRequestId.FindStringSubmatch(request.ID); g == nil {
|
||||||
|
return toolkit.FailedErrorf("invalid id %s", request.ID)
|
||||||
|
} else {
|
||||||
|
ns = g[1]
|
||||||
|
name = g[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
if namespace.IsRestricted(ns) {
|
||||||
|
return toolkit.FailedErrorf("restricted namespace %s", ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !index.ValidRequestVersion.MatchString(request.Version) {
|
||||||
|
return toolkit.FailedErrorf("invalid version %s", request.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !request.Yank && !index.ValidRequestAddress.MatchString(request.Address) {
|
||||||
|
return toolkit.FailedErrorf("invalid address %s", request.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(`Metadata:
|
||||||
|
ID: %s
|
||||||
|
Version: %s
|
||||||
|
Address: %s
|
||||||
|
Namespace: %s
|
||||||
|
Name: %s
|
||||||
|
`, request.ID, request.Version, request.Address, ns, name)
|
||||||
|
|
||||||
|
tk.SetOutput("id", request.ID)
|
||||||
|
tk.SetOutput("namespace", ns)
|
||||||
|
tk.SetOutput("name", name)
|
||||||
|
tk.SetOutput("version", request.Version)
|
||||||
|
|
||||||
|
if !request.Yank {
|
||||||
|
tk.SetOutput("address", request.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Issue string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c config
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.Issue, ok = tk.GetInput("issue")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("issue must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metadata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/compute-metadata"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestComputeMetadata(t *testing.T) {
|
||||||
|
spec.Run(t, "compute-metadata", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
ExpectWithOffset = NewWithT(t).ExpectWithOffset
|
||||||
|
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
asJSONString := func(v interface{}) string {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
asTOMLString := func(v interface{}) string {
|
||||||
|
b, err := toml.Marshal(v)
|
||||||
|
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
it("returns error when id is invalid", func() {
|
||||||
|
tk.On("GetInput", "issue").Return(asJSONString(github.Issue{
|
||||||
|
Body: github.String(fmt.Sprintf("```\n%s\n```", asTOMLString(index.Request{
|
||||||
|
ID: "test@namespace/test-name",
|
||||||
|
}))),
|
||||||
|
}), true)
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(MatchError("::error ::invalid id test@namespace/test-name"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns error if namespace is restricted", func() {
|
||||||
|
tk.On("GetInput", "issue").Return(asJSONString(github.Issue{
|
||||||
|
Body: github.String(asTOMLString(index.Request{
|
||||||
|
ID: "cnb/test-name",
|
||||||
|
})),
|
||||||
|
}), true)
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(MatchError("::error ::restricted namespace cnb"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns error when version is invalid", func() {
|
||||||
|
tk.On("GetInput", "issue").Return(asJSONString(github.Issue{
|
||||||
|
Body: github.String(fmt.Sprintf("```\n%s\n```", asTOMLString(index.Request{
|
||||||
|
ID: "test-namespace/test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
}))),
|
||||||
|
}), true)
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(MatchError("::error ::invalid version test-version"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns error when yank is false and address is invalid", func() {
|
||||||
|
tk.On("GetInput", "issue").Return(asJSONString(github.Issue{
|
||||||
|
Body: github.String(asTOMLString(index.Request{
|
||||||
|
ID: "test-namespace/test-name",
|
||||||
|
Version: "0.0.0",
|
||||||
|
Address: "host.com:443/repository/image:tag",
|
||||||
|
})),
|
||||||
|
}), true)
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(MatchError("::error ::invalid address host.com:443/repository/image:tag"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("computes metadata when yank is false", func() {
|
||||||
|
tk.On("GetInput", "issue").Return(asJSONString(github.Issue{
|
||||||
|
Body: github.String(asTOMLString(index.Request{
|
||||||
|
ID: "test-namespace/test-name",
|
||||||
|
Version: "0.0.0",
|
||||||
|
Address: "host.com:443/repository/image@sha256:133f2117e15569ca59645eddad78f4a6a675c435f9614e4b137364274f3a7614",
|
||||||
|
})),
|
||||||
|
}), true)
|
||||||
|
tk.On("SetOutput", "id", "test-namespace/test-name")
|
||||||
|
tk.On("SetOutput", "version", "0.0.0")
|
||||||
|
tk.On("SetOutput", "address", "host.com:443/repository/image@sha256:133f2117e15569ca59645eddad78f4a6a675c435f9614e4b137364274f3a7614")
|
||||||
|
tk.On("SetOutput", "namespace", "test-namespace")
|
||||||
|
tk.On("SetOutput", "name", "test-name")
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("computes metadata when yank is true", func() {
|
||||||
|
tk.On("GetInput", "issue").Return(asJSONString(github.Issue{
|
||||||
|
Body: github.String(asTOMLString(index.Request{
|
||||||
|
ID: "test-namespace/test-name",
|
||||||
|
Version: "0.0.0",
|
||||||
|
Yank: true,
|
||||||
|
})),
|
||||||
|
}), true)
|
||||||
|
tk.On("SetOutput", "id", "test-namespace/test-name")
|
||||||
|
tk.On("SetOutput", "version", "0.0.0")
|
||||||
|
tk.On("SetOutput", "namespace", "test-namespace")
|
||||||
|
tk.On("SetOutput", "name", "test-name")
|
||||||
|
|
||||||
|
Expect(metadata.ComputeMetadata(tk)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Entry struct {
|
||||||
|
Namespace string `json:"ns"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Yanked bool `json:"yanked"`
|
||||||
|
Address string `json:"addr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalEntries(entries []Entry) (string, error) {
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
j := json.NewEncoder(b)
|
||||||
|
|
||||||
|
for _, e := range entries {
|
||||||
|
if err := j.Encode(e); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnmarshalEntries(content string) ([]Entry, error) {
|
||||||
|
var entries []Entry
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(strings.NewReader(content))
|
||||||
|
for scanner.Scan() {
|
||||||
|
var e Entry
|
||||||
|
if err := json.Unmarshal(scanner.Bytes(), &e); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
entries = append(entries, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, scanner.Err()
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEntry(t *testing.T) {
|
||||||
|
spec.Run(t, "entry", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
ExpectWithOffset = NewWithT(t).ExpectWithOffset
|
||||||
|
)
|
||||||
|
|
||||||
|
asJSONString := func(v interface{}) string {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
it("marshals entries", func() {
|
||||||
|
Expect(index.MarshalEntries([]index.Entry{
|
||||||
|
{
|
||||||
|
Namespace: "test-namespace-1",
|
||||||
|
Name: "test-name-1",
|
||||||
|
Version: "test-version-1",
|
||||||
|
Address: "test-address-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Namespace: "test-namespace-2",
|
||||||
|
Name: "test-name-2",
|
||||||
|
Version: "test-version-2",
|
||||||
|
Address: "test-address-2",
|
||||||
|
},
|
||||||
|
})).To(Equal(fmt.Sprintf("%s\n%s\n",
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace-1",
|
||||||
|
Name: "test-name-1",
|
||||||
|
Version: "test-version-1",
|
||||||
|
Address: "test-address-1",
|
||||||
|
}),
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace-2",
|
||||||
|
Name: "test-name-2",
|
||||||
|
Version: "test-version-2",
|
||||||
|
Address: "test-address-2",
|
||||||
|
}),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("unmarshals entries", func() {
|
||||||
|
Expect(index.UnmarshalEntries(fmt.Sprintf("%s\n%s\n",
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace-1",
|
||||||
|
Name: "test-name-1",
|
||||||
|
Version: "test-version-1",
|
||||||
|
Address: "test-address-1",
|
||||||
|
}),
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace-2",
|
||||||
|
Name: "test-name-2",
|
||||||
|
Version: "test-version-2",
|
||||||
|
Address: "test-address-2",
|
||||||
|
}),
|
||||||
|
))).To(Equal([]index.Entry{
|
||||||
|
{
|
||||||
|
Namespace: "test-namespace-1",
|
||||||
|
Name: "test-name-1",
|
||||||
|
Version: "test-version-1",
|
||||||
|
Address: "test-address-1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Namespace: "test-namespace-2",
|
||||||
|
Name: "test-name-2",
|
||||||
|
Version: "test-version-2",
|
||||||
|
Address: "test-address-2",
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Path(namespace string, name string) string {
|
||||||
|
var path string
|
||||||
|
|
||||||
|
switch len(name) {
|
||||||
|
case 1:
|
||||||
|
path = "1"
|
||||||
|
case 2:
|
||||||
|
path = "2"
|
||||||
|
case 3:
|
||||||
|
path = filepath.Join("3", name[0:2])
|
||||||
|
default:
|
||||||
|
path = filepath.Join(name[0:2], name[2:4])
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(path, filepath.Join(fmt.Sprintf("%s_%s", namespace, name)))
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPath(t *testing.T) {
|
||||||
|
spec.Run(t, "path", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
)
|
||||||
|
|
||||||
|
it("returns path for 1 character name", func() {
|
||||||
|
Expect(index.Path("test-namespace", "a")).To(Equal(filepath.Join("1", "test-namespace_a")))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns path for 2 character name", func() {
|
||||||
|
Expect(index.Path("test-namespace", "ab")).To(Equal(filepath.Join("2", "test-namespace_ab")))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns path for 3 character name", func() {
|
||||||
|
Expect(index.Path("test-namespace", "abc")).To(Equal(filepath.Join("3", "ab", "test-namespace_abc")))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns path for 4+ character name", func() {
|
||||||
|
Expect(index.Path("test-namespace", "abcd")).To(Equal(filepath.Join("ab", "cd", "test-namespace_abcd")))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ValidRequestId = regexp.MustCompile(`^([a-zA-Z0-9.-]+)/([a-zA-Z0-9./-]+)$`)
|
||||||
|
ValidRequestVersion = regexp.MustCompile(`^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
|
||||||
|
ValidRequestAddress = regexp.MustCompile(`(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9](?::[0-9]+)?/[^:]+@sha256:[A-Fa-f0-9]{64}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
ID string
|
||||||
|
Version string
|
||||||
|
Address string `toml:"addr"`
|
||||||
|
Yank bool `toml:"yank,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RequestFailureLabel = "failure"
|
||||||
|
RequestSuccessLabel = "succeeded"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WaitForCompletion(number int, url string, tk toolkit.Toolkit, issues services.IssuesService, strategy retry.Strategy) error {
|
||||||
|
for a := retry.Start(strategy, nil); a.Next(); {
|
||||||
|
issue, _, err := issues.Get(context.Background(), "buildpacks", "registry-index", number)
|
||||||
|
if err != nil {
|
||||||
|
tk.Warningf("unable to get state for %s", url)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, l := range issue.Labels {
|
||||||
|
if *l.Name == RequestFailureLabel {
|
||||||
|
return toolkit.FailedErrorf("Registry request %s failed", url)
|
||||||
|
} else if *l.Name == RequestSuccessLabel {
|
||||||
|
fmt.Printf("Registry request %s succeeded\n", url)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolkit.FailedError("timed out waiting for request to be processed")
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package index_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWaitForCompletion(t *testing.T) {
|
||||||
|
spec.Run(t, "wait-for-completion", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
|
||||||
|
i = &services.MockIssuesService{}
|
||||||
|
s = retry.LimitCount(2, retry.Regular{Min: 2})
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
it("it handles success", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).
|
||||||
|
Return(&github.Issue{Labels: []*github.Label{{Name: github.String(index.RequestSuccessLabel)}}}, nil, nil)
|
||||||
|
|
||||||
|
Expect(index.WaitForCompletion(1, "test-url", tk, i, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("it handles failure", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).
|
||||||
|
Return(&github.Issue{Labels: []*github.Label{{Name: github.String(index.RequestFailureLabel)}}}, nil, nil)
|
||||||
|
|
||||||
|
Expect(index.WaitForCompletion(1, "test-url", tk, i, s)).
|
||||||
|
To(MatchError("::error ::Registry request test-url failed"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("retries", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).
|
||||||
|
Return(&github.Issue{}, nil, nil).
|
||||||
|
Once()
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).
|
||||||
|
Return(&github.Issue{Labels: []*github.Label{{Name: github.String(index.RequestSuccessLabel)}}}, nil, nil)
|
||||||
|
|
||||||
|
Expect(index.WaitForCompletion(1, "test-url", tk, i, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namespace
|
||||||
|
|
||||||
|
var restrictedNamespaces = []string{
|
||||||
|
"buildpack",
|
||||||
|
"buildpack-io",
|
||||||
|
"buildpack.io",
|
||||||
|
"buildpackio",
|
||||||
|
"buildpacks",
|
||||||
|
"buildpacks-io",
|
||||||
|
"buildpacks.io",
|
||||||
|
"cnb",
|
||||||
|
"cnbs",
|
||||||
|
"cncf",
|
||||||
|
"cncf-cnb",
|
||||||
|
"cncf-cnbs",
|
||||||
|
"example",
|
||||||
|
"examples",
|
||||||
|
"official",
|
||||||
|
"pack",
|
||||||
|
"sample",
|
||||||
|
"samples",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Namespace struct {
|
||||||
|
Owners []Owner `json:"owners"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRestricted(namespace string) bool {
|
||||||
|
for _, n := range restrictedNamespaces {
|
||||||
|
if n == namespace {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namespace_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/namespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNamespace(t *testing.T) {
|
||||||
|
spec.Run(t, "namespace", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
)
|
||||||
|
|
||||||
|
it("identifies restricted namespaces", func() {
|
||||||
|
Expect(namespace.IsRestricted("cnb")).To(BeTrue())
|
||||||
|
Expect(namespace.IsRestricted("test-namespace")).To(BeFalse())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namespace
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrganizationType = "github_org"
|
||||||
|
UserType = "github_user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Owner struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OwnerPredicate func(Owner) bool
|
||||||
|
|
||||||
|
func IsOwner(owners []Owner, predicate OwnerPredicate) bool {
|
||||||
|
for _, o := range owners {
|
||||||
|
if predicate(o) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ByUser(id int64) OwnerPredicate {
|
||||||
|
return func(owner Owner) bool {
|
||||||
|
return owner.Type == UserType && owner.ID == id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ByOrganizations(ids []int64) OwnerPredicate {
|
||||||
|
return func(owner Owner) bool {
|
||||||
|
for _, id := range ids {
|
||||||
|
if owner.Type == OrganizationType && owner.ID == id {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namespace_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/namespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOwner(t *testing.T) {
|
||||||
|
spec.Run(t, "owner", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
)
|
||||||
|
|
||||||
|
it("identifies owner by predicate", func() {
|
||||||
|
Expect(namespace.IsOwner([]namespace.Owner{{}}, func(_ namespace.Owner) bool {
|
||||||
|
return false
|
||||||
|
})).To(BeFalse())
|
||||||
|
|
||||||
|
Expect(namespace.IsOwner([]namespace.Owner{{}}, func(_ namespace.Owner) bool {
|
||||||
|
return true
|
||||||
|
})).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("identifies owner by user", func() {
|
||||||
|
Expect(namespace.ByUser(1)(namespace.Owner{ID: 2, Type: namespace.OrganizationType})).To(BeFalse())
|
||||||
|
Expect(namespace.ByUser(1)(namespace.Owner{ID: 2, Type: namespace.UserType})).To(BeFalse())
|
||||||
|
Expect(namespace.ByUser(1)(namespace.Owner{ID: 1, Type: namespace.OrganizationType})).To(BeFalse())
|
||||||
|
Expect(namespace.ByUser(1)(namespace.Owner{ID: 1, Type: namespace.UserType})).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("identifies owner by organizations", func() {
|
||||||
|
Expect(namespace.ByOrganizations([]int64{1})(namespace.Owner{ID: 2, Type: namespace.UserType})).To(BeFalse())
|
||||||
|
Expect(namespace.ByOrganizations([]int64{1})(namespace.Owner{ID: 2, Type: namespace.OrganizationType})).To(BeFalse())
|
||||||
|
Expect(namespace.ByOrganizations([]int64{1})(namespace.Owner{ID: 1, Type: namespace.UserType})).To(BeFalse())
|
||||||
|
Expect(namespace.ByOrganizations([]int64{1})(namespace.Owner{ID: 1, Type: namespace.OrganizationType})).To(BeTrue())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namespace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
const version = "v1"
|
||||||
|
|
||||||
|
func Path(namespace string) string {
|
||||||
|
return filepath.Join(version, fmt.Sprintf("%s.json", namespace))
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package namespace_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/namespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPath(t *testing.T) {
|
||||||
|
spec.Run(t, "path", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
)
|
||||||
|
|
||||||
|
it("returns namespace path", func() {
|
||||||
|
Expect(namespace.Path("test-namespace")).To(Equal(filepath.Join("v1", "test-namespace.json")))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
// Code generated by mockery v2.4.0-beta. DO NOT EDIT.
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
github "github.com/google/go-github/v39/github"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockIssuesService is an autogenerated mock type for the IssuesService type
|
||||||
|
type MockIssuesService struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create provides a mock function with given fields: ctx, owner, repo, issue
|
||||||
|
func (_m *MockIssuesService) Create(ctx context.Context, owner string, repo string, issue *github.IssueRequest) (*github.Issue, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, issue)
|
||||||
|
|
||||||
|
var r0 *github.Issue
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, *github.IssueRequest) *github.Issue); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, issue)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.Issue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, *github.IssueRequest) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, issue)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, *github.IssueRequest) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, issue)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get provides a mock function with given fields: ctx, owner, repo, number
|
||||||
|
func (_m *MockIssuesService) Get(ctx context.Context, owner string, repo string, number int) (*github.Issue, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, number)
|
||||||
|
|
||||||
|
var r0 *github.Issue
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int) *github.Issue); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, number)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.Issue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, int) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, number)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, int) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, number)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Code generated by mockery v2.4.0-beta. DO NOT EDIT.
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
github "github.com/google/go-github/v39/github"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockOrganizationsService is an autogenerated mock type for the OrganizationsService type
|
||||||
|
type MockOrganizationsService struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// List provides a mock function with given fields: ctx, user, opts
|
||||||
|
func (_m *MockOrganizationsService) List(ctx context.Context, user string, opts *github.ListOptions) ([]*github.Organization, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, user, opts)
|
||||||
|
|
||||||
|
var r0 []*github.Organization
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, *github.ListOptions) []*github.Organization); ok {
|
||||||
|
r0 = rf(ctx, user, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*github.Organization)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, *github.ListOptions) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, user, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, *github.ListOptions) error); ok {
|
||||||
|
r2 = rf(ctx, user, opts)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Code generated by mockery v2.4.0-beta. DO NOT EDIT.
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
github "github.com/google/go-github/v39/github"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockRepositoriesService is an autogenerated mock type for the RepositoriesService type
|
||||||
|
type MockRepositoriesService struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFile provides a mock function with given fields: ctx, owner, repo, path, opts
|
||||||
|
func (_m *MockRepositoriesService) CreateFile(ctx context.Context, owner string, repo string, path string, opts *github.RepositoryContentFileOptions) (*github.RepositoryContentResponse, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, path, opts)
|
||||||
|
|
||||||
|
var r0 *github.RepositoryContentResponse
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *github.RepositoryContentFileOptions) *github.RepositoryContentResponse); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.RepositoryContentResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, *github.RepositoryContentFileOptions) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, string, *github.RepositoryContentFileOptions) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContents provides a mock function with given fields: ctx, owner, repo, path, opts
|
||||||
|
func (_m *MockRepositoriesService) GetContents(ctx context.Context, owner string, repo string, path string, opts *github.RepositoryContentGetOptions) (*github.RepositoryContent, []*github.RepositoryContent, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, path, opts)
|
||||||
|
|
||||||
|
var r0 *github.RepositoryContent
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *github.RepositoryContentGetOptions) *github.RepositoryContent); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.RepositoryContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 []*github.RepositoryContent
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, *github.RepositoryContentGetOptions) []*github.RepositoryContent); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).([]*github.RepositoryContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 *github.Response
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, string, *github.RepositoryContentGetOptions) *github.Response); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(2) != nil {
|
||||||
|
r2 = ret.Get(2).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r3 error
|
||||||
|
if rf, ok := ret.Get(3).(func(context.Context, string, string, string, *github.RepositoryContentGetOptions) error); ok {
|
||||||
|
r3 = rf(ctx, owner, repo, path, opts)
|
||||||
|
} else {
|
||||||
|
r3 = ret.Error(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2, r3
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate mockery --all --inpackage --case=underscore
|
||||||
|
|
||||||
|
type IssuesService interface {
|
||||||
|
Create(ctx context.Context, owner string, repo string, issue *github.IssueRequest) (*github.Issue, *github.Response, error)
|
||||||
|
Get(ctx context.Context, owner string, repo string, number int) (*github.Issue, *github.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrganizationsService interface {
|
||||||
|
List(ctx context.Context, user string, opts *github.ListOptions) ([]*github.Organization, *github.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type RepositoriesService interface {
|
||||||
|
CreateFile(ctx context.Context, owner, repo, path string, opts *github.RepositoryContentFileOptions) (*github.RepositoryContentResponse, *github.Response, error)
|
||||||
|
GetContents(ctx context.Context, owner, repo, path string, opts *github.RepositoryContentGetOptions) (fileContent *github.RepositoryContent, directoryContent []*github.RepositoryContent, resp *github.Response, err error)
|
||||||
|
}
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 the original author or 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
|
|
||||||
*
|
|
||||||
* https://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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/google/go-github/v32/github"
|
|
||||||
"github.com/pelletier/go-toml"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IssuesService interface {
|
|
||||||
Create(ctx context.Context, owner string, repo string, issue *github.IssueRequest) (*github.Issue, *github.Response, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Registry struct {
|
|
||||||
Issues IssuesService
|
|
||||||
ID string
|
|
||||||
Version string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Registry) Add(address string) error {
|
|
||||||
body, err := toml.Marshal(map[string]string{
|
|
||||||
"id": r.ID,
|
|
||||||
"version": r.Version,
|
|
||||||
"addr": address,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to marshal to TOML\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &github.IssueRequest{
|
|
||||||
Title: github.String(fmt.Sprintf("ADD %s@%s", r.ID, r.Version)),
|
|
||||||
Body: github.String(string(body)),
|
|
||||||
}
|
|
||||||
|
|
||||||
issue, _, err := r.Issues.Create(context.Background(), "buildpacks", "registry-index", req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to create issue\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Created issue %s\n", *issue.HTMLURL)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Registry) Yank() error {
|
|
||||||
body, err := toml.Marshal(map[string]string{
|
|
||||||
"id": r.ID,
|
|
||||||
"version": r.Version,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to marshal to TOML\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &github.IssueRequest{
|
|
||||||
Title: github.String(fmt.Sprintf("YANK %s@%s", r.ID, r.Version)),
|
|
||||||
Body: github.String(string(body)),
|
|
||||||
}
|
|
||||||
|
|
||||||
issue, _, err := r.Issues.Create(context.Background(), "buildpacks", "registry-index", req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to create issue\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Created issue %s\n", *issue.HTMLURL)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 the original author or 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
|
|
||||||
*
|
|
||||||
* https://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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package registry_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-github/v32/github"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
"github.com/pelletier/go-toml"
|
|
||||||
"github.com/sclevine/spec"
|
|
||||||
"github.com/sclevine/spec/report"
|
|
||||||
|
|
||||||
"github.com/buildpacks/github-actions/registry"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRegistry(t *testing.T) {
|
|
||||||
spec.Run(t, "registry", func(t *testing.T, when spec.G, it spec.S) {
|
|
||||||
var (
|
|
||||||
Expect = NewWithT(t).Expect
|
|
||||||
|
|
||||||
i = TestIssues{Response: &github.Issue{HTMLURL: github.String("test-html-url")}}
|
|
||||||
|
|
||||||
r = registry.Registry{
|
|
||||||
Issues: &i,
|
|
||||||
ID: "test-namespace/test-name",
|
|
||||||
Version: "test-version",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
it("creates add issue", func() {
|
|
||||||
Expect(r.Add("test-address")).To(Succeed())
|
|
||||||
|
|
||||||
Expect(i.Owner).To(Equal("buildpacks"))
|
|
||||||
Expect(i.Repo).To(Equal("registry-index"))
|
|
||||||
Expect(*i.Request.Title).To(Equal("ADD test-namespace/test-name@test-version"))
|
|
||||||
|
|
||||||
var body map[string]string
|
|
||||||
Expect(toml.Unmarshal([]byte(*i.Request.Body), &body)).To(Succeed())
|
|
||||||
Expect(body).To(Equal(map[string]string{
|
|
||||||
"id": "test-namespace/test-name",
|
|
||||||
"version": "test-version",
|
|
||||||
"addr": "test-address",
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates yank issue", func() {
|
|
||||||
Expect(r.Yank()).To(Succeed())
|
|
||||||
|
|
||||||
Expect(i.Owner).To(Equal("buildpacks"))
|
|
||||||
Expect(i.Repo).To(Equal("registry-index"))
|
|
||||||
Expect(*i.Request.Title).To(Equal("YANK test-namespace/test-name@test-version"))
|
|
||||||
|
|
||||||
var body map[string]string
|
|
||||||
Expect(toml.Unmarshal([]byte(*i.Request.Body), &body)).To(Succeed())
|
|
||||||
Expect(body).To(Equal(map[string]string{
|
|
||||||
"id": "test-namespace/test-name",
|
|
||||||
"version": "test-version",
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
}, spec.Report(report.Terminal{}))
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestIssues struct {
|
|
||||||
Owner string
|
|
||||||
Repo string
|
|
||||||
Request *github.IssueRequest
|
|
||||||
|
|
||||||
Response *github.Issue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TestIssues) Create(_ context.Context, owner string, repo string, issue *github.IssueRequest) (*github.Issue, *github.Response, error) {
|
|
||||||
t.Owner = owner
|
|
||||||
t.Repo = repo
|
|
||||||
t.Request = issue
|
|
||||||
|
|
||||||
return t.Response, nil, nil
|
|
||||||
}
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
entry "github.com/buildpacks/github-actions/registry/request-add-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tk := &toolkit.DefaultToolkit{}
|
||||||
|
|
||||||
|
t, ok := tk.GetInput("token")
|
||||||
|
if !ok {
|
||||||
|
fmt.Println(toolkit.FailedError("token must be specified"))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gh := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: t})))
|
||||||
|
|
||||||
|
strategy := retry.LimitTime(20*time.Minute,
|
||||||
|
retry.Exponential{
|
||||||
|
Initial: time.Second,
|
||||||
|
MaxDelay: 30 * time.Second,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := entry.RequestAddEntry(tk, gh.Issues, strategy); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RequestAddEntry(tk toolkit.Toolkit, issues services.IssuesService, strategy retry.Strategy) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := toml.Marshal(index.Request{
|
||||||
|
ID: c.ID,
|
||||||
|
Version: c.Version,
|
||||||
|
Address: c.Address,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to marshal to TOML\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &github.IssueRequest{
|
||||||
|
Title: github.String(fmt.Sprintf("ADD %s@%s", c.ID, c.Version)),
|
||||||
|
Body: github.String(fmt.Sprintf("```\n%s\n```", string(body))),
|
||||||
|
}
|
||||||
|
|
||||||
|
issue, _, err := issues.Create(context.Background(), "buildpacks", "registry-index", req)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to create issue\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := *issue.HTMLURL
|
||||||
|
number := *issue.Number
|
||||||
|
|
||||||
|
fmt.Printf("Created issue %s\n", url)
|
||||||
|
return index.WaitForCompletion(number, url, tk, issues, strategy)
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
ID string
|
||||||
|
Version string
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c config
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.ID, ok = tk.GetInput("id")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("id must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Version, ok = tk.GetInput("version")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("version must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Address, ok = tk.GetInput("address")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("address must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
"github.com/buildpacks/github-actions/registry/request-add-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequestAddEntry(t *testing.T) {
|
||||||
|
spec.Run(t, "request-add-entry", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
|
||||||
|
i = &services.MockIssuesService{}
|
||||||
|
s = retry.LimitCount(2, retry.Regular{Min: 2})
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "id").Return("test-namespace/test-name", true)
|
||||||
|
tk.On("GetInput", "version").Return("test-version", true)
|
||||||
|
tk.On("GetInput", "address").Return("test-address", true)
|
||||||
|
|
||||||
|
b, err := toml.Marshal(index.Request{
|
||||||
|
ID: "test-namespace/test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
i.On("Create", mock.Anything, "buildpacks", "registry-index", &github.IssueRequest{
|
||||||
|
Title: github.String("ADD test-namespace/test-name@test-version"),
|
||||||
|
Body: github.String(fmt.Sprintf("```\n%s\n```", string(b))),
|
||||||
|
}).Return(&github.Issue{
|
||||||
|
Number: github.Int(1),
|
||||||
|
HTMLURL: github.String("test-html-url"),
|
||||||
|
}, nil, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("add entry succeeds", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).Return(&github.Issue{
|
||||||
|
Labels: []*github.Label{{Name: github.String(index.RequestSuccessLabel)}},
|
||||||
|
}, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.RequestAddEntry(tk, i, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("add entry fails", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).Return(&github.Issue{
|
||||||
|
Labels: []*github.Label{{Name: github.String(index.RequestFailureLabel)}},
|
||||||
|
}, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.RequestAddEntry(tk, i, s)).
|
||||||
|
To(MatchError("::error ::Registry request test-html-url failed"))
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
entry "github.com/buildpacks/github-actions/registry/request-yank-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tk := &toolkit.DefaultToolkit{}
|
||||||
|
|
||||||
|
t, ok := tk.GetInput("token")
|
||||||
|
if !ok {
|
||||||
|
fmt.Println(toolkit.FailedError("token must be specified"))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gh := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: t})))
|
||||||
|
|
||||||
|
strategy := retry.LimitTime(20*time.Minute,
|
||||||
|
retry.Exponential{
|
||||||
|
Initial: time.Second,
|
||||||
|
MaxDelay: 30 * time.Second,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := entry.RequestYankEntry(tk, gh.Issues, strategy); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RequestYankEntry(tk toolkit.Toolkit, issues services.IssuesService, strategy retry.Strategy) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := toml.Marshal(index.Request{
|
||||||
|
ID: c.ID,
|
||||||
|
Version: c.Version,
|
||||||
|
Yank: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to marshal to TOML\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &github.IssueRequest{
|
||||||
|
Title: github.String(fmt.Sprintf("YANK %s@%s", c.ID, c.Version)),
|
||||||
|
Body: github.String(fmt.Sprintf("```\n%s\n```", string(body))),
|
||||||
|
}
|
||||||
|
|
||||||
|
issue, _, err := issues.Create(context.Background(), "buildpacks", "registry-index", req)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to create issue\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := *issue.HTMLURL
|
||||||
|
number := *issue.Number
|
||||||
|
|
||||||
|
fmt.Printf("Created issue %s\n", url)
|
||||||
|
return index.WaitForCompletion(number, url, tk, issues, strategy)
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
ID string
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c config
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.ID, ok = tk.GetInput("id")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("id must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Version, ok = tk.GetInput("version")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("version must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
"github.com/buildpacks/github-actions/registry/request-yank-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequestYankEntry(t *testing.T) {
|
||||||
|
spec.Run(t, "request-yank-entry", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
|
||||||
|
i = &services.MockIssuesService{}
|
||||||
|
s = retry.LimitCount(2, retry.Regular{Min: 2})
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "id").Return("test-namespace/test-name", true)
|
||||||
|
tk.On("GetInput", "version").Return("test-version", true)
|
||||||
|
|
||||||
|
b, err := toml.Marshal(index.Request{
|
||||||
|
ID: "test-namespace/test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Yank: true,
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
i.On("Create", mock.Anything, "buildpacks", "registry-index", &github.IssueRequest{
|
||||||
|
Title: github.String("YANK test-namespace/test-name@test-version"),
|
||||||
|
Body: github.String(fmt.Sprintf("```\n%s\n```", string(b))),
|
||||||
|
}).Return(&github.Issue{
|
||||||
|
Number: github.Int(1),
|
||||||
|
HTMLURL: github.String("test-html-url"),
|
||||||
|
}, nil, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("yank entry succeeds", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).Return(&github.Issue{
|
||||||
|
Labels: []*github.Label{{Name: github.String(index.RequestSuccessLabel)}},
|
||||||
|
}, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.RequestYankEntry(tk, i, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
it("yank entry fails", func() {
|
||||||
|
i.On("Get", mock.Anything, "buildpacks", "registry-index", 1).Return(&github.Issue{
|
||||||
|
Labels: []*github.Label{{Name: github.String(index.RequestFailureLabel)}},
|
||||||
|
}, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.RequestYankEntry(tk, i, s)).
|
||||||
|
To(MatchError("::error ::Registry request test-html-url failed"))
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/verify-namespace-owner"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tk := &toolkit.DefaultToolkit{}
|
||||||
|
|
||||||
|
t, ok := tk.GetInput("token")
|
||||||
|
if !ok {
|
||||||
|
fmt.Println(toolkit.FailedError("token must be specified"))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gh := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: t})))
|
||||||
|
|
||||||
|
strategy := retry.LimitTime(2*time.Minute,
|
||||||
|
retry.Exponential{
|
||||||
|
Initial: time.Second,
|
||||||
|
Jitter: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := owner.VerifyNamespaceOwner(tk, gh.Organizations, gh.Repositories, strategy); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package owner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/namespace"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VerifyNamespaceOwner(tk toolkit.Toolkit, organizations services.OrganizationsService, repositories services.RepositoriesService, strategy retry.Strategy) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var user github.User
|
||||||
|
if err := json.Unmarshal([]byte(c.User), &user); err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal user\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := getNamespace(tk, c, user, repositories, strategy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if isBlockedNamespaces(config{}) {
|
||||||
|
return toolkit.FailedErrorf("The namespace '%s' is restricted.", c.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
if namespace.IsOwner(n.Owners, namespace.ByUser(*user.ID)) {
|
||||||
|
fmt.Printf("Verified %s is an owner of %s\n", *user.Login, c.Namespace)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ids, err := listOrganizations(*user.Login, organizations)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to list organizations for %s\n%w", *user.Login, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if namespace.IsOwner(n.Owners, namespace.ByOrganizations(ids)) {
|
||||||
|
fmt.Printf("Verified %s is an owner of %s\n", *user.Login, c.Namespace)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolkit.FailedErrorf("%s is not an owner of %s", *user.Login, c.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
User string
|
||||||
|
Owner string
|
||||||
|
Repository string
|
||||||
|
Namespace string
|
||||||
|
AddIfMissing bool
|
||||||
|
blockedNamespaces []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c = config{AddIfMissing: false}
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.User, ok = tk.GetInput("user")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("user must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Owner, ok = tk.GetInput("owner")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("owner must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Repository, ok = tk.GetInput("repository")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("repository must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Namespace, ok = tk.GetInput("namespace")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("namespace must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.blockedNamespaces, ok = tk.GetInputList("blocked_namespaces")
|
||||||
|
if !ok {
|
||||||
|
defaultBlockedNamespaces := []string{"cncf", "buildpacks", "cnb", "buildpacksio", "buildpack"}
|
||||||
|
c.blockedNamespaces = defaultBlockedNamespaces
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := tk.GetInput("add-if-missing"); ok {
|
||||||
|
if t, err := strconv.ParseBool(s); err == nil {
|
||||||
|
c.AddIfMissing = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNamespace(tk toolkit.Toolkit, c config, user github.User, repositories services.RepositoriesService, strategy retry.Strategy) (namespace.Namespace, error) {
|
||||||
|
file := namespace.Path(c.Namespace)
|
||||||
|
|
||||||
|
for a := retry.Start(strategy, nil); a.Next(); {
|
||||||
|
content, _, resp, err := repositories.GetContents(context.Background(), c.Owner, c.Repository, file, nil)
|
||||||
|
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||||
|
if !c.AddIfMissing {
|
||||||
|
return namespace.Namespace{}, toolkit.FailedErrorf("invalid namespace %s", c.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(namespace.Namespace{Owners: []namespace.Owner{{ID: *user.ID, Type: namespace.UserType}}})
|
||||||
|
if err != nil {
|
||||||
|
return namespace.Namespace{}, toolkit.FailedErrorf("unable to decode namespace\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tk.Debugf("creating new namespace: %s\n%s", file, b)
|
||||||
|
if _, resp, err := repositories.CreateFile(context.Background(), c.Owner, c.Repository, file, &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String(fmt.Sprintf("New Namespace: %s", c.Namespace)),
|
||||||
|
Content: b,
|
||||||
|
}); resp != nil && resp.StatusCode == http.StatusConflict {
|
||||||
|
tk.Warningf("retrying namespace update after conflict: %s", file)
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
tk.Errorf("unable to create namespace: %s", file)
|
||||||
|
return namespace.Namespace{}, toolkit.FailedErrorf("unable to create namespace\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("New Namespace: %s\n", c.Namespace)
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return namespace.Namespace{}, toolkit.FailedErrorf("unable to read namespace %s\n%w", c.Namespace, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := content.GetContent()
|
||||||
|
if err != nil {
|
||||||
|
return namespace.Namespace{}, toolkit.FailedErrorf("unable to get namespace content\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var n namespace.Namespace
|
||||||
|
if err := json.Unmarshal([]byte(s), &n); err != nil {
|
||||||
|
return namespace.Namespace{}, toolkit.FailedErrorf("unable to unmarshal owners\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespace.Namespace{}, toolkit.FailedError("timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
func listOrganizations(user string, organizations services.OrganizationsService) ([]int64, error) {
|
||||||
|
var ids []int64
|
||||||
|
|
||||||
|
opt := &github.ListOptions{PerPage: 100}
|
||||||
|
|
||||||
|
for {
|
||||||
|
orgs, rsp, err := organizations.List(context.Background(), user, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range orgs {
|
||||||
|
ids = append(ids, *o.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsp.NextPage == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
opt.Page = rsp.NextPage
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBlockedNamespaces(c config) bool {
|
||||||
|
for _, name := range c.blockedNamespaces {
|
||||||
|
if c.Namespace == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package owner_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/namespace"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
owner "github.com/buildpacks/github-actions/registry/verify-namespace-owner"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVerifyNamespaceOwner(t *testing.T) {
|
||||||
|
spec.Run(t, "verify-namespace-owner", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
ExpectWithOffset = NewWithT(t).ExpectWithOffset
|
||||||
|
|
||||||
|
o = &services.MockOrganizationsService{}
|
||||||
|
r = &services.MockRepositoriesService{}
|
||||||
|
rOpts *github.RepositoryContentGetOptions
|
||||||
|
s = retry.LimitCount(2, retry.Regular{Min: 2})
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
asJSONString := func(v interface{}) string {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("Debugf", mock.Anything, mock.Anything, mock.Anything).Return()
|
||||||
|
tk.On("GetInput", "owner").Return("test-owner", true)
|
||||||
|
tk.On("GetInput", "repository").Return("test-repository", true)
|
||||||
|
tk.On("GetInput", "namespace").Return("test-namespace", true)
|
||||||
|
tk.On("GetInput", "user").
|
||||||
|
Return(asJSONString(github.User{ID: github.Int64(1), Login: github.String("test-user")}), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
context("unknown namespace", func() {
|
||||||
|
it.Before(func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("v1", "test-namespace.json"), rOpts).
|
||||||
|
Return(nil, nil, &github.Response{Response: &http.Response{StatusCode: http.StatusNotFound}}, nil).
|
||||||
|
Once()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if add-if-missing is false", func() {
|
||||||
|
tk.On("GetInput", "add-if-missing").Return("", false)
|
||||||
|
tk.On("GetInputList", "blocked_namespaces").Return([]string{"test-owner"}, false)
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).
|
||||||
|
To(MatchError("::error ::invalid namespace test-namespace"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if namespace is blocked", func() {
|
||||||
|
tk.On("GetInput", "add-if-missing").Return("", false)
|
||||||
|
tk.On("GetInputList", "blocked_namespaces").Return([]string{"test-owner"}, false)
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).
|
||||||
|
To(MatchError("::error ::invalid namespace test-namespace"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("succeeds if add-if-missing is true", func() {
|
||||||
|
tk.On("GetInput", "add-if-missing").Return("true", true)
|
||||||
|
tk.On("GetInputList", "blocked_namespaces").Return([]string{"true"}, true)
|
||||||
|
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("v1", "test-namespace.json"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(namespace.Namespace{Owners: []namespace.Owner{{ID: 1, Type: namespace.UserType}}})),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
c := asJSONString(namespace.Namespace{Owners: []namespace.Owner{{ID: 1, Type: namespace.UserType}}})
|
||||||
|
|
||||||
|
r.On("CreateFile", mock.Anything, "test-owner", "test-repository", filepath.Join("v1", "test-namespace.json"), &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String("New Namespace: test-namespace"),
|
||||||
|
Content: []byte(c),
|
||||||
|
}).Return(&github.RepositoryContentResponse{
|
||||||
|
Content: &github.RepositoryContent{Content: github.String(c)},
|
||||||
|
}, nil, nil)
|
||||||
|
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
context("user-owned namespace", func() {
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "add-if-missing").Return("", false)
|
||||||
|
tk.On("GetInputList", "blocked_namespaces").Return([]string{"test-owner"}, false)
|
||||||
|
o.On("List", mock.Anything, "test-user", mock.Anything).
|
||||||
|
Return([]*github.Organization{}, &github.Response{}, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if user does not own", func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("v1", "test-namespace.json"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(namespace.Namespace{Owners: []namespace.Owner{{ID: 2, Type: namespace.UserType}}})),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).
|
||||||
|
To(MatchError("::error ::test-user is not an owner of test-namespace"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("succeeds if user does own", func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("v1", "test-namespace.json"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(namespace.Namespace{Owners: []namespace.Owner{{ID: 1, Type: namespace.UserType}}})),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
context("organization-owned namespace", func() {
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "add-if-missing").Return("", false)
|
||||||
|
tk.On("GetInputList", "blocked_namespaces").Return([]string{""}, false)
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("v1", "test-namespace.json"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(namespace.Namespace{Owners: []namespace.Owner{{ID: 1, Type: namespace.OrganizationType}}})),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if user does not own", func() {
|
||||||
|
o.On("List", mock.Anything, "test-user", mock.Anything).
|
||||||
|
Return([]*github.Organization{}, &github.Response{}, nil)
|
||||||
|
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).
|
||||||
|
To(MatchError("::error ::test-user is not an owner of test-namespace"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("succeeds if user does own", func() {
|
||||||
|
o.On("List", mock.Anything, "test-user", mock.Anything).
|
||||||
|
Return([]*github.Organization{{ID: github.Int64(1)}}, &github.Response{}, nil)
|
||||||
|
|
||||||
|
Expect(owner.VerifyNamespaceOwner(tk, o, r, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
entry "github.com/buildpacks/github-actions/registry/yank-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tk := &toolkit.DefaultToolkit{}
|
||||||
|
|
||||||
|
t, ok := tk.GetInput("token")
|
||||||
|
if !ok {
|
||||||
|
fmt.Println(toolkit.FailedError("token must be specified"))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
gh := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: t})))
|
||||||
|
|
||||||
|
strategy := retry.LimitTime(2*time.Minute,
|
||||||
|
retry.Exponential{
|
||||||
|
Initial: time.Second,
|
||||||
|
Jitter: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := entry.YankEntry(tk, gh.Repositories, strategy); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
func YankEntry(tk toolkit.Toolkit, repositories services.RepositoriesService, strategy retry.Strategy) error {
|
||||||
|
c, err := parseConfig(tk)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file := index.Path(c.Namespace, c.Name)
|
||||||
|
|
||||||
|
for a := retry.Start(strategy, nil); a.Next(); {
|
||||||
|
content, _, resp, err := repositories.GetContents(context.Background(), c.Owner, c.Repository, file, nil)
|
||||||
|
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||||
|
return toolkit.FailedErrorf("index %s does not exist", c.Name)
|
||||||
|
} else if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to read index %s\n%w", c.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := content.GetContent()
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to get index content\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := index.UnmarshalEntries(s)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to unmarshal entries\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
i := indexOf(entries, c.Namespace, c.Version)
|
||||||
|
if i == nil {
|
||||||
|
return toolkit.FailedErrorf("index %s already does not have namespace %s and version %s", c.Name, c.Namespace, c.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries[*i].Yanked = true
|
||||||
|
|
||||||
|
s, err = index.MarshalEntries(entries)
|
||||||
|
if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to marshal entries\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, resp, err := repositories.CreateFile(context.Background(), c.Owner, c.Repository, file, &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String(fmt.Sprintf("YANK %s/%s@%s", c.Namespace, c.Name, c.Version)),
|
||||||
|
SHA: content.SHA,
|
||||||
|
Content: []byte(s),
|
||||||
|
}); resp != nil && resp.StatusCode == http.StatusConflict {
|
||||||
|
tk.Warning("retrying index update after conflict")
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return toolkit.FailedErrorf("unable to create index\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Yanked %s/%s@%s\n", c.Namespace, c.Name, c.Version)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolkit.FailedError("timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Owner string
|
||||||
|
Repository string
|
||||||
|
Namespace string
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(tk toolkit.Toolkit) (config, error) {
|
||||||
|
var (
|
||||||
|
c config
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
c.Owner, ok = tk.GetInput("owner")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("owner must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Repository, ok = tk.GetInput("repository")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("repository must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Namespace, ok = tk.GetInput("namespace")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("namespace must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Name, ok = tk.GetInput("name")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("name must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Version, ok = tk.GetInput("version")
|
||||||
|
if !ok {
|
||||||
|
return config{}, toolkit.FailedError("version must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func indexOf(entries []index.Entry, namespace string, version string) *int {
|
||||||
|
for i, e := range entries {
|
||||||
|
if e.Namespace == namespace && e.Version == version {
|
||||||
|
return &i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2020 the original author or 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
|
||||||
|
*
|
||||||
|
* https://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package entry_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v39/github"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/sclevine/spec"
|
||||||
|
"github.com/sclevine/spec/report"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"gopkg.in/retry.v1"
|
||||||
|
|
||||||
|
"github.com/buildpacks/github-actions/internal/toolkit"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/index"
|
||||||
|
"github.com/buildpacks/github-actions/registry/internal/services"
|
||||||
|
entry "github.com/buildpacks/github-actions/registry/yank-entry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestYankEntry(t *testing.T) {
|
||||||
|
spec.Run(t, "yank-entry", func(t *testing.T, context spec.G, it spec.S) {
|
||||||
|
var (
|
||||||
|
Expect = NewWithT(t).Expect
|
||||||
|
ExpectWithOffset = NewWithT(t).ExpectWithOffset
|
||||||
|
|
||||||
|
r = &services.MockRepositoriesService{}
|
||||||
|
rOpts *github.RepositoryContentGetOptions
|
||||||
|
s = retry.LimitCount(2, retry.Regular{Min: 2})
|
||||||
|
tk = &toolkit.MockToolkit{}
|
||||||
|
)
|
||||||
|
|
||||||
|
asJSONString := func(v interface{}) string {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
ExpectWithOffset(1, err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Before(func() {
|
||||||
|
tk.On("GetInput", "owner").Return("test-owner", true)
|
||||||
|
tk.On("GetInput", "repository").Return("test-repository", true)
|
||||||
|
tk.On("GetInput", "namespace").Return("test-namespace", true)
|
||||||
|
tk.On("GetInput", "name").Return("test-name", true)
|
||||||
|
tk.On("GetInput", "version").Return("test-version", true)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
context("index does not exist", func() {
|
||||||
|
it.Before(func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), rOpts).
|
||||||
|
Return(nil, nil, &github.Response{Response: &http.Response{StatusCode: http.StatusNotFound}}, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("fails if index does not exist", func() {
|
||||||
|
Expect(entry.YankEntry(tk, r, s)).
|
||||||
|
To(MatchError("::error ::index test-name does not exist"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
context("index does exist", func() {
|
||||||
|
|
||||||
|
it("fails if version does not exist", func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "another-version",
|
||||||
|
Address: "test-address",
|
||||||
|
})),
|
||||||
|
SHA: github.String("test-sha"),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.YankEntry(tk, r, s)).
|
||||||
|
To(MatchError("::error ::index test-name already does not have namespace test-namespace and version test-version"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds entry to index", func() {
|
||||||
|
r.On("GetContents", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), rOpts).
|
||||||
|
Return(&github.RepositoryContent{
|
||||||
|
Content: github.String(asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
})),
|
||||||
|
SHA: github.String("test-sha"),
|
||||||
|
}, nil, nil, nil)
|
||||||
|
|
||||||
|
r.On("CreateFile", mock.Anything, "test-owner", "test-repository", filepath.Join("te", "st", "test-namespace_test-name"), &github.RepositoryContentFileOptions{
|
||||||
|
Author: &github.CommitAuthor{
|
||||||
|
Name: github.String("buildpacks-bot"),
|
||||||
|
Email: github.String("cncf-buildpacks-maintainers@lists.cncf.io"),
|
||||||
|
},
|
||||||
|
Message: github.String("YANK test-namespace/test-name@test-version"),
|
||||||
|
Content: []byte(fmt.Sprintf("%s\n",
|
||||||
|
asJSONString(index.Entry{
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
Name: "test-name",
|
||||||
|
Version: "test-version",
|
||||||
|
Address: "test-address",
|
||||||
|
Yanked: true,
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
SHA: github.String("test-sha"),
|
||||||
|
}).
|
||||||
|
Return(nil, nil, nil)
|
||||||
|
|
||||||
|
Expect(entry.YankEntry(tk, r, s)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}, spec.Report(report.Terminal{}))
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
name: 'Setup pack CLI'
|
||||||
|
description: 'Install the Cloud Native Buildpacks pack CLI and add it to $PATH'
|
||||||
|
author: 'Cloud Native Buildpacks'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
pack-version:
|
||||||
|
description: 'The version of pack to install'
|
||||||
|
required: false
|
||||||
|
default: '0.38.2'
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Install pack CLI
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
mkdir -p "${HOME}"/bin
|
||||||
|
echo "PATH=${HOME}/bin:${PATH}" >> "${GITHUB_ENV}"
|
||||||
|
|
||||||
|
PLATFORM="linux"
|
||||||
|
if [ $(arch) = "aarch64" ]; then
|
||||||
|
PLATFORM="linux-arm64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PACK_VERSION=${{ inputs.pack-version }}
|
||||||
|
echo "Installing pack ${PACK_VERSION}"
|
||||||
|
curl \
|
||||||
|
--show-error \
|
||||||
|
--silent \
|
||||||
|
--location \
|
||||||
|
--fail \
|
||||||
|
--retry 3 \
|
||||||
|
--connect-timeout 5 \
|
||||||
|
--max-time 60 \
|
||||||
|
"https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-${PLATFORM}.tgz" \
|
||||||
|
| tar -C "${HOME}/bin" -xz pack
|
|
@ -0,0 +1,66 @@
|
||||||
|
name: 'Setup tools'
|
||||||
|
description: 'Install the tools crane and yq, and add them to $PATH'
|
||||||
|
author: 'Cloud Native Buildpacks'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
crane-version:
|
||||||
|
description: 'The version of crane to install'
|
||||||
|
required: false
|
||||||
|
default: '0.19.1'
|
||||||
|
yj-version:
|
||||||
|
description: 'The version of yj to install'
|
||||||
|
required: false
|
||||||
|
default: '5.1.0'
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Install additional buildpack management tools
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
mkdir -p "${HOME}"/bin
|
||||||
|
echo "PATH=${HOME}/bin:${PATH}" >> "${GITHUB_ENV}"
|
||||||
|
|
||||||
|
CRANE_PLATFORM="Linux_x86_64"
|
||||||
|
if [ $(arch) = "aarch64" ]; then
|
||||||
|
CRANE_PLATFORM="Linux_arm64"
|
||||||
|
fi
|
||||||
|
CRANE_VERSION=${{ inputs.crane-version }}
|
||||||
|
echo "Installing crane ${CRANE_VERSION}"
|
||||||
|
curl \
|
||||||
|
--show-error \
|
||||||
|
--silent \
|
||||||
|
--location \
|
||||||
|
--fail \
|
||||||
|
--retry 3 \
|
||||||
|
--connect-timeout 5 \
|
||||||
|
--max-time 60 \
|
||||||
|
"https://github.com/google/go-containerregistry/releases/download/v${CRANE_VERSION}/go-containerregistry_${CRANE_PLATFORM}.tar.gz" \
|
||||||
|
| tar -C "${HOME}/bin" -xz crane
|
||||||
|
|
||||||
|
YJ_VERSION=${{ inputs.yj-version }}
|
||||||
|
echo "Installing yj ${YJ_VERSION}"
|
||||||
|
YJ_DOWNLOAD_FILENAME="yj-linux"
|
||||||
|
if [[ "${YJ_VERSION}" < "5.1.0" ]]; then
|
||||||
|
YJ_PLATFORM=""
|
||||||
|
else
|
||||||
|
YJ_PLATFORM="-amd64"
|
||||||
|
fi
|
||||||
|
if [ $(arch) = "aarch64" ]; then
|
||||||
|
YJ_PLATFORM="-arm64"
|
||||||
|
fi
|
||||||
|
curl \
|
||||||
|
--show-error \
|
||||||
|
--silent \
|
||||||
|
--location \
|
||||||
|
--fail \
|
||||||
|
--retry 3 \
|
||||||
|
--connect-timeout 5 \
|
||||||
|
--max-time 60 \
|
||||||
|
--output "${HOME}/bin/yj" \
|
||||||
|
"https://github.com/sclevine/yj/releases/download/v${YJ_VERSION}/${YJ_DOWNLOAD_FILENAME}${YJ_PLATFORM}"
|
||||||
|
chmod +x "${HOME}"/bin/yj
|
Loading…
Reference in New Issue