Compare commits
	
		
			612 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 16ebe778df | ||
|   | 646a62b4f2 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d92ab1347f | ||
|   | 4f7cdeb0f0 | ||
|   | ad3cd774a4 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 3efbc13366 | ||
|   | 2dbe91db48 | ||
|   | 7de3854c4c | ||
|   | 175aa53a3f | ||
|   | 806a2a461f | ||
|   | a8d35412fb | ||
|   | 1672e74297 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a04f51d3b4 | ||
|   | 5176d81f87 | ||
|   | ec10ae8f96 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 597e8fc414 | ||
|   | e050dfa622 | ||
|   | d1fcdb6ee0 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a6067b9a1a | ||
|   | 1ca370b3a9 | ||
|   | 2c95ebed5c | ||
|   | d189d0ef33 | ||
|   | a254f8ca60 | ||
|   | 94dae62c78 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 267a69d6cc | ||
|   | f23fb2a7cb | ||
|   | ef76d100ee | ||
|   | 522345f555 | ||
|   | 1a162644f9 | ||
|   | 9eea548195 | ||
|   | 11c2faaa9e | ||
|   | de2365af33 | ||
|   | bca5082da7 | ||
|   | e7aab408d9 | ||
|   | 63eb7590c6 | ||
|   | 53ec48606f | ||
|   | fe9d9f1d0c | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ad37ba1ad0 | ||
|   | aabbd3f4d7 | ||
|   | 9c7c277413 | ||
|   | 987902144c | ||
|   | 709dde20a7 | ||
|   | ec2d640ea6 | ||
|   | 3dc0757c66 | ||
|   | dcb0699155 | ||
|   | a3c06e8698 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | e75138d857 | ||
|   | 9552610e81 | ||
|   | 99c83871c1 | ||
|   | af64c4e18f | ||
|   | 6fdff4fb09 | ||
|   | 9e59c61762 | ||
|   | 49351df2b7 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 723ff6ffad | ||
|   | 15560696de | ||
|   | 57e1d34ac3 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 309982ebc9 | ||
|   | 9476c25b2a | ||
|   | 97be5a4928 | ||
|   | 9cac6c8ea0 | ||
|   | 31159d49c0 | ||
|   | 07e1c3e148 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | f7febd621d | ||
|   | f6010ea701 | ||
|   | c0a6b9680f | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0dfe9c3d41 | ||
|   | 94f8f8c2ee | ||
|   | 22f4433c58 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6721c56015 | ||
|   | 4367da978b | ||
|   | 0883ebe52d | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 76e5c2d6ea | ||
|   | 29d67824d8 | ||
|   | c382f710d3 | ||
|   | 5a5b70d974 | ||
|   | dc24cf9e25 | ||
|   | 667cb22c52 | ||
|   | d880b1964b | ||
|   | e51051ad0b | ||
|   | 86c2bd0031 | ||
|   | 268d2b1611 | ||
|   | 2b8dc7f529 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 840c12be17 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 26368743c0 | ||
|   | cfed4e995e | ||
|   | dca03ca8fd | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | e030091ff4 | ||
|   | 84354d3b32 | ||
|   | de5408fe94 | ||
|   | cfc1555281 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | f6a172d30e | ||
|   | ca052bb54a | ||
|   | 025c2051f3 | ||
|   | 12076d2fb1 | ||
|   | ef6cba3353 | ||
|   | 4c16cf906a | ||
|   | a3118a86c8 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c86eb8b0f7 | ||
|   | 2a53c6ccda | ||
|   | ccef1f210d | ||
|   | 79117b6ea5 | ||
|   | df19a799eb | ||
|   | 0e2ab16cd2 | ||
|   | 54d0f58d64 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 563a2f55e4 | ||
|   | 6003d3266a | ||
|   | e1e22cdde8 | ||
|   | fc15b64049 | ||
|   | 6c58ea3670 | ||
|   | 729f7f4926 | ||
|   | 99d83235bc | ||
|   | 1d5307d7af | ||
|   | cf8d130912 | ||
|   | 8804d8e2ac | ||
|   | 1984549052 | ||
|   | 5bc9e2e9b9 | ||
|   | eb539f44b1 | ||
|   | b6ff9e5753 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 929fba6cce | ||
|   | 7f1f43ba33 | ||
|   | 40d6a900e0 | ||
|   | d56be63626 | ||
|   | eb3cfeaf00 | ||
|   | d0fc12d8a4 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 68615d5b67 | ||
|   | c3b570184c | ||
|   | 7e6f77677b | ||
|   | 2ce6beaad4 | ||
|   | 4c8d1e6826 | ||
|   | b0312962ef | ||
|   | 96acf63e4c | ||
|   | f8bc7f4600 | ||
|   | c2064be02c | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 4f02f34098 | ||
|   | 090ca155fc | ||
|   | ec4854f780 | ||
|   | 2cdde995de | ||
|   | 008747aa03 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 1580753126 | ||
|   | 2a7db1d68a | ||
|   | 35e7dd5921 | ||
|   | af5a7ed5ba | ||
|   | 2a85189a6c | ||
|   | 6c2079483e | ||
|   | afdf0c0a67 | ||
|   | 00ae31ab6e | ||
|   | 701942b6e5 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 90e54d0b1d | ||
|   | 831ca179d3 | ||
|   | 6bd0e5492f | ||
|   | b3eddbb94c | ||
|   | ffd798c1f1 | ||
|   | 62d8db0960 | ||
|   | 8ab81cb898 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d47e7c357d | ||
|   | 4976231911 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d236adc992 | ||
|   | 94d76d3bc1 | ||
|   | 2b28f2a854 | ||
|   | 9f6f8c940b | ||
|   | 8411d080ee | ||
|   | 4a13e500e5 | ||
|   | 7416668686 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | b4f76a5dc6 | ||
|   | b7feb766fa | ||
|   | fae8018297 | ||
|   | b625868b13 | ||
|   | 5193ef1da6 | ||
|   | d3afd779e4 | ||
|   | 7a786bb2b9 | ||
|   | c66ae3adcf | ||
|   | 248131c7bf | ||
|   | b425c4cd5a | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9834ce5b4d | ||
|   | fdf7f43ecf | ||
|   | e3a4c332fb | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c48d200483 | ||
|   | 8d2cf95286 | ||
|   | 3c7915695f | ||
|   | 0a283b683f | ||
|   | c544b50d70 | ||
|   | dd31262fa7 | ||
|   | 5f01267817 | ||
|   | 0f847266c3 | ||
|   | ea8499618b | ||
|   | 4c1b68d83a | ||
|   | 5909c5bffe | ||
|   | 285730d174 | ||
|   | 4bbe0177ef | ||
|   | cc4d1d4d5f | ||
|   | e7d3750abc | ||
|   | 4556201a14 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9fa62cfa91 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 8026f009fc | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6b35a7a7f1 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c6e64b478a | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | e2505c6383 | ||
|   | 0565240e2d | ||
|   | 3ab07f8801 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | b9e7e4daec | ||
|   | 04d1a3b049 | ||
|   | 1a4d1a13fb | ||
|   | 675965c0e1 | ||
|   | 58ee34cb6b | ||
|   | c97c4060bd | ||
|   | 47d5369e0b | ||
|   | 8895c7468f | ||
|   | 59ba712c53 | ||
|   | 0c20fff10d | ||
|   | 0a97817b6a | ||
|   | ec39ef320c | ||
|   | f46044b799 | ||
|   | 4e4ee680f6 | ||
|   | e86cf554b6 | ||
|   | daa0106f78 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ce51e905a6 | ||
|   | 1fde16337d | ||
|   | ae311c520f | ||
|   | 9311bf5263 | ||
|   | b1654941ef | ||
|   | 12a9f89349 | ||
|   | 2036a561be | ||
|   | b1d46f11a2 | ||
|   | e5b2fc7017 | ||
|   | 24216ba114 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | eb33afda71 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9407ba1305 | ||
|   | 429cdb70ad | ||
|   | 74a34eff3a | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6787bde0a6 | ||
|   | 56932deb0a | ||
|   | 0681013357 | ||
|   | be4bf1099e | ||
|   | 9ec154c4b6 | ||
|   | 380260b6c7 | ||
|   | ac790be09a | ||
|   | dc0a85b056 | ||
|   | aca01f02d5 | ||
|   | 4b0752a2b1 | ||
|   | be06a9da57 | ||
|   | 19184b90ca | ||
|   | 57e90a56ab | ||
|   | 4fad532b9f | ||
|   | 413aee355f | ||
|   | f05b754b57 | ||
|   | 2f3765570b | ||
|   | 68d0dc20df | ||
|   | 1fd7f72e60 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ea907fb0a4 | ||
|   | 2eb1c1961a | ||
|   | 27376fe2fc | ||
|   | c9330004c2 | ||
|   | dac08d41ad | ||
|   | 44ea916f6c | ||
|   | 0167eef179 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 91bf8bfc4d | ||
|   | a799b4decf | ||
|   | 87480bdf69 | ||
|   | f9efed53cc | ||
|   | 3580b78e04 | ||
|   | 91df6b874e | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ea92b18afb | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6f91eb31f7 | ||
|   | eafaea8d0f | ||
|   | ddd2a92197 | ||
|   | a54198e85a | ||
|   | 7e3a79c50d | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 4a730ce64b | ||
|   | 817ed59f97 | ||
|   | a3646c08f8 | ||
|   | 5c3465b033 | ||
|   | e9c0697e5b | ||
|   | e090350180 | ||
|   | f2a1d5e99d | ||
|   | 81f5252b54 | ||
|   | b3435979d1 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 80def7c74e | ||
|   | 35434f557a | ||
|   | d63c96254b | ||
|   | 21fe05ff59 | ||
|   | 097a3e23ac | ||
|   | d8823bfaed | ||
|   | 3a3620ed49 | ||
|   | 8082ebc6ea | ||
|   | a3ae207c14 | ||
|   | 4858a31f84 | ||
|   | d10433366f | ||
|   | ee5cabd9e3 | ||
|   | 7944f9a25b | ||
|   | c088e12d82 | ||
|   | e941dc0149 | ||
|   | 0d6f3e8936 | ||
|   | c779d8500d | ||
|   | b651cf69a6 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0db6129a57 | ||
|   | 70cc701b9c | ||
|   | af7537dc3e | ||
|   | 2d8166c4b9 | ||
|   | 6a8fbf0dbc | ||
|   | f74fd039f3 | ||
|   | 695ee8547d | ||
|   | fd7264830a | ||
|   | 6842956e83 | ||
|   | 9d1b8fa4e2 | ||
|   | 17c742ea85 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 916f6873ae | ||
|   | a3f7a443f9 | ||
|   | 05e89e68aa | ||
|   | d16cc0b66f | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 306a0a9f50 | ||
|   | 55a3485913 | ||
|   | 71e9aaaf29 | ||
|   | 3b5e8027fc | ||
|   | 02d3266a89 | ||
|   | f403dafe18 | ||
|   | 1104d47137 | ||
|   | 838bf90c88 | ||
|   | 337a09d182 | ||
|   | 37abcedcc1 | ||
|   | 67109bc4b2 | ||
|   | d1b0eb0a29 | ||
|   | a0635fe7cd | ||
|   | f834265449 | ||
|   | 0191543e0b | ||
|   | 2a16835223 | ||
|   | 9b96801525 | ||
|   | 6afac853c9 | ||
|   | 3bfdd83cd7 | ||
|   | 316d5eb8b3 | ||
|   | 1d910c8aa2 | ||
|   | f9ccca010f | ||
|   | c40bf0fdf6 | ||
|   | 223ed1ebd4 | ||
|   | fdafae777b | ||
|   | 0cb700ffba | ||
|   | ee7989df81 | ||
|   | 74f883a069 | ||
|   | 0149503e26 | ||
|   | 26ce4f3617 | ||
|   | ed2672fc33 | ||
|   | 472ccddef1 | ||
|   | d235d2d5ea | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 2f519a7883 | ||
|   | 4eb68bb2ac | ||
|   | b4755849f0 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ade1a6afe3 | ||
|   | 21d6059e1e | ||
|   | c2c50190db | ||
|   | a154a68da0 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 4ac90f5dca | ||
|   | 175d02bffe | ||
|   | 546378e7fb | ||
|   | ffe65bfc27 | ||
|   | d4c14fd006 | ||
|   | 6e95f19fb8 | ||
|   | 2a752d5a63 | ||
|   | c56af95754 | ||
|   | 75aaa63262 | ||
|   | f97d6e2850 | ||
|   | 47c00d78bf | ||
|   | 871b930e7a | ||
|   | 105bf59b00 | ||
|   | 48888e0b13 | ||
|   | 6b820ad47e | ||
|   | e1a10350ee | ||
|   | 0f5a7d48d5 | ||
|   | 6a6e8c7c14 | ||
|   | e189a1cb78 | ||
|   | 2cf0d6fbdc | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 3cde535b0c | ||
|   | 83a00fb5e6 | ||
|   | 1d5915004a | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 2e87529dad | ||
|   | e27bcee4eb | ||
|   | 71d260c49a | ||
|   | 965c6a410d | ||
|   | 08aa123a28 | ||
|   | 1527803881 | ||
|   | a49d9ab751 | ||
|   | cbb574ee73 | ||
|   | 8b56e74b48 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a5024d816a | ||
|   | 2235b57edd | ||
|   | 15b9e74b95 | ||
|   | 48daa618bd | ||
|   | c84f382811 | ||
|   | cd5d0b79ea | ||
|   | 30a32246ba | ||
|   | 1f19633b92 | ||
|   | 67af6dc1d3 | ||
|   | 988cb093f2 | ||
|   | 1cb9d22b93 | ||
|   | 5ffbca1432 | ||
|   | a8d76c070a | ||
|   | 12b1e419c2 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 2a60beff0d | ||
|   | 5268745b5f | ||
|   | a2a27346c0 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 05d9e522ae | ||
|   | 42863b1282 | ||
|   | c372f73edc | ||
|   | d17cab8f42 | ||
|   | 4c2810ab91 | ||
|   | 307a009589 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | f2c26aa560 | ||
|   | a806b8fe18 | ||
|   | ae74c4950a | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 80c878df65 | ||
|   | a571ccfa72 | ||
|   | 283625c36b | ||
|   | bb751c2095 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 8d9444d675 | ||
|   | c5e6528d5d | ||
|   | ceb414dc73 | ||
|   | dda70725ed | ||
|   | e551b19e49 | ||
|   | 3554377aa3 | ||
|   | a62bc1b22b | ||
|   | c2085839e1 | ||
|   | fcd91249e5 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0ebe720aed | ||
|   | 38b45804b5 | ||
|   | ba317382dc | ||
|   | 43721d2346 | ||
|   | 5ea21bf2ba | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 300b1bdff7 | ||
|   | 84580d7737 | ||
|   | a460b5e683 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9f1392c9bf | ||
|   | 9472e90210 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 5accc8e023 | ||
|   | f7a2a67b4c | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | b905f177bc | ||
|   | 0779722168 | ||
|   | fd75456293 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ada965aa7b | ||
|   | b5730d2471 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 839389a46c | ||
|   | 34c1caa1ce | ||
|   | 6ff230f13e | ||
|   | 75c825aabc | ||
|   | 5f7b938b8c | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 7ae34a20f3 | ||
|   | acb76cdd52 | ||
|   | 2d081a4fd5 | ||
|   | ac9327eae2 | ||
|   | 7c41daf2a5 | ||
|   | e115266953 | ||
|   | 50fa0058d9 | ||
|   | 309fb9180f | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | db68526220 | ||
|   | fe02965b48 | ||
|   | 5af8693d82 | ||
|   | 7f9d37fa54 | ||
|   | d7458455bb | ||
|   | 1ca185b339 | ||
|   | eebf87aed1 | ||
|   | d8b0ca6f0e | ||
|   | da767377fb | ||
|   | 8c76bb76c2 | ||
|   | b598b2a3bd | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | eb2857f4ca | ||
|   | f4cf574474 | ||
|   | 5c924147ba | ||
|   | 253376207c | ||
|   | 6f7a604875 | ||
|   | 604f033158 | ||
|   | 5645ea7274 | ||
|   | 1814d3dfb3 | ||
|   | fc5a732e0c | ||
|   | b1aeb1103e | ||
|   | e31f93ab9f | ||
|   | 9ed5823618 | ||
|   | 4222161e3e | ||
|   | 67ff4df4b7 | ||
|   | 91274a04da | ||
|   | ff329397c0 | ||
|   | 04841f2a72 | ||
|   | 049b7cab08 | ||
|   | 0a196c9deb | ||
|   | 94e0a28d6a | ||
|   | 5e11b373bf | ||
|   | 6f3b90dea1 | ||
|   | f71a68fb09 | ||
|   | 82446970f9 | ||
|   | 2cf7b61533 | ||
|   | 0732bea0f8 | ||
|   | 96daefdf52 | ||
|   | 9f46d13e71 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a8f79af565 | ||
|   | 04d5124fcb | ||
|   | 541dfa92f4 | ||
|   | 291bae5a41 | ||
|   | 91520dfd9f | ||
|   | a41d90ba13 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 22baeb6cdf | ||
|   | 6061a365d8 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9962be8aaf | ||
|   | 375f72aff6 | ||
|   | 8ba85ead00 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c6dca826de | ||
|   | 0c3d31c275 | ||
|   | 5681933133 | ||
|   | 821890eae4 | ||
|   | d0931a71a9 | ||
|   | 326ec1ede4 | ||
|   | b0c26e5619 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 3139e8d280 | ||
|   | a66e35b9cb | ||
|   | 6a98f97e24 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 26f24d6851 | ||
|   | b0b7751850 | ||
|   | c0b121fe44 | ||
|   | 09d66c261a | ||
|   | 24d162ecb4 | ||
|   | 6484a61448 | ||
|   | c40e0ee07a | ||
|   | e06a3af40d | ||
|   | 2e10e1984b | ||
|   | 1a60e0d706 | ||
|   | 3530a97c47 | ||
|   | 3c507bedc4 | ||
|   | 7c64fd5e10 | ||
|   | c65ff7ffb1 | ||
|   | 2a8d638779 | ||
|   | 900c06250b | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | b5e5b85e1b | ||
|   | cf25934f0f | ||
|   | 37831a7a20 | ||
|   | ad1d2e93be | ||
|   | e80adc3299 | ||
|   | 7594ecce5b | ||
|   | 1bc1040cae | ||
|   | fcaaa5e487 | ||
|   | 0987321e12 | ||
|   | 94827201d1 | ||
|   | 128f05c85a | ||
|   | a15ef4dd9f | ||
|   | c7dab97e55 | ||
|   | a1d2218d38 | ||
|   | 0b56a3c3b3 | ||
|   | ae29b67b96 | ||
|   | b44cfd9087 | ||
|   | a437a4518f | ||
|   | a7071c9d9a | ||
|   | 9199c83f6e | ||
|   | 93a9859764 | ||
|   | 9cbc67d577 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 07bca60c0f | ||
|   | cc01c17e75 | ||
|   | 90850ba046 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 915370c72f | ||
|   | f87b75314d | ||
|   | ecbc0634e4 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 06b9aae8bc | ||
|   | 779802e2ee | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | dd8c19ed49 | ||
|   | ad44023a93 | ||
|   | 57f367c048 | ||
|   | 74242a33cc | ||
|   | 2b2d125b68 | ||
|   | 5ac438e8df | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ae91a8353f | ||
|   | ca26f5b713 | ||
|   | c9589d1941 | ||
|   | 95f997534a | ||
|   | 655d1f6b37 | ||
|   | 6f4938aa75 | ||
|   | 18fa566857 | ||
|   | 11f0499b05 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | f3f2d78b13 | ||
|   | 5b3f377cdd | ||
|   | cc23ce7e44 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 64708ddf75 | ||
|   | 8e208dd401 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | bb77c476bd | ||
|   | 8e1d874ee2 | ||
|   | 3a090ce0da | ||
|   | 17822e4df4 | ||
|   | 5e92e6623e | ||
|   | 3ce082ae8d | ||
|   | d619a7ff00 | ||
|   | 19c07384dc | ||
|   | 4cef7b9d89 | ||
|   | 5676f00637 | ||
|   | c0c3e27be3 | ||
|   | c9b5cc4c4e | ||
|   | 6e53d9494f | ||
|   | 01f4a7369d | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 91bb504133 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c4742793d5 | ||
|   | e1b7f96249 | ||
|   | 5a4a26c0fc | ||
|   | 8891861577 | ||
|   | f6a733366a | ||
|   | eb4f14646c | ||
|   | 646552f0a1 | ||
|   | 2ec8f1d346 | ||
|   | 8f5c91aad9 | ||
|   | 6a12baa867 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | da940a9403 | ||
|   | 9cf6eb2b16 | ||
|   | 3c2d8e5269 | ||
|   | d693655c74 | ||
|   | bfea497a8e | ||
|   | 8ca2ca55d4 | ||
|   | 460e0e47f5 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | edb2e175f1 | ||
|   | 09f8407c80 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 614833a85f | ||
|   | 0ec1157bb5 | ||
|   | 22d49d64f5 | 
| @@ -1 +1,12 @@ | ||||
| node_modules | ||||
| /coverage | ||||
|  | ||||
| # Dependency directories | ||||
| node_modules/ | ||||
| jspm_packages/ | ||||
|  | ||||
| # yarn v2 | ||||
| .yarn/cache | ||||
| .yarn/unplugged | ||||
| .yarn/build-state.yml | ||||
| .yarn/install-state.gz | ||||
| .pnp.* | ||||
|   | ||||
							
								
								
									
										3
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| /dist/** | ||||
| /coverage/** | ||||
| /node_modules/** | ||||
							
								
								
									
										24
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| { | ||||
|   "env": { | ||||
|     "node": true, | ||||
|     "es6": true, | ||||
|     "jest": true | ||||
|   }, | ||||
|   "extends": [ | ||||
|     "eslint:recommended", | ||||
|     "plugin:@typescript-eslint/eslint-recommended", | ||||
|     "plugin:@typescript-eslint/recommended", | ||||
|     "plugin:jest/recommended", | ||||
|     "plugin:prettier/recommended" | ||||
|   ], | ||||
|   "parser": "@typescript-eslint/parser", | ||||
|   "parserOptions": { | ||||
|     "ecmaVersion": 2023, | ||||
|     "sourceType": "module" | ||||
|   }, | ||||
|   "plugins": [ | ||||
|     "@typescript-eslint", | ||||
|     "jest", | ||||
|     "prettier" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +1,4 @@ | ||||
| /.yarn/releases/** binary | ||||
| /.yarn/plugins/** binary | ||||
| /dist/** linguist-generated=true | ||||
| /lib/** linguist-generated=true | ||||
|   | ||||
							
								
								
									
										1
									
								
								.github/CODEOWNERS
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/CODEOWNERS
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | ||||
| *	@crazy-max | ||||
							
								
								
									
										3
									
								
								.github/CODE_OF_CONDUCT.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.github/CODE_OF_CONDUCT.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # Code of conduct | ||||
|  | ||||
| - [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines) | ||||
							
								
								
									
										35
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							| @@ -2,33 +2,20 @@ | ||||
|  | ||||
| Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. | ||||
|  | ||||
| Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE). | ||||
| Contributions to this project are [released](https://docs.github.com/en/github/site-policy/github-terms-of-service#6-contributions-under-repository-license) | ||||
| to the public under the [project's open source license](LICENSE). | ||||
|  | ||||
| ## Submitting a pull request | ||||
|  | ||||
| 1. [Fork](https://github.com/docker/build-push-action/fork) and clone the repository | ||||
| 2. Configure and install the dependencies: `yarn install` | ||||
| 3. Make sure the tests pass on your machine: `yarn run test` | ||||
| 4. Create a new branch: `git checkout -b my-branch-name` | ||||
| 5. Make your change, add tests, and make sure the tests still pass | ||||
| 6. Run pre-checkin: `yarn run pre-checkin` | ||||
| 7. Push to your fork and [submit a pull request](https://github.com/docker/build-push-action/compare) | ||||
| 8. Pat your self on the back and wait for your pull request to be reviewed and merged. | ||||
|  | ||||
| ## Container based developer flow | ||||
|  | ||||
| If you don't want to maintain a Node developer environment that fits this project you can use containerized commands instead of invoking yarn directly. | ||||
|  | ||||
| ``` | ||||
| # format code and build javascript artifacts | ||||
| docker buildx bake pre-checkin | ||||
|  | ||||
| # validate all code has correctly formatted and built | ||||
| docker buildx bake validate | ||||
|  | ||||
| # run tests | ||||
| docker buildx bake test | ||||
| ``` | ||||
| 3. Create a new branch: `git checkout -b my-branch-name` | ||||
| 4. Make your changes | ||||
| 5. Make sure the tests pass: `docker buildx bake test` | ||||
| 6. Format code and build javascript artifacts: `docker buildx bake pre-checkin` | ||||
| 7. Validate all code has correctly formatted and built: `docker buildx bake validate` | ||||
| 8. Push to your fork and [submit a pull request](https://github.com/docker/build-push-action/compare) | ||||
| 9. Pat your self on the back and wait for your pull request to be reviewed and merged. | ||||
|  | ||||
| Here are a few things you can do that will increase the likelihood of your pull request being accepted: | ||||
|  | ||||
| @@ -40,5 +27,5 @@ Here are a few things you can do that will increase the likelihood of your pull | ||||
| ## Resources | ||||
|  | ||||
| - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) | ||||
| - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) | ||||
| - [GitHub Help](https://help.github.com) | ||||
| - [Using Pull Requests](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) | ||||
| - [GitHub Help](https://docs.github.com/en) | ||||
|   | ||||
							
								
								
									
										101
									
								
								.github/ISSUE_TEMPLATE/bug.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								.github/ISSUE_TEMPLATE/bug.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| # https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema | ||||
| name: Bug Report | ||||
| description: Report a bug | ||||
| labels: | ||||
|   - status/triage | ||||
|  | ||||
| body: | ||||
|   - type: markdown | ||||
|     attributes: | ||||
|       value: | | ||||
|         Thank you for taking the time to report a bug! | ||||
|         If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com). | ||||
|         Before submitting a bug report, check out the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md). | ||||
|  | ||||
|   - type: checkboxes | ||||
|     attributes: | ||||
|       label: Contributing guidelines | ||||
|       description: > | ||||
|         Make sure you've read the contributing guidelines before proceeding. | ||||
|       options: | ||||
|         - label: I've read the [contributing guidelines](https://github.com/docker/build-push-action/blob/master/.github/CONTRIBUTING.md) and wholeheartedly agree | ||||
|           required: true | ||||
|  | ||||
|   - type: checkboxes | ||||
|     attributes: | ||||
|       label: "I've found a bug, and:" | ||||
|       description: | | ||||
|         Make sure that your request fulfills all of the following requirements. | ||||
|         If one requirement cannot be satisfied, explain in detail why. | ||||
|       options: | ||||
|         - label: The documentation does not mention anything about my problem | ||||
|         - label: There are no open or closed issues that are related to my problem | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: Description | ||||
|       description: > | ||||
|         Provide a brief description of the bug in 1-2 sentences. | ||||
|     validations: | ||||
|       required: true | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: Expected behaviour | ||||
|       description: > | ||||
|         Describe precisely what you'd expect to happen. | ||||
|     validations: | ||||
|       required: true | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: Actual behaviour | ||||
|       description: > | ||||
|         Describe precisely what is actually happening. | ||||
|     validations: | ||||
|       required: true | ||||
|  | ||||
|   - type: input | ||||
|     attributes: | ||||
|       label: Repository URL | ||||
|       description: > | ||||
|         Enter the URL of the repository where you are experiencing the | ||||
|         issue. If your repository is private, provide a link to a minimal | ||||
|         repository that reproduces the issue. | ||||
|  | ||||
|   - type: input | ||||
|     attributes: | ||||
|       label: Workflow run URL | ||||
|       description: > | ||||
|         Enter the URL of the GitHub Action workflow run, if public. | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: YAML workflow | ||||
|       description: | | ||||
|         Provide the YAML of the workflow that's causing the issue. | ||||
|         Make sure to remove any sensitive information. | ||||
|       render: yaml | ||||
|     validations: | ||||
|       required: true | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: Workflow logs | ||||
|       description: > | ||||
|         [Attach](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files) | ||||
|         the [log file of your workflow run](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs) | ||||
|         and make sure to remove any sensitive information. | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: BuildKit logs | ||||
|       description: > | ||||
|         If applicable, provide the [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs) | ||||
|       render: text | ||||
|  | ||||
|   - type: textarea | ||||
|     attributes: | ||||
|       label: Additional info | ||||
|       description: | | ||||
|         Provide any additional information that could be useful. | ||||
							
								
								
									
										37
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,37 +0,0 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Create a report to help us improve | ||||
| --- | ||||
|  | ||||
| ### Troubleshooting | ||||
|  | ||||
| Before sumbitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md). | ||||
|  | ||||
| ### Behaviour | ||||
|  | ||||
| #### Steps to reproduce this issue | ||||
|  | ||||
| 1. | ||||
| 2. | ||||
| 3. | ||||
|  | ||||
| #### Expected behaviour | ||||
|  | ||||
| > Tell us what should happen | ||||
|  | ||||
| #### Actual behaviour | ||||
|  | ||||
| > Tell us what happens instead | ||||
|  | ||||
| ### Configuration | ||||
|  | ||||
| * Repository URL (if public):  | ||||
| * Build URL (if public):  | ||||
|  | ||||
| ```yml | ||||
| # paste your YAML workflow file here and remove sensitive data | ||||
| ``` | ||||
|  | ||||
| ### Logs | ||||
|  | ||||
| > Download the [log file of your build](https://help.github.com/en/actions/configuring-and-managing-workflows/managing-a-workflow-run#downloading-logs) and [attach it](https://help.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue. | ||||
							
								
								
									
										9
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| # https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser | ||||
| blank_issues_enabled: true | ||||
| contact_links: | ||||
|   - name: Questions and Discussions | ||||
|     url: https://github.com/docker/build-push-action/discussions/new | ||||
|     about: Use Github Discussions to ask questions and/or open discussion topics. | ||||
|   - name: Documentation | ||||
|     url: https://docs.docker.com/build/ci/github-actions/ | ||||
|     about: Read the documentation. | ||||
							
								
								
									
										15
									
								
								.github/ISSUE_TEMPLATE/feature.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								.github/ISSUE_TEMPLATE/feature.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| # https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema | ||||
| name: Feature request | ||||
| description: Missing functionality? Come tell us about it! | ||||
| labels: | ||||
|   - kind/enhancement | ||||
|   - status/triage | ||||
|  | ||||
| body: | ||||
|   - type: textarea | ||||
|     id: description | ||||
|     attributes: | ||||
|       label: Description | ||||
|       description: What is the feature you want to see? | ||||
|     validations: | ||||
|       required: true | ||||
							
								
								
									
										12
									
								
								.github/SECURITY.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.github/SECURITY.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| # Reporting security issues | ||||
|  | ||||
| The project maintainers take security seriously. If you discover a security | ||||
| issue, please bring it to their attention right away! | ||||
|  | ||||
| **Please _DO NOT_ file a public issue**, instead send your report privately to | ||||
| [security@docker.com](mailto:security@docker.com). | ||||
|  | ||||
| Security reports are greatly appreciated, and we will publicly thank you for it. | ||||
| We also like to send gifts—if you'd like Docker swag, make sure to let | ||||
| us know. We currently do not offer a paid security bounty program, but are not | ||||
| ruling it out in the future. | ||||
							
								
								
									
										31
									
								
								.github/SUPPORT.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								.github/SUPPORT.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,31 +0,0 @@ | ||||
| # Support [](https://isitmaintained.com/project/docker/build-push-action) | ||||
|  | ||||
| First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md). | ||||
|  | ||||
| ## Reporting an issue | ||||
|  | ||||
| Please do a search in [open issues](https://github.com/docker/build-push-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed. | ||||
|  | ||||
| If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment. | ||||
|  | ||||
| :+1: - upvote | ||||
|  | ||||
| :-1: - downvote | ||||
|  | ||||
| If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below. | ||||
|  | ||||
| ## Writing good bug reports and feature requests | ||||
|  | ||||
| File a single issue per problem and feature request. | ||||
|  | ||||
| * Do not enumerate multiple bugs or feature requests in the same issue. | ||||
| * Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes. | ||||
|  | ||||
| The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix. | ||||
|  | ||||
| You are now ready to [create a new issue](https://github.com/docker/build-push-action/issues/new/choose)! | ||||
|  | ||||
| ## Closure policy | ||||
|  | ||||
| * Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines. | ||||
| * Issues that go a week without a response from original poster are subject to closure at our discretion. | ||||
							
								
								
									
										
											BIN
										
									
								
								.github/build-push-action.png
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								.github/build-push-action.png
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 19 KiB | 
							
								
								
									
										
											BIN
										
									
								
								.github/build-push-summary.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								.github/build-push-summary.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 81 KiB | 
							
								
								
									
										9
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							| @@ -5,14 +5,15 @@ updates: | ||||
|     schedule: | ||||
|       interval: "daily" | ||||
|     labels: | ||||
|       - ":game_die: dependencies" | ||||
|       - ":robot: bot" | ||||
|       - "dependencies" | ||||
|       - "bot" | ||||
|   - package-ecosystem: "npm" | ||||
|     directory: "/" | ||||
|     schedule: | ||||
|       interval: "daily" | ||||
|     versioning-strategy: "increase" | ||||
|     allow: | ||||
|       - dependency-type: "production" | ||||
|     labels: | ||||
|       - ":game_die: dependencies" | ||||
|       - ":robot: bot" | ||||
|       - "dependencies" | ||||
|       - "bot" | ||||
|   | ||||
							
								
								
									
										5
									
								
								.github/e2e/distribution/env
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.github/e2e/distribution/env
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| REGISTRY_FQDN=localhost:8080 | ||||
| REGISTRY_SLUG=localhost:8080/test-docker-action | ||||
|  | ||||
| DISTRIBUTION_HOST=localhost | ||||
| DISTRIBUTION_PORT=8080 | ||||
							
								
								
									
										13
									
								
								.github/e2e/distribution/install.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										13
									
								
								.github/e2e/distribution/install.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -eu | ||||
|  | ||||
| : "${DISTRIBUTION_VERSION:=2}" | ||||
| : "${DISTRIBUTION_HOST:=localhost}" | ||||
| : "${DISTRIBUTION_PORT:=8080}" | ||||
|  | ||||
| echo "::group::Starting registry:${DISTRIBUTION_VERSION}" | ||||
| ( | ||||
|   set -x | ||||
|   docker run -d --name registry -p "${DISTRIBUTION_PORT}:5000" "registry:${DISTRIBUTION_VERSION}" | ||||
| ) | ||||
| echo "::endgroup::" | ||||
							
								
								
									
										8
									
								
								.github/e2e/harbor/env
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.github/e2e/harbor/env
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| REGISTRY_FQDN=localhost:8081 | ||||
| REGISTRY_USER=admin | ||||
| REGISTRY_PASSWORD=Harbor12345 | ||||
| REGISTRY_SLUG=localhost:8081/test-docker-action/test-docker-action | ||||
|  | ||||
| HARBOR_HOST=localhost | ||||
| HARBOR_PORT=8081 | ||||
| HARBOR_PROJECT=test-docker-action | ||||
							
								
								
									
										79
									
								
								.github/e2e/harbor/install.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										79
									
								
								.github/e2e/harbor/install.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -eu | ||||
|  | ||||
| : "${HARBOR_VERSION:=v2.7.0}" | ||||
| : "${HARBOR_HOST:=localhost}" | ||||
| : "${HARBOR_PORT:=49154}" | ||||
| : "${REGISTRY_USER:=admin}" | ||||
| : "${REGISTRY_PASSWORD:=Harbor12345}" | ||||
|  | ||||
| : "${HARBOR_PROJECT:=test-docker-action}" | ||||
|  | ||||
| project_post_data() { | ||||
|   cat <<EOF | ||||
| { | ||||
|   "project_name": "$HARBOR_PROJECT", | ||||
|   "public": true | ||||
| } | ||||
| EOF | ||||
| } | ||||
|  | ||||
| export TERM=xterm | ||||
|  | ||||
| # download | ||||
| echo "::group::Downloading Harbor $HARBOR_VERSION" | ||||
| ( | ||||
|   cd /tmp | ||||
|   set -x | ||||
|   wget -q "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz" -O harbor-online-installer.tgz | ||||
|   tar xvf harbor-online-installer.tgz | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| # config | ||||
| echo "::group::Configuring Harbor" | ||||
| ( | ||||
|   cd /tmp/harbor | ||||
|   set -x | ||||
|   cp harbor.yml.tmpl harbor.yml | ||||
|   harborConfig="$(harborHost="$HARBOR_HOST" harborPort="$HARBOR_PORT" harborPwd="$REGISTRY_PASSWORD" yq --no-colors '.hostname = env(harborHost) | .http.port = env(harborPort) | .harbor_admin_password = env(harborPwd) | del(.https)' harbor.yml)" | ||||
|   tee harbor.yml <<<"$harborConfig" >/dev/null | ||||
|   yq --no-colors harbor.yml | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| # install and start | ||||
| echo "::group::Installing Harbor" | ||||
| ( | ||||
|   cd /tmp/harbor | ||||
|   set -x | ||||
|   ./install.sh | ||||
|   sleep 10 | ||||
|   netstat -aptn | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| # compose config | ||||
| echo "::group::Compose config" | ||||
| ( | ||||
|   cd /tmp/harbor | ||||
|   set -x | ||||
|   docker compose config | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| # create project | ||||
| echo "::group::Creating project" | ||||
| ( | ||||
|   set -x | ||||
|   curl --fail -v -k --max-time 10 -u "$REGISTRY_USER:$REGISTRY_PASSWORD" -X POST -H "Content-Type: application/json" -d "$(project_post_data)" "http://$HARBOR_HOST:$HARBOR_PORT/api/v2.0/projects" | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| # list projects | ||||
| echo "::group::List projects" | ||||
| ( | ||||
|   set -x | ||||
|   curl --fail -s -k --max-time 10 -u "$REGISTRY_USER:$REGISTRY_PASSWORD" -H "Content-Type: application/json" "http://$HARBOR_HOST:$HARBOR_PORT/api/v2.0/projects" | jq | ||||
| ) | ||||
| echo "::endgroup::" | ||||
							
								
								
									
										8
									
								
								.github/e2e/nexus/docker-compose.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.github/e2e/nexus/docker-compose.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| services: | ||||
|   nexus: | ||||
|     image: sonatype/nexus3:${NEXUS_VERSION:-latest} | ||||
|     volumes: | ||||
|       - "./data:/nexus-data" | ||||
|     ports: | ||||
|       - "8081:8081" | ||||
|       - "8082:8082" | ||||
							
								
								
									
										9
									
								
								.github/e2e/nexus/env
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.github/e2e/nexus/env
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| REGISTRY_FQDN=localhost:8082 | ||||
| REGISTRY_USER=admin | ||||
| REGISTRY_PASSWORD=Nexus12345 | ||||
| REGISTRY_SLUG=localhost:8082/test-docker-action | ||||
|  | ||||
| NEXUS_HOST=localhost | ||||
| NEXUS_PORT=8081 | ||||
| NEXUS_REGISTRY_PORT=8082 | ||||
| NEXUS_REPO=test-docker-action | ||||
							
								
								
									
										93
									
								
								.github/e2e/nexus/install.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										93
									
								
								.github/e2e/nexus/install.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -eu | ||||
|  | ||||
| SCRIPT_DIR=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) | ||||
|  | ||||
| : "${NEXUS_VERSION:=3.47.1}" | ||||
| : "${NEXUS_HOST:=localhost}" | ||||
| : "${NEXUS_PORT:=8081}" | ||||
| : "${NEXUS_REGISTRY_PORT:=8082}" | ||||
| : "${REGISTRY_USER:=admin}" | ||||
| : "${REGISTRY_PASSWORD:=Nexus12345}" | ||||
|  | ||||
| : "${NEXUS_REPO:=test-docker-action}" | ||||
|  | ||||
| createrepo_post_data() { | ||||
|   cat <<EOF | ||||
| { | ||||
|   "name": "${NEXUS_REPO}", | ||||
|   "online": true, | ||||
|   "storage": { | ||||
|     "blobStoreName": "default", | ||||
|     "strictContentTypeValidation": true, | ||||
|     "writePolicy": "ALLOW" | ||||
|   }, | ||||
|   "docker": { | ||||
|     "v1Enabled": false, | ||||
|     "forceBasicAuth": true, | ||||
|     "httpPort": ${NEXUS_REGISTRY_PORT}, | ||||
|     "httpsPort": null, | ||||
|     "subdomain": null | ||||
|   } | ||||
| } | ||||
| EOF | ||||
| } | ||||
|  | ||||
| export NEXUS_VERSION | ||||
|  | ||||
| mkdir -p /tmp/nexus/data | ||||
| chown 200:200 /tmp/nexus/data | ||||
| cp "${SCRIPT_DIR}/docker-compose.yml" /tmp/nexus/docker-compose.yml | ||||
|  | ||||
| echo "::group::Pulling Nexus $NEXUS_VERSION" | ||||
| ( | ||||
|   cd /tmp/nexus | ||||
|   set -x | ||||
|   docker compose pull | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| echo "::group::Compose config" | ||||
| ( | ||||
|   cd /tmp/nexus | ||||
|   set -x | ||||
|   docker compose config | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| echo "::group::Running Nexus" | ||||
| ( | ||||
|   cd /tmp/nexus | ||||
|   set -x | ||||
|   docker compose up -d | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| echo "::group::Running Nexus" | ||||
| ( | ||||
|   cd /tmp/nexus | ||||
|   set -x | ||||
|   docker compose up -d | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| echo "::group::Waiting for Nexus to be ready" | ||||
| until $(curl --output /dev/null --silent --head --fail "http://$NEXUS_HOST:$NEXUS_PORT"); do | ||||
|   printf '.' | ||||
|   sleep 5 | ||||
| done | ||||
| echo "::endgroup::" | ||||
|  | ||||
| echo "::group::Change user's password" | ||||
| ( | ||||
|   set -x | ||||
|   curl --fail -v -k --max-time 10 -u "$REGISTRY_USER:$(cat /tmp/nexus/data/admin.password)" -X PUT -H 'Content-Type: text/plain' -d "$REGISTRY_PASSWORD" "http://$NEXUS_HOST:$NEXUS_PORT/service/rest/v1/security/users/$REGISTRY_USER/change-password" | ||||
| ) | ||||
| echo "::endgroup::" | ||||
|  | ||||
| echo "::group::Create Docker repository" | ||||
| ( | ||||
|   set -x | ||||
|   curl --fail -v -k --max-time 10 -u "$REGISTRY_USER:$REGISTRY_PASSWORD" -X POST -H 'Content-Type: application/json' -d "$(createrepo_post_data)" "http://$NEXUS_HOST:$NEXUS_PORT/service/rest/v1/repositories/docker/hosted" | ||||
| ) | ||||
| echo "::endgroup::" | ||||
							
								
								
									
										130
									
								
								.github/workflows/.e2e-run.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								.github/workflows/.e2e-run.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| # reusable workflow | ||||
| name: .e2e-run | ||||
|  | ||||
| on: | ||||
|   workflow_call: | ||||
|     inputs: | ||||
|       id: | ||||
|         required: false | ||||
|         type: string | ||||
|       type: | ||||
|         required: true | ||||
|         type: string | ||||
|       name: | ||||
|         required: true | ||||
|         type: string | ||||
|       registry: | ||||
|         required: false | ||||
|         type: string | ||||
|       slug: | ||||
|         required: false | ||||
|         type: string | ||||
|       username_secret: | ||||
|         required: false | ||||
|         type: string | ||||
|       password_secret: | ||||
|         required: false | ||||
|         type: string | ||||
|  | ||||
| env: | ||||
|   HARBOR_VERSION: v2.7.0 | ||||
|   NEXUS_VERSION: 3.47.1 | ||||
|   DISTRIBUTION_VERSION: 2.8.1 | ||||
|  | ||||
| jobs: | ||||
|   run: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - | ||||
|             buildx_version: latest | ||||
|             buildkit_image: moby/buildkit:buildx-stable-1 | ||||
|           - | ||||
|             buildx_version: https://github.com/docker/buildx.git#master | ||||
|             buildkit_image: moby/buildkit:master | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Set up env | ||||
|         if: inputs.type == 'local' | ||||
|         run: | | ||||
|           cat ./.github/e2e/${{ inputs.id }}/env >> $GITHUB_ENV | ||||
|       - | ||||
|         name: Set up BuildKit config | ||||
|         run: | | ||||
|           touch /tmp/buildkitd.toml | ||||
|           if [ "${{ inputs.type }}" = "local" ]; then | ||||
|             echo -e "[registry.\"${{ env.REGISTRY_FQDN }}\"]\nhttp = true\ninsecure = true" > /tmp/buildkitd.toml | ||||
|           fi | ||||
|       - | ||||
|         name: Set up Docker daemon | ||||
|         if: inputs.type == 'local' | ||||
|         run: | | ||||
|           if [ ! -e /etc/docker/daemon.json ]; then | ||||
|             echo '{}' | tee /etc/docker/daemon.json >/dev/null | ||||
|           fi | ||||
|           DOCKERD_CONFIG=$(jq '.+{"insecure-registries":["http://${{ env.REGISTRY_FQDN }}"]}' /etc/docker/daemon.json) | ||||
|           sudo tee /etc/docker/daemon.json <<<"$DOCKERD_CONFIG" >/dev/null | ||||
|           sudo service docker restart | ||||
|       - | ||||
|         name: Install ${{ inputs.name }} | ||||
|         if: inputs.type == 'local' | ||||
|         run: | | ||||
|           sudo -E bash ./.github/e2e/${{ inputs.id }}/install.sh | ||||
|           sudo chown $(id -u):$(id -g) -R ~/.docker | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: meta | ||||
|         uses: docker/metadata-action@v5 | ||||
|         with: | ||||
|           images: ${{ env.REGISTRY_SLUG || inputs.slug }} | ||||
|           tags: | | ||||
|             type=ref,event=branch,enable=${{ matrix.buildx_version == 'latest' && matrix.buildkit_image == 'moby/buildkit:buildx-stable-1' }} | ||||
|             type=ref,event=tag,enable=${{ matrix.buildx_version == 'latest' && matrix.buildkit_image == 'moby/buildkit:buildx-stable-1' }} | ||||
|             type=raw,gh-runid-${{ github.run_id }} | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|         with: | ||||
|           version: ${{ matrix.buildx_version }} | ||||
|           buildkitd-config: /tmp/buildkitd.toml | ||||
|           buildkitd-flags: --debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host | ||||
|           driver-opts: | | ||||
|             image=${{ matrix.buildkit_image }} | ||||
|             network=host | ||||
|       - | ||||
|         name: Login to Registry | ||||
|         if: github.event_name != 'pull_request' && (env.REGISTRY_USER || inputs.username_secret) != '' | ||||
|         uses: docker/login-action@v3 | ||||
|         with: | ||||
|           registry: ${{ env.REGISTRY_FQDN || inputs.registry }} | ||||
|           username: ${{ env.REGISTRY_USER || secrets[inputs.username_secret] }} | ||||
|           password: ${{ env.REGISTRY_PASSWORD || secrets[inputs.password_secret] }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/multi.Dockerfile | ||||
|           platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x | ||||
|           push: ${{ github.event_name != 'pull_request' }} | ||||
|           tags: ${{ steps.meta.outputs.tags }} | ||||
|           labels: ${{ steps.meta.outputs.labels }} | ||||
|           cache-from: type=registry,ref=${{ env.REGISTRY_SLUG || inputs.slug }}:master | ||||
|           cache-to: type=inline | ||||
|       - | ||||
|         name: Inspect image | ||||
|         run: | | ||||
|           docker pull ${{ env.REGISTRY_SLUG || inputs.slug }}:${{ steps.meta.outputs.version }} | ||||
|           docker image inspect ${{ env.REGISTRY_SLUG || inputs.slug }}:${{ steps.meta.outputs.version }} | ||||
|       - | ||||
|         name: Check manifest | ||||
|         run: | | ||||
|           docker buildx imagetools inspect ${{ env.REGISTRY_SLUG || inputs.slug }}:${{ steps.meta.outputs.version }} --format '{{json .}}' | ||||
							
								
								
									
										1347
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1347
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										121
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,105 +1,114 @@ | ||||
| name: e2e | ||||
|  | ||||
| concurrency: | ||||
|   group: ${{ github.workflow }}-${{ github.ref }} | ||||
|   cancel-in-progress: true | ||||
|  | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * *' # everyday at 10am | ||||
|     - cron: '0 10 * * *' | ||||
|   push: | ||||
|     branches: | ||||
|       - master | ||||
|       - 'master' | ||||
|     tags: | ||||
|       - v* | ||||
|       - 'v*' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|   build: | ||||
|     uses: ./.github/workflows/.e2e-run.yml | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - | ||||
|             name: Distribution | ||||
|             id: distribution | ||||
|             type: local | ||||
|           - | ||||
|             name: Docker Hub | ||||
|             registry: '' | ||||
|             slug: ghactionstest/ghactionstest | ||||
|             username_secret: DOCKERHUB_USERNAME | ||||
|             password_secret: DOCKERHUB_TOKEN | ||||
|             type: remote | ||||
|           - | ||||
|             name: GitHub | ||||
|             registry: ghcr.io | ||||
|             slug: ghcr.io/docker-ghactiontest/test | ||||
|             username_secret: GHCR_USERNAME | ||||
|             password_secret: GHCR_PAT | ||||
|             type: remote | ||||
|           - | ||||
|             name: GitLab | ||||
|             registry: registry.gitlab.com | ||||
|             slug: registry.gitlab.com/test1716/test | ||||
|             username_secret: GITLAB_USERNAME | ||||
|             password_secret: GITLAB_TOKEN | ||||
|             type: remote | ||||
|           - | ||||
|             name: AWS ECR | ||||
|             registry: 175142243308.dkr.ecr.us-east-2.amazonaws.com | ||||
|             slug: 175142243308.dkr.ecr.us-east-2.amazonaws.com/sandbox/test-docker-action | ||||
|             username_secret: AWS_ACCESS_KEY_ID | ||||
|             password_secret: AWS_SECRET_ACCESS_KEY | ||||
|             type: remote | ||||
|           - | ||||
|             name: AWS ECR Public | ||||
|             registry: public.ecr.aws | ||||
|             slug: public.ecr.aws/q3b5f1u4/test-docker-action | ||||
|             username_secret: AWS_ACCESS_KEY_ID | ||||
|             password_secret: AWS_SECRET_ACCESS_KEY | ||||
|             type: remote | ||||
|           - | ||||
|             name: Google Artifact Registry | ||||
|             registry: us-east4-docker.pkg.dev | ||||
|             slug: us-east4-docker.pkg.dev/sandbox-298914/docker-official-github-actions/test-docker-action | ||||
|             username_secret: GAR_USERNAME | ||||
|             password_secret: GAR_JSON_KEY | ||||
|             type: remote | ||||
|           - | ||||
|             name: Google Container Registry | ||||
|             registry: gcr.io | ||||
|             slug: gcr.io/sandbox-298914/test-docker-action | ||||
|             username_secret: GCR_USERNAME | ||||
|             password_secret: GCR_JSON_KEY | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: docker_meta | ||||
|         uses: crazy-max/ghaction-docker-meta@v1 | ||||
|         with: | ||||
|           images: ${{ matrix.slug }} | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to Registry | ||||
|         if: github.event_name != 'pull_request' | ||||
|         uses: docker/login-action@v1 | ||||
|         with: | ||||
|           registry: ${{ matrix.registry }} | ||||
|           username: ${{ secrets[matrix.username_secret] }} | ||||
|           password: ${{ secrets[matrix.password_secret] }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/Dockerfile-multi | ||||
|           platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x | ||||
|           push: ${{ github.event_name != 'pull_request' }} | ||||
|           tags: ${{ steps.docker_meta.outputs.tags }} | ||||
|           labels: ${{ steps.docker_meta.outputs.labels }} | ||||
|           cache-from: type=registry,ref=${{ matrix.slug }}:master | ||||
|           cache-to: type=inline | ||||
|       - | ||||
|         name: Inspect image | ||||
|         if: github.event_name != 'pull_request' | ||||
|         run: | | ||||
|           docker pull ${{ matrix.slug }}:${{ steps.docker_meta.outputs.version }} | ||||
|           docker image inspect ${{ matrix.slug }}:${{ steps.docker_meta.outputs.version }} | ||||
|       - | ||||
|         name: Check manifest | ||||
|         if: github.event_name != 'pull_request' | ||||
|         run: | | ||||
|           docker buildx imagetools inspect ${{ matrix.slug }}:${{ steps.docker_meta.outputs.version }} | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|             type: remote | ||||
|           - | ||||
|             name: Azure Container Registry | ||||
|             registry: officialgithubactions.azurecr.io | ||||
|             slug: officialgithubactions.azurecr.io/test-docker-action | ||||
|             username_secret: AZURE_CLIENT_ID | ||||
|             password_secret: AZURE_CLIENT_SECRET | ||||
|             type: remote | ||||
|           - | ||||
|             name: Quay | ||||
|             registry: quay.io | ||||
|             slug: quay.io/docker_build_team/ghactiontest | ||||
|             username_secret: QUAY_USERNAME | ||||
|             password_secret: QUAY_TOKEN | ||||
|             type: remote | ||||
|           - | ||||
|             name: Artifactory | ||||
|             registry: infradock.jfrog.io | ||||
|             slug: infradock.jfrog.io/test-ghaction/build-push-action | ||||
|             username_secret: ARTIFACTORY_USERNAME | ||||
|             password_secret: ARTIFACTORY_TOKEN | ||||
|             type: remote | ||||
|           - | ||||
|             name: Harbor | ||||
|             id: harbor | ||||
|             type: local | ||||
|           - | ||||
|             name: Nexus | ||||
|             id: nexus | ||||
|             type: local | ||||
|     with: | ||||
|       id: ${{ matrix.id }} | ||||
|       type: ${{ matrix.type }} | ||||
|       name: ${{ matrix.name }} | ||||
|       registry: ${{ matrix.registry }} | ||||
|       slug: ${{ matrix.slug }} | ||||
|       username_secret: ${{ matrix.username_secret }} | ||||
|       password_secret: ${{ matrix.password_secret }} | ||||
|     secrets: inherit | ||||
|   | ||||
							
								
								
									
										71
									
								
								.github/workflows/example.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										71
									
								
								.github/workflows/example.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,71 +0,0 @@ | ||||
| # This workflow is provided just as an usage example and not for repo testing/verification | ||||
| name: example | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * 0' # everyday sunday at 10am | ||||
|   push: | ||||
|     branches: | ||||
|       - '**' | ||||
|     tags: | ||||
|       - 'v*.*.*' | ||||
|   pull_request: | ||||
|  | ||||
| env: | ||||
|   DOCKER_IMAGE: localhost:5000/name/app | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
|         ports: | ||||
|           - 5000:5000 | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: docker_meta | ||||
|         uses: crazy-max/ghaction-docker-meta@v1 | ||||
|         with: | ||||
|           images: ${{ env.DOCKER_IMAGE }} # list of Docker images to use as base name for tags | ||||
|           tag-sha: true # add git short SHA as Docker tag | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         with: | ||||
|           driver-opts: network=host | ||||
|       - | ||||
|         name: Build and export to Docker client | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/Dockerfile | ||||
|           load: true | ||||
|           tags: ${{ steps.docker_meta.outputs.tags }} | ||||
|           labels: ${{ steps.docker_meta.outputs.labels }} | ||||
|       - | ||||
|         name: Build and push to local registry | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/Dockerfile | ||||
|           push: ${{ github.event_name != 'pull_request' }} | ||||
|           tags: ${{ steps.docker_meta.outputs.tags }} | ||||
|           labels: ${{ steps.docker_meta.outputs.labels }} | ||||
|       - | ||||
|         name: Inspect image | ||||
|         run: | | ||||
|           docker image inspect ${{ env.DOCKER_IMAGE }}:${{ steps.docker_meta.outputs.version }} | ||||
|       - | ||||
|         name: Check manifest | ||||
|         if: github.event_name != 'pull_request' | ||||
|         run: | | ||||
|           docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}:${{ steps.docker_meta.outputs.version }} | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
							
								
								
									
										36
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,43 +1,31 @@ | ||||
| name: test | ||||
|  | ||||
| concurrency: | ||||
|   group: ${{ github.workflow }}-${{ github.ref }} | ||||
|   cancel-in-progress: true | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - master | ||||
|       - 'master' | ||||
|       - 'releases/v*' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - master | ||||
|  | ||||
| jobs: | ||||
|   test-containerized: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Validate | ||||
|         run: docker buildx bake validate | ||||
|       - | ||||
|         name: Test | ||||
|         run: docker buildx bake test | ||||
|  | ||||
|   test: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Install | ||||
|         run: yarn install | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Test | ||||
|         run: yarn run test | ||||
|         uses: docker/bake-action@v5 | ||||
|         with: | ||||
|           targets: test | ||||
|       - | ||||
|         name: Upload coverage | ||||
|         uses: codecov/codecov-action@v1 | ||||
|         if: success() | ||||
|         uses: codecov/codecov-action@v4 | ||||
|         with: | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|           file: ./coverage/clover.xml | ||||
|           token: ${{ secrets.CODECOV_TOKEN }} | ||||
|   | ||||
							
								
								
									
										45
									
								
								.github/workflows/validate.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/validate.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| name: validate | ||||
|  | ||||
| concurrency: | ||||
|   group: ${{ github.workflow }}-${{ github.ref }} | ||||
|   cancel-in-progress: true | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'releases/v*' | ||||
|   pull_request: | ||||
|  | ||||
| jobs: | ||||
|   prepare: | ||||
|     runs-on: ubuntu-latest | ||||
|     outputs: | ||||
|       targets: ${{ steps.targets.outputs.matrix }} | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Targets matrix | ||||
|         id: targets | ||||
|         run: | | ||||
|           echo "matrix=$(docker buildx bake validate --print | jq -cr '.group.validate.targets')" >> $GITHUB_OUTPUT | ||||
|  | ||||
|   validate: | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: | ||||
|       - prepare | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         target: ${{ fromJson(needs.prepare.outputs.targets) }} | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Validate | ||||
|         uses: docker/bake-action@v5 | ||||
|         with: | ||||
|           targets: ${{ matrix.target }} | ||||
							
								
								
									
										38
									
								
								.github/workflows/virtual-env.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								.github/workflows/virtual-env.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,38 +0,0 @@ | ||||
| name: virtual-env | ||||
|  | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * *' # everyday at 10am | ||||
|  | ||||
| jobs: | ||||
|   os: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: | ||||
|           - ubuntu-latest | ||||
|           - ubuntu-20.04 | ||||
|           - ubuntu-18.04 | ||||
|           - ubuntu-16.04 | ||||
|     steps: | ||||
|       - | ||||
|         name: List install packages | ||||
|         run: apt list --installed | ||||
|       - | ||||
|         name: Docker info | ||||
|         run: docker info | ||||
|       - | ||||
|         name: Docker version | ||||
|         run: docker version | ||||
|       - | ||||
|         name: buildx version | ||||
|         run: docker buildx version | ||||
|       - | ||||
|         name: containerd version | ||||
|         run: containerd --version | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
							
								
								
									
										70
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +1,5 @@ | ||||
| node_modules | ||||
| lib | ||||
| # https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore | ||||
|  | ||||
| # Jetbrains | ||||
| /.idea | ||||
| /*.iml | ||||
|  | ||||
| # Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore | ||||
| # Logs | ||||
| logs | ||||
| *.log | ||||
| @@ -13,6 +7,7 @@ npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
| lerna-debug.log* | ||||
| .pnpm-debug.log* | ||||
|  | ||||
| # Diagnostic reports (https://nodejs.org/api/report.html) | ||||
| report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||||
| @@ -23,34 +18,14 @@ pids | ||||
| *.seed | ||||
| *.pid.lock | ||||
|  | ||||
| # Directory for instrumented libs generated by jscoverage/JSCover | ||||
| lib-cov | ||||
|  | ||||
| # Coverage directory used by tools like istanbul | ||||
| coverage | ||||
| *.lcov | ||||
|  | ||||
| # nyc test coverage | ||||
| .nyc_output | ||||
|  | ||||
| # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||||
| .grunt | ||||
|  | ||||
| # Bower dependency directory (https://bower.io/) | ||||
| bower_components | ||||
|  | ||||
| # node-waf configuration | ||||
| .lock-wscript | ||||
|  | ||||
| # Compiled binary addons (https://nodejs.org/api/addons.html) | ||||
| build/Release | ||||
|  | ||||
| # Dependency directories | ||||
| node_modules/ | ||||
| jspm_packages/ | ||||
|  | ||||
| # TypeScript v1 declaration files | ||||
| typings/ | ||||
|  | ||||
| # TypeScript cache | ||||
| *.tsbuildinfo | ||||
|  | ||||
| @@ -60,36 +35,19 @@ typings/ | ||||
| # Optional eslint cache | ||||
| .eslintcache | ||||
|  | ||||
| # Optional REPL history | ||||
| .node_repl_history | ||||
|  | ||||
| # Output of 'npm pack' | ||||
| *.tgz | ||||
|  | ||||
| # Yarn Integrity file | ||||
| .yarn-integrity | ||||
|  | ||||
| # dotenv environment variables file | ||||
| # dotenv environment variable files | ||||
| .env | ||||
| .env.test | ||||
| .env.development.local | ||||
| .env.test.local | ||||
| .env.production.local | ||||
| .env.local | ||||
|  | ||||
| # parcel-bundler cache (https://parceljs.org/) | ||||
| .cache | ||||
|  | ||||
| # next.js build output | ||||
| .next | ||||
|  | ||||
| # nuxt.js build output | ||||
| .nuxt | ||||
|  | ||||
| # vuepress build output | ||||
| .vuepress/dist | ||||
|  | ||||
| # Serverless directories | ||||
| .serverless/ | ||||
|  | ||||
| # FuseBox cache | ||||
| .fusebox/ | ||||
|  | ||||
| # DynamoDB Local files | ||||
| .dynamodb/ | ||||
| # yarn v2 | ||||
| .yarn/cache | ||||
| .yarn/unplugged | ||||
| .yarn/build-state.yml | ||||
| .yarn/install-state.gz | ||||
| .pnp.* | ||||
|   | ||||
							
								
								
									
										6
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| # Dependency directories | ||||
| node_modules/ | ||||
| jspm_packages/ | ||||
|  | ||||
| # yarn v2 | ||||
| .yarn/ | ||||
| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|   "printWidth": 120, | ||||
|   "printWidth": 240, | ||||
|   "tabWidth": 2, | ||||
|   "useTabs": false, | ||||
|   "semi": true, | ||||
|   | ||||
							
								
								
									
										541
									
								
								.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										541
									
								
								.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										13
									
								
								.yarnrc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.yarnrc.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| logFilters: | ||||
|   - code: YN0013 | ||||
|     level: discard | ||||
|   - code: YN0019 | ||||
|     level: discard | ||||
|   - code: YN0076 | ||||
|     level: discard | ||||
|  | ||||
| nodeLinker: node-modules | ||||
|  | ||||
| plugins: | ||||
|   - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs | ||||
|     spec: "@yarnpkg/plugin-interactive-tools" | ||||
							
								
								
									
										52
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,52 +0,0 @@ | ||||
| #syntax=docker/dockerfile:1.2 | ||||
|  | ||||
| FROM node:12 AS deps | ||||
| WORKDIR /src | ||||
| COPY package.json yarn.lock ./ | ||||
| RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \ | ||||
|   yarn install | ||||
|  | ||||
| FROM scratch AS update-yarn | ||||
| COPY --from=deps /src/yarn.lock / | ||||
|  | ||||
| FROM deps AS validate-yarn | ||||
| COPY .git .git | ||||
| RUN status=$(git status --porcelain -- yarn.lock); if [ -n "$status" ]; then echo $status; exit 1; fi | ||||
|  | ||||
| FROM deps AS base | ||||
| COPY . . | ||||
|  | ||||
| FROM base AS build | ||||
| RUN yarn build | ||||
|  | ||||
| FROM deps AS test | ||||
| COPY --from=docker /usr/local/bin/docker /usr/bin/ | ||||
| ARG TARGETOS | ||||
| ARG TARGETARCH | ||||
| ARG BUILDX_VERSION=v0.5.1 | ||||
| ENV RUNNER_TEMP=/tmp/github_runner | ||||
| ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ||||
| RUN mkdir -p /usr/local/lib/docker/cli-plugins && \ | ||||
|   curl -fsSL https://github.com/docker/buildx/releases/download/$BUILDX_VERSION/buildx-$BUILDX_VERSION.$TARGETOS-$TARGETARCH > /usr/local/lib/docker/cli-plugins/docker-buildx && \ | ||||
|   chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx && \ | ||||
|   docker buildx version | ||||
| COPY . . | ||||
| RUN yarn run test | ||||
|  | ||||
| FROM base AS run-format | ||||
| RUN yarn run format | ||||
|  | ||||
| FROM scratch AS format | ||||
| COPY --from=run-format /src/src/*.ts /src/ | ||||
|  | ||||
| FROM base AS validate-format | ||||
| RUN yarn run format-check | ||||
|  | ||||
| FROM scratch AS dist | ||||
| COPY --from=build /src/dist/ /dist/ | ||||
|  | ||||
| FROM build AS validate-build | ||||
| RUN status=$(git status --porcelain -- dist); if [ -n "$status" ]; then echo $status; exit 1; fi | ||||
|  | ||||
| FROM base AS dev | ||||
| ENTRYPOINT ["bash"] | ||||
							
								
								
									
										286
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										286
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,28 +1,15 @@ | ||||
| [](https://github.com/docker/build-push-action/releases/latest) | ||||
| [](https://github.com/marketplace/actions/build-and-push-docker-images) | ||||
| [](https://github.com/docker/build-push-action/actions?workflow=ci) | ||||
| [](https://github.com/docker/build-push-action/actions?workflow=test) | ||||
| [](https://github.com/docker/build-push-action/actions?workflow=ci) | ||||
| [](https://github.com/docker/build-push-action/actions?workflow=test) | ||||
| [](https://codecov.io/gh/docker/build-push-action) | ||||
|  | ||||
| ## Upgrade from v1 | ||||
|  | ||||
| `v2` of this action includes significant updates and now uses Docker [Buildx](https://github.com/docker/buildx). It's | ||||
| also rewritten as a [typescript-action](https://github.com/actions/typescript-action/) to be as close as possible | ||||
| of the [GitHub Runner](https://github.com/actions/virtual-environments) during its execution. | ||||
|  | ||||
| [Upgrade notes](UPGRADE.md) with many [usage examples](#advanced-usage) have been added to handle most use cases but | ||||
| `v1` is still available through [`releases/v1` branch](https://github.com/docker/build-push-action/tree/releases/v1). | ||||
|  | ||||
| ## About | ||||
|  | ||||
| GitHub Action to build and push Docker images with [Buildx](https://github.com/docker/buildx) with full support of the | ||||
| features provided by [Moby BuildKit](https://github.com/moby/buildkit) builder toolkit. This includes multi-platform | ||||
| build, secrets, remote cache, etc. and different builder deployment/namespacing options. | ||||
|  | ||||
| > :bulb: See also: | ||||
| > * [login](https://github.com/docker/login-action) action | ||||
| > * [setup-buildx](https://github.com/docker/setup-buildx-action) action | ||||
| > * [setup-qemu](https://github.com/docker/setup-qemu-action) action | ||||
| GitHub Action to build and push Docker images with [Buildx](https://github.com/docker/buildx) | ||||
| with full support of the features provided by [Moby BuildKit](https://github.com/moby/buildkit) | ||||
| builder toolkit. This includes multi-platform build, secrets, remote cache, etc. | ||||
| and different builder deployment/namespacing options. | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -31,55 +18,43 @@ ___ | ||||
| * [Usage](#usage) | ||||
|   * [Git context](#git-context) | ||||
|   * [Path context](#path-context) | ||||
| * [Advanced usage](#advanced-usage) | ||||
|   * [Multi-platform image](docs/advanced/multi-platform.md) | ||||
|   * [Secrets](docs/advanced/secrets.md) | ||||
|   * [Isolated builders](docs/advanced/isolated-builders.md) | ||||
|   * [Push to multi-registries](docs/advanced/push-multi-registries.md) | ||||
|   * [Cache](docs/advanced/cache.md) | ||||
|     * [Registry cache](docs/advanced/cache.md#registry-cache) | ||||
|     * [GitHub cache](docs/advanced/cache.md#github-cache) | ||||
|   * [Local registry](docs/advanced/local-registry.md) | ||||
|   * [Export image to Docker](docs/advanced/export-docker.md) | ||||
|   * [Handle tags and labels](docs/advanced/tags-labels.md) | ||||
|   * [Update DockerHub repo description](docs/advanced/dockerhub-desc.md) | ||||
| * [Examples](#examples) | ||||
| * [Summaries](#summaries) | ||||
| * [Customizing](#customizing) | ||||
|   * [inputs](#inputs) | ||||
|   * [outputs](#outputs) | ||||
|   * [environment variables](#environment-variables) | ||||
| * [Troubleshooting](#troubleshooting) | ||||
| * [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot) | ||||
| * [Limitation](#limitation) | ||||
| * [Contributing](#contributing) | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| By default, this action uses the [Git context](#git-context) so you don't need to use the | ||||
| [`actions/checkout`](https://github.com/actions/checkout/) action to checkout the repository because this will be | ||||
| done directly by buildkit. The git reference will be based on the [event that triggered your workflow](https://docs.github.com/en/actions/reference/events-that-trigger-workflows) | ||||
| and will result in the following context: `https://github.com/<owner>/<repo>.git#<ref>`. | ||||
| In the examples below we are also using 3 other actions: | ||||
|  | ||||
| Be careful because **any file mutation in the steps that precede the build step will be ignored** since | ||||
| the context is based on the git reference. However, you can use the [Path context](#path-context) using the | ||||
| [`context` input](#inputs) alongside the [`actions/checkout`](https://github.com/actions/checkout/) action to remove | ||||
| this restriction. | ||||
|  | ||||
| In the examples below we are using 3 other actions: | ||||
|  | ||||
| * [`setup-buildx`](https://github.com/docker/setup-buildx-action) action will create and boot a builder using by  | ||||
| default the `docker-container` [builder driver](https://github.com/docker/buildx#--driver-driver). This is | ||||
| **not required but recommended** using it to be able to build multi-platform images, export cache, etc. | ||||
| * [`setup-qemu`](https://github.com/docker/setup-qemu-action) action can be useful if you want | ||||
| to add emulation support with QEMU to be able to build against more platforms.  | ||||
| * [`login`](https://github.com/docker/setup-qemu-action) action will take care to log in against a Docker registry. | ||||
| * [`setup-buildx`](https://github.com/docker/setup-buildx-action) action will | ||||
|   create and boot a builder using by default the [`docker-container` driver](https://docs.docker.com/build/building/drivers/docker-container/). | ||||
|   This is **not required but recommended** using it to be able to build | ||||
|   multi-platform images, export cache, etc. | ||||
| * [`setup-qemu`](https://github.com/docker/setup-qemu-action) action can be | ||||
|   useful if you want to add emulation support with QEMU to be able to build | ||||
|   against more platforms.  | ||||
| * [`login`](https://github.com/docker/login-action) action will take care to | ||||
|   log in against a Docker registry. | ||||
|  | ||||
| ### Git context | ||||
|  | ||||
| By default, this action uses the [Git context](https://docs.docker.com/engine/reference/commandline/build/#git-repositories), | ||||
| so you don't need to use the [`actions/checkout`](https://github.com/actions/checkout/) | ||||
| action to check out the repository as this will be done directly by [BuildKit](https://github.com/moby/buildkit). | ||||
|  | ||||
| The git reference will be based on the [event that triggered your workflow](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) | ||||
| and will result in the following context: `https://github.com/<owner>/<repo>.git#<ref>`. | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -87,37 +62,54 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v3 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v6 | ||||
|         with: | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
| ``` | ||||
|  | ||||
| Building from the current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token) | ||||
| so it does not need to be passed. If you want to authenticate against another private repository, you have to use | ||||
| a [secret](docs/advanced/secrets.md) named `GIT_AUTH_TOKEN` to be able to authenticate against it with buildx: | ||||
| Be careful because **any file mutation in the steps that precede the build step | ||||
| will be ignored, including processing of the `.dockerignore` file** since | ||||
| the context is based on the Git reference. However, you can use the | ||||
| [Path context](#path-context) using the [`context` input](#inputs) alongside | ||||
| the [`actions/checkout`](https://github.com/actions/checkout/) action to remove | ||||
| this restriction. | ||||
|  | ||||
| Default Git context can also be provided using the [Handlebars template](https://handlebarsjs.com/guide/) | ||||
| expression `{{defaultContext}}`. Here we can use it to provide a subdirectory | ||||
| to the default Git context: | ||||
|  | ||||
| ```yaml | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v6 | ||||
|         with: | ||||
|           context: "{{defaultContext}}:mysubdir" | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
| ``` | ||||
|  | ||||
| Building from the current repository automatically uses the [GitHub Token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication), | ||||
| so it does not need to be passed. If you want to authenticate against another | ||||
| private repository, you have to use a [secret](https://docs.docker.com/build/ci/github-actions/secrets) | ||||
| named `GIT_AUTH_TOKEN` to be able to authenticate against it with Buildx: | ||||
|  | ||||
| ```yaml | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v6 | ||||
|         with: | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
| @@ -125,9 +117,6 @@ a [secret](docs/advanced/secrets.md) named `GIT_AUTH_TOKEN` to be able to authen | ||||
|             GIT_AUTH_TOKEN=${{ secrets.MYTOKEN }} | ||||
| ``` | ||||
|  | ||||
| > :warning: Subdir for Git context is not yet supported ([moby/buildkit#1684](https://github.com/moby/buildkit/issues/1684)) | ||||
| > but you can use the [path context](#path-context) in the meantime. More info on [Docker docs website](https://docs.docker.com/engine/reference/commandline/build/#git-repositories). | ||||
|  | ||||
| ### Path context | ||||
|  | ||||
| ```yaml | ||||
| @@ -135,8 +124,6 @@ name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -144,47 +131,71 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1 | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v3 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v6 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
| ``` | ||||
|  | ||||
| ## Advanced usage | ||||
| ## Examples | ||||
|  | ||||
| * [Multi-platform image](docs/advanced/multi-platform.md) | ||||
| * [Secrets](docs/advanced/secrets.md) | ||||
| * [Isolated builders](docs/advanced/isolated-builders.md) | ||||
| * [Push to multi-registries](docs/advanced/push-multi-registries.md) | ||||
| * [Cache](docs/advanced/cache.md) | ||||
|   * [Registry cache](docs/advanced/cache.md#registry-cache) | ||||
|   * [GitHub cache](docs/advanced/cache.md#github-cache) | ||||
| * [Local registry](docs/advanced/local-registry.md) | ||||
| * [Export image to Docker](docs/advanced/export-docker.md) | ||||
| * [Handle tags and labels](docs/advanced/tags-labels.md) | ||||
| * [Update DockerHub repo description](docs/advanced/dockerhub-desc.md) | ||||
| * [Multi-platform image](https://docs.docker.com/build/ci/github-actions/multi-platform/) | ||||
| * [Secrets](https://docs.docker.com/build/ci/github-actions/secrets/) | ||||
| * [Push to multi-registries](https://docs.docker.com/build/ci/github-actions/push-multi-registries/) | ||||
| * [Manage tags and labels](https://docs.docker.com/build/ci/github-actions/manage-tags-labels/) | ||||
| * [Cache management](https://docs.docker.com/build/ci/github-actions/cache/) | ||||
| * [Export to Docker](https://docs.docker.com/build/ci/github-actions/export-docker/) | ||||
| * [Test before push](https://docs.docker.com/build/ci/github-actions/test-before-push/) | ||||
| * [Local registry](https://docs.docker.com/build/ci/github-actions/local-registry/) | ||||
| * [Share built image between jobs](https://docs.docker.com/build/ci/github-actions/share-image-jobs/) | ||||
| * [Named contexts](https://docs.docker.com/build/ci/github-actions/named-contexts/) | ||||
| * [Copy image between registries](https://docs.docker.com/build/ci/github-actions/copy-image-registries/) | ||||
| * [Update Docker Hub repo description](https://docs.docker.com/build/ci/github-actions/update-dockerhub-desc/) | ||||
| * [SBOM and provenance attestations](https://docs.docker.com/build/ci/github-actions/attestations/) | ||||
| * [Annotations](https://docs.docker.com/build/ci/github-actions/annotations/) | ||||
| * [Reproducible builds](https://docs.docker.com/build/ci/github-actions/reproducible-builds/) | ||||
|  | ||||
| ## Summaries | ||||
|  | ||||
| This action generates a [job summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/) | ||||
| that provides a detailed overview of the build execution. The summary shows an | ||||
| overview of all the steps executed during the build, including the build inputs | ||||
| and eventual errors. | ||||
|  | ||||
|  | ||||
|  | ||||
| The summary also includes a link for downloading the build record with | ||||
| additional details about the build, including build stats, logs, outputs, and | ||||
| more. The build record can be imported to Docker Desktop for inspecting the | ||||
| build in greater detail. | ||||
|  | ||||
| Summaries are enabled by default, but can be disabled with the | ||||
| `DOCKER_BUILD_SUMMARY` [environment variable](#environment-variables). | ||||
|  | ||||
| For more information about summaries, refer to the | ||||
| [documentation](https://docs.docker.com/go/build-summary/). | ||||
|  | ||||
| ## Customizing | ||||
|  | ||||
| ### inputs | ||||
|  | ||||
| Following inputs can be used as `step.with` keys | ||||
| The following inputs can be used as `step.with` keys: | ||||
|  | ||||
| > `List` type is a newline-delimited string | ||||
| > ```yaml | ||||
| @@ -198,56 +209,65 @@ Following inputs can be used as `step.with` keys | ||||
| > tags: name/app:latest,name/app:1.0.0 | ||||
| > ``` | ||||
|  | ||||
| | Name                | Type     | Description                        | | ||||
| |---------------------|----------|------------------------------------| | ||||
| | `builder`           | String   | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) | | ||||
| | `context`           | String   | Build's context is the set of files located in the specified [`PATH` or `URL`](https://docs.docker.com/engine/reference/commandline/build/) (default [Git context](#git-context)) | | ||||
| | `file`              | String   | Path to the Dockerfile. (default `{context}/Dockerfile`) | | ||||
| | `build-args`        | List     | List of build-time variables | | ||||
| | `labels`            | List     | List of metadata for an image | | ||||
| | `tags`              | List/CSV | List of tags | | ||||
| | `pull`              | Bool     | Always attempt to pull a newer version of the image (default `false`) | | ||||
| | `target`            | String   | Sets the target stage to build | | ||||
| | `allow`             | List/CSV | List of [extra privileged entitlement](https://github.com/docker/buildx#--allowentitlement) (eg. `network.host,security.insecure`) | | ||||
| | `no-cache`          | Bool     | Do not use cache when building the image (default `false`) | | ||||
| | `platforms`         | List/CSV | List of [target platforms](https://github.com/docker/buildx#---platformvaluevalue) for build | | ||||
| | `load`              | Bool     | [Load](https://github.com/docker/buildx#--load) is a shorthand for `--output=type=docker` (default `false`) | | ||||
| | `push`              | Bool     | [Push](https://github.com/docker/buildx#--push) is a shorthand for `--output=type=registry` (default `false`) | | ||||
| | `outputs`           | List     | List of [output destinations](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) (format: `type=local,dest=path`) | | ||||
| | `cache-from`        | List     | List of [external cache sources](https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue) (eg. `type=local,src=path/to/dir`) | | ||||
| | `cache-to`          | List     | List of [cache export destinations](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue) (eg. `type=local,dest=path/to/dir`) | | ||||
| | `secrets`           | List     | List of secrets to expose to the build (eg. `key=string`, `GIT_AUTH_TOKEN=mytoken`) | | ||||
| | `secret-files`      | List     | List of secret files to expose to the build (eg. `key=filename`, `MY_SECRET=./secret.txt`) | | ||||
| | `ssh`               | List     | List of SSH agent socket or keys to expose to the build | | ||||
| | Name               | Type        | Description                                                                                                                                                                       | | ||||
| |--------------------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `add-hosts`        | List/CSV    | List of [customs host-to-IP mapping](https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host) (e.g., `docker:10.180.0.1`)      | | ||||
| | `allow`            | List/CSV    | List of [extra privileged entitlement](https://docs.docker.com/engine/reference/commandline/buildx_build/#allow) (e.g., `network.host,security.insecure`)                         | | ||||
| | `annotations`      | List        | List of annotation to set to the image                                                                                                                                            | | ||||
| | `attests`          | List        | List of [attestation](https://docs.docker.com/build/attestations/) parameters (e.g., `type=sbom,generator=image`)                                                                 |  | ||||
| | `builder`          | String      | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action)                                                                                       | | ||||
| | `build-args`       | List        | List of [build-time variables](https://docs.docker.com/engine/reference/commandline/buildx_build/#build-arg)                                                                      | | ||||
| | `build-contexts`   | List        | List of additional [build contexts](https://docs.docker.com/engine/reference/commandline/buildx_build/#build-context) (e.g., `name=path`)                                         | | ||||
| | `cache-from`       | List        | List of [external cache sources](https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from) (e.g., `type=local,src=path/to/dir`)                              | | ||||
| | `cache-to`         | List        | List of [cache export destinations](https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to) (e.g., `type=local,dest=path/to/dir`)                            | | ||||
| | `cgroup-parent`    | String      | Optional [parent cgroup](https://docs.docker.com/engine/reference/commandline/build/#use-a-custom-parent-cgroup---cgroup-parent) for the container used in the build              | | ||||
| | `context`          | String      | Build's context is the set of files located in the specified [`PATH` or `URL`](https://docs.docker.com/engine/reference/commandline/build/) (default [Git context](#git-context)) | | ||||
| | `file`             | String      | Path to the Dockerfile. (default `{context}/Dockerfile`)                                                                                                                          | | ||||
| | `labels`           | List        | List of metadata for an image                                                                                                                                                     | | ||||
| | `load`             | Bool        | [Load](https://docs.docker.com/engine/reference/commandline/buildx_build/#load) is a shorthand for `--output=type=docker` (default `false`)                                       | | ||||
| | `network`          | String      | Set the networking mode for the `RUN` instructions during build                                                                                                                   | | ||||
| | `no-cache`         | Bool        | Do not use cache when building the image (default `false`)                                                                                                                        | | ||||
| | `no-cache-filters` | List/CSV    | Do not cache specified stages                                                                                                                                                     | | ||||
| | `outputs`          | List        | List of [output destinations](https://docs.docker.com/engine/reference/commandline/buildx_build/#output) (format: `type=local,dest=path`)                                         | | ||||
| | `platforms`        | List/CSV    | List of [target platforms](https://docs.docker.com/engine/reference/commandline/buildx_build/#platform) for build                                                                 | | ||||
| | `provenance`       | Bool/String | Generate [provenance](https://docs.docker.com/build/attestations/slsa-provenance/) attestation for the build (shorthand for `--attest=type=provenance`)                           | | ||||
| | `pull`             | Bool        | Always attempt to pull all referenced images (default `false`)                                                                                                                    | | ||||
| | `push`             | Bool        | [Push](https://docs.docker.com/engine/reference/commandline/buildx_build/#push) is a shorthand for `--output=type=registry` (default `false`)                                     | | ||||
| | `sbom`             | Bool/String | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build (shorthand for `--attest=type=sbom`)                                                  | | ||||
| | `secrets`          | List        | List of [secrets](https://docs.docker.com/engine/reference/commandline/buildx_build/#secret) to expose to the build (e.g., `key=string`, `GIT_AUTH_TOKEN=mytoken`)                | | ||||
| | `secret-envs`      | List/CSV    | List of [secret env vars](https://docs.docker.com/engine/reference/commandline/buildx_build/#secret) to expose to the build (e.g., `key=envname`, `MY_SECRET=MY_ENV_VAR`)         | | ||||
| | `secret-files`     | List        | List of [secret files](https://docs.docker.com/engine/reference/commandline/buildx_build/#secret) to expose to the build (e.g., `key=filename`, `MY_SECRET=./secret.txt`)         | | ||||
| | `shm-size`         | String      | Size of [`/dev/shm`](https://docs.docker.com/engine/reference/commandline/buildx_build/#shm-size) (e.g., `2g`)                                                                    | | ||||
| | `ssh`              | List        | List of [SSH agent socket or keys](https://docs.docker.com/engine/reference/commandline/buildx_build/#ssh) to expose to the build                                                 | | ||||
| | `tags`             | List/CSV    | List of tags                                                                                                                                                                      | | ||||
| | `target`           | String      | Sets the target stage to build                                                                                                                                                    | | ||||
| | `ulimit`           | List        | [Ulimit](https://docs.docker.com/engine/reference/commandline/buildx_build/#ulimit) options (e.g., `nofile=1024:1024`)                                                            | | ||||
| | `github-token`     | String      | GitHub Token used to authenticate against a repository for [Git context](#git-context) (default `${{ github.token }}`)                                                            | | ||||
|  | ||||
| ### outputs | ||||
|  | ||||
| Following outputs are available | ||||
| The following outputs are available: | ||||
|  | ||||
| | Name          | Type    | Description                           | | ||||
| |---------------|---------|---------------------------------------| | ||||
| | `digest`      | String  | Image content-addressable identifier also called a digest | | ||||
| | Name       | Type    | Description           | | ||||
| |------------|---------|-----------------------| | ||||
| | `imageid`  | String  | Image ID              | | ||||
| | `digest`   | String  | Image digest          | | ||||
| | `metadata` | JSON    | Build result metadata | | ||||
|  | ||||
| ### environment variables | ||||
|  | ||||
| | Name                                 | Type   | Default | Description                                                                                                                                                                                                                                                        | | ||||
| |--------------------------------------|--------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `DOCKER_BUILD_CHECKS_ANNOTATIONS`    | Bool   | `true`  | If `false`, GitHub annotations are not generated for [build checks](https://docs.docker.com/build/checks/)                                                                                                                                                         | | ||||
| | `DOCKER_BUILD_SUMMARY`               | Bool   | `true`  | If `false`, [build summary](https://docs.docker.com/build/ci/github-actions/build-summary/) generation is disabled                                                                                                                                                 | | ||||
| | `DOCKER_BUILD_RECORD_UPLOAD`         | Bool   | `true`  | If `false`, build record upload as [GitHub artifact](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts) is disabled                                                                                                            | | ||||
| | `DOCKER_BUILD_RECORD_RETENTION_DAYS` | Number |         | Duration after which build record artifact will expire in days. Defaults to repository/org [retention settings](https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy) if unset or `0` | | ||||
|  | ||||
| ## Troubleshooting | ||||
|  | ||||
| See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | ||||
|  | ||||
| ## Keep up-to-date with GitHub Dependabot | ||||
| ## Contributing | ||||
|  | ||||
| Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot) | ||||
| has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem), | ||||
| to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file: | ||||
|  | ||||
| ```yaml | ||||
| version: 2 | ||||
| updates: | ||||
|   # Maintain dependencies for GitHub Actions | ||||
|   - package-ecosystem: "github-actions" | ||||
|     directory: "/" | ||||
|     schedule: | ||||
|       interval: "daily" | ||||
| ``` | ||||
|  | ||||
| ## Limitation | ||||
|  | ||||
| This action is only available for Linux [virtual environments](https://help.github.com/en/articles/virtual-environments-for-github-actions#supported-virtual-environments-and-hardware-resources). | ||||
| Want to contribute? Awesome! You can find information about contributing to | ||||
| this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md) | ||||
|   | ||||
| @@ -1,6 +1,10 @@ | ||||
| # Troubleshooting | ||||
|  | ||||
| * [Cannot push to a registry](#cannot-push-to-a-registry) | ||||
|   * [BuildKit container logs](#buildkit-container-logs) | ||||
|   * [With containerd](#with-containerd) | ||||
| * [`repository name must be lowercase`](#repository-name-must-be-lowercase) | ||||
| * [Image not loaded](#image-not-loaded) | ||||
|  | ||||
| ## Cannot push to a registry | ||||
|  | ||||
| @@ -12,23 +16,22 @@ While pushing to a registry, you may encounter these kinds of issues: | ||||
| * `failed commit on ref "manifest-sha256:...": unexpected status: 401 Unauthorized` | ||||
| * `unexpected response: 401 Unauthorized` | ||||
|  | ||||
| These issues are not directly related to this action but are rather linked to [buildx](https://github.com/docker/buildx), | ||||
| [buildkit](https://github.com/moby/buildkit), [containerd](https://github.com/containerd/containerd) or the registry | ||||
| on which you're pushing your image. The quality of error message depends on the registry and are usually not very informative. | ||||
| These issues are not directly related to this action but are rather linked to | ||||
| [Buildx](https://github.com/docker/buildx), [BuildKit](https://github.com/moby/buildkit), | ||||
| [containerd](https://github.com/containerd/containerd) or the registry on which | ||||
| you're pushing your image. The quality of error message depends on the registry | ||||
| and are usually not very informative. | ||||
|  | ||||
| To help you solve this, you should first enable debugging in the | ||||
| [setup-buildx action step](https://github.com/docker/setup-buildx-action): | ||||
| ### BuildKit container logs | ||||
|  | ||||
| ```yaml | ||||
|   - | ||||
|     name: Set up Docker Buildx | ||||
|     uses: docker/setup-buildx-action@v1 | ||||
|     with: | ||||
|       buildkitd-flags: --debug | ||||
| ``` | ||||
| To help you solve this, you have to [enable debugging in the setup-buildx](https://github.com/docker/setup-buildx-action#buildkit-container-logs) | ||||
| action step and attach BuildKit container logs to your issue. | ||||
|  | ||||
| Next you can test pushing with [containerd action](https://github.com/crazy-max/ghaction-setup-containerd) using the | ||||
| following workflow. If it works then open an issue on [buildkit](https://github.com/moby/buildkit) repository. | ||||
| ### With containerd | ||||
|  | ||||
| Next you can test pushing with [containerd action](https://github.com/crazy-max/ghaction-setup-containerd) | ||||
| using the following workflow. If it works then open an issue on [BuildKit](https://github.com/moby/buildkit) | ||||
| repository. | ||||
|  | ||||
| ```yaml | ||||
| name: containerd | ||||
| @@ -42,21 +45,21 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v4 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v3 | ||||
|         with: | ||||
|           buildkitd-flags: --debug | ||||
|       - | ||||
|         name: Set up containerd | ||||
|         uses: crazy-max/ghaction-setup-containerd@v1 | ||||
|         uses: crazy-max/ghaction-setup-containerd@v2 | ||||
|       - | ||||
|         name: Build Docker image | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v6 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
| @@ -71,3 +74,91 @@ jobs: | ||||
|         run: | | ||||
|           sudo ctr --debug i push --user "${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }}" docker.io/user/app:latest | ||||
| ``` | ||||
|  | ||||
| ## `repository name must be lowercase` | ||||
|  | ||||
| You may encounter this issue if you're using `github.repository` as a repo slug | ||||
| in your tag: | ||||
|  | ||||
| ``` | ||||
| #6 exporting to image | ||||
| #6 exporting layers | ||||
| #6 exporting layers 1.2s done | ||||
| #6 exporting manifest sha256:b47f7dfb97b89ccd5de553af3c8cd94c4795884cbe5693e93946b1d95a7b1d12 0.0s done | ||||
| #6 exporting config sha256:995e93fab8196893192f08a38deea6769dc4d98f86cf705eccc24ec96a3e271c 0.0s done | ||||
| #6 ERROR: invalid reference format: repository name must be lowercase | ||||
| ------ | ||||
|  > exporting to image: | ||||
| ------ | ||||
| error: failed to solve: invalid reference format: repository name must be lowercase | ||||
| ``` | ||||
|  | ||||
| or a cache reference: | ||||
|  | ||||
| ``` | ||||
| #10 importing cache manifest from ghcr.io/My-Org/repo:main | ||||
| #10 ERROR: invalid reference format: repository name must be lowercase | ||||
| ``` | ||||
|  | ||||
| To fix this issue you can use our [metadata action](https://github.com/docker/metadata-action) | ||||
| to generate sanitized tags: | ||||
|  | ||||
| ```yaml | ||||
| - name: Docker meta | ||||
|   id: meta | ||||
|   uses: docker/metadata-action@v4 | ||||
|   with: | ||||
|     images: ghcr.io/${{ github.repository }} | ||||
|     tags: latest | ||||
|  | ||||
| - name: Build and push | ||||
|   uses: docker/build-push-action@v6 | ||||
|   with: | ||||
|     context: . | ||||
|     push: true | ||||
|     tags: ${{ steps.meta.outputs.tags }} | ||||
| ``` | ||||
|  | ||||
| Or a dedicated step to sanitize the slug: | ||||
|  | ||||
| ```yaml | ||||
| - name: Sanitize repo slug | ||||
|   uses: actions/github-script@v6 | ||||
|   id: repo_slug | ||||
|   with: | ||||
|     result-encoding: string | ||||
|     script: return 'ghcr.io/${{ github.repository }}'.toLowerCase() | ||||
|  | ||||
| - name: Build and push | ||||
|   uses: docker/build-push-action@v6 | ||||
|   with: | ||||
|     context: . | ||||
|     push: true | ||||
|     tags: ${{ steps.repo_slug.outputs.result }}:latest | ||||
| ``` | ||||
|  | ||||
| ## Image not loaded | ||||
|  | ||||
| Sometimes when your workflows are heavy consumers of disk storage, it can happen that build-push-action declares that the built image is loaded, but then not found in the following workflow steps. | ||||
|  | ||||
| - You can use the following solution as workaround, to free space on disk before building docker image using the following workflow step | ||||
|  | ||||
| ```yaml | ||||
|       # Free disk space | ||||
|       - name: Free Disk space | ||||
|         shell: bash | ||||
|         run: | | ||||
|           sudo rm -rf /usr/local/lib/android  # will release about 10 GB if you don't need Android | ||||
|           sudo rm -rf /usr/share/dotnet # will release about 20GB if you don't need .NET | ||||
| ``` | ||||
|  | ||||
| - Another workaround can be to call `docker/setup-buildx-action` with docker driver | ||||
|  | ||||
| ```yaml | ||||
| name: Set up Docker Buildx | ||||
| uses: docker/setup-buildx-action@v3 | ||||
| with: | ||||
|   driver: docker | ||||
| ``` | ||||
|  | ||||
| More details in the [related issue](https://github.com/docker/build-push-action/issues/321) | ||||
|   | ||||
							
								
								
									
										147
									
								
								UPGRADE.md
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								UPGRADE.md
									
									
									
									
									
								
							| @@ -1,147 +0,0 @@ | ||||
| # Upgrade notes | ||||
|  | ||||
| ## v1 to v2 | ||||
|  | ||||
| * Input `path` is now called `context` for consistency with other Docker build tools | ||||
| * `path` defaults to current git repository so checkout action is not required in a workflow | ||||
| * Rename `dockerfile` input to `file` for consistency with other Docker build tools | ||||
| * Rename `always_pull` input to `pull` for consistency with other Docker build tools | ||||
| * Add `builder` input to be able to choose a builder instance through our [setup-buildx action](https://github.com/docker/setup-buildx-action) | ||||
| * Add [`platforms`](https://github.com/docker/buildx#---platformvaluevalue) input to support multi-platform builds | ||||
| * Add [`allow`](https://github.com/docker/buildx#--allowentitlement) input | ||||
| * Add [`load`](https://github.com/docker/buildx#--load) input | ||||
| * Add [`outputs`](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) input | ||||
| * Add [`cache-from`](https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue) input (`cache_froms` removed) | ||||
| * Add [`cache-to`](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue) input | ||||
| * Rename `build_args` input to `build-args` for consistency with other Docker build tools | ||||
| * Add `secrets` input | ||||
| * Review `tags` input | ||||
| * Remove `repository` input. See [Simple workflow](#simple-workflow) for migration | ||||
| * Remove `username`, `password` and `registry` inputs. Login support moved to [docker/login-action](https://github.com/docker/login-action) repo | ||||
| * Remove `tag_with_sha`, `tag_with_ref`, `add_git_labels` inputs. See [Tags with ref and Git labels](#tags-with-ref-and-git-labels) for migration | ||||
| * Handle Git context | ||||
| * Add `digest` output | ||||
|  | ||||
| ### Simple workflow | ||||
|  | ||||
| ```yaml | ||||
| # v1 | ||||
| steps: | ||||
|   - | ||||
|     name: Checkout code | ||||
|     uses: actions/checkout@v2 | ||||
|   - | ||||
|     name: Build and push Docker images | ||||
|     uses: docker/build-push-action@v1 | ||||
|     with: | ||||
|       username: ${{ secrets.DOCKER_USERNAME }} | ||||
|       password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|       repository: myorg/myrepository | ||||
|       always_pull: true | ||||
|       build_args: arg1=value1,arg2=value2 | ||||
|       cache_froms: myorg/myrepository:latest | ||||
|       tags: latest | ||||
| ``` | ||||
|  | ||||
| ```yaml | ||||
| # v2 | ||||
| steps: | ||||
|   - | ||||
|     name: Checkout code | ||||
|     uses: actions/checkout@v2 | ||||
|   - | ||||
|     name: Set up Docker Buildx | ||||
|     uses: docker/setup-buildx-action@v1 | ||||
|   - | ||||
|     name: Login to DockerHub | ||||
|     uses: docker/login-action@v1 | ||||
|     with: | ||||
|       username: ${{ secrets.DOCKER_USERNAME }} | ||||
|       password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|   - | ||||
|     name: Build and push | ||||
|     uses: docker/build-push-action@v2 | ||||
|     with: | ||||
|       context: . | ||||
|       pull: true | ||||
|       push: true | ||||
|       build-args: | | ||||
|         arg1=value1 | ||||
|         arg2=value2 | ||||
|       cache-from: type=registry,ref=myorg/myrepository:latest | ||||
|       cache-to: type=inline | ||||
|       tags: myorg/myrepository:latest | ||||
| ``` | ||||
|  | ||||
| ### Tags with ref and Git labels | ||||
|  | ||||
| ```yaml | ||||
| # v1 | ||||
| steps: | ||||
|   - | ||||
|     name: Checkout code | ||||
|     uses: actions/checkout@v2 | ||||
|   - | ||||
|     name: Build and push Docker images | ||||
|     uses: docker/build-push-action@v1 | ||||
|     with: | ||||
|       username: ${{ secrets.DOCKER_USERNAME }} | ||||
|       password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|       repository: myorg/myrepository | ||||
|       push: ${{ github.event_name != 'pull_request' }} | ||||
|       tag_with_ref: true | ||||
|       tag_with_sha: true | ||||
|       add_git_labels: true | ||||
| ``` | ||||
|  | ||||
| ```yaml | ||||
| # v2 | ||||
| steps: | ||||
|   - | ||||
|     name: Checkout | ||||
|     uses: actions/checkout@v2 | ||||
|   - | ||||
|     name: Prepare | ||||
|     id: prep | ||||
|     run: | | ||||
|       DOCKER_IMAGE=myorg/myrepository | ||||
|       VERSION=edge | ||||
|       if [[ $GITHUB_REF == refs/tags/* ]]; then | ||||
|         VERSION=${GITHUB_REF#refs/tags/} | ||||
|       elif [[ $GITHUB_REF == refs/heads/* ]]; then | ||||
|         VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g') | ||||
|       elif [[ $GITHUB_REF == refs/pull/* ]]; then | ||||
|         VERSION=pr-${{ github.event.number }} | ||||
|       fi | ||||
|       TAGS="${DOCKER_IMAGE}:${VERSION}" | ||||
|       if [ "${{ github.event_name }}" = "push" ]; then | ||||
|         TAGS="$TAGS,${DOCKER_IMAGE}:sha-${GITHUB_SHA::8}" | ||||
|       fi | ||||
|       echo ::set-output name=version::${VERSION} | ||||
|       echo ::set-output name=tags::${TAGS} | ||||
|       echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ') | ||||
|   - | ||||
|     name: Set up Docker Buildx | ||||
|     uses: docker/setup-buildx-action@v1 | ||||
|   - | ||||
|     name: Login to DockerHub | ||||
|     if: github.event_name != 'pull_request' | ||||
|     uses: docker/login-action@v1  | ||||
|     with: | ||||
|       username: ${{ secrets.DOCKER_USERNAME }} | ||||
|       password: ${{ secrets.DOCKER_PASSWORD }} | ||||
|   - | ||||
|     name: Build and push | ||||
|     uses: docker/build-push-action@v2 | ||||
|     with: | ||||
|       context: . | ||||
|       push: ${{ github.event_name != 'pull_request' }} | ||||
|       tags: ${{ steps.prep.outputs.tags }} | ||||
|       labels: | | ||||
|         org.opencontainers.image.source=${{ github.event.repository.html_url }} | ||||
|         org.opencontainers.image.created=${{ steps.prep.outputs.created }} | ||||
|         org.opencontainers.image.revision=${{ github.sha }} | ||||
| ``` | ||||
|  | ||||
| > You can also use the [Docker meta action to handle tags and labels](docs/advanced/tags-labels.md) based on GitHub | ||||
| > actions events and Git metadata. | ||||
							
								
								
									
										207
									
								
								__mocks__/@actions/github.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								__mocks__/@actions/github.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| import {jest} from '@jest/globals'; | ||||
|  | ||||
| export const context = { | ||||
|   repo: { | ||||
|     owner: 'docker', | ||||
|     repo: 'build-push-action' | ||||
|   }, | ||||
|   ref: 'refs/heads/master', | ||||
|   runId: 123456789, | ||||
|   payload: { | ||||
|     after: '860c1904a1ce19322e91ac35af1ab07466440c37', | ||||
|     base_ref: null, | ||||
|     before: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a', | ||||
|     commits: [ | ||||
|       { | ||||
|         author: { | ||||
|           email: 'crazy-max@users.noreply.github.com', | ||||
|           name: 'CrazyMax', | ||||
|           username: 'crazy-max' | ||||
|         }, | ||||
|         committer: { | ||||
|           email: 'crazy-max@users.noreply.github.com', | ||||
|           name: 'CrazyMax', | ||||
|           username: 'crazy-max' | ||||
|         }, | ||||
|         distinct: true, | ||||
|         id: '860c1904a1ce19322e91ac35af1ab07466440c37', | ||||
|         message: 'hello dev', | ||||
|         timestamp: '2022-04-19T11:27:24+02:00', | ||||
|         tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820', | ||||
|         url: 'https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37' | ||||
|       } | ||||
|     ], | ||||
|     compare: 'https://github.com/docker/test-docker-action/compare/5f3331d7f704...860c1904a1ce', | ||||
|     created: false, | ||||
|     deleted: false, | ||||
|     forced: false, | ||||
|     head_commit: { | ||||
|       author: { | ||||
|         email: 'crazy-max@users.noreply.github.com', | ||||
|         name: 'CrazyMax', | ||||
|         username: 'crazy-max' | ||||
|       }, | ||||
|       committer: { | ||||
|         email: 'crazy-max@users.noreply.github.com', | ||||
|         name: 'CrazyMax', | ||||
|         username: 'crazy-max' | ||||
|       }, | ||||
|       distinct: true, | ||||
|       id: '860c1904a1ce19322e91ac35af1ab07466440c37', | ||||
|       message: 'hello dev', | ||||
|       timestamp: '2022-04-19T11:27:24+02:00', | ||||
|       tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820', | ||||
|       url: 'https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37' | ||||
|     }, | ||||
|     organization: { | ||||
|       avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4', | ||||
|       description: 'Docker helps developers bring their ideas to life by conquering the complexity of app development.', | ||||
|       events_url: 'https://api.github.com/orgs/docker/events', | ||||
|       hooks_url: 'https://api.github.com/orgs/docker/hooks', | ||||
|       id: 5429470, | ||||
|       issues_url: 'https://api.github.com/orgs/docker/issues', | ||||
|       login: 'docker', | ||||
|       members_url: 'https://api.github.com/orgs/docker/members{/member}', | ||||
|       node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=', | ||||
|       public_members_url: 'https://api.github.com/orgs/docker/public_members{/member}', | ||||
|       repos_url: 'https://api.github.com/orgs/docker/repos', | ||||
|       url: 'https://api.github.com/orgs/docker' | ||||
|     }, | ||||
|     pusher: { | ||||
|       email: 'github@crazymax.dev', | ||||
|       name: 'crazy-max' | ||||
|     }, | ||||
|     ref: 'refs/heads/dev', | ||||
|     repository: { | ||||
|       allow_forking: true, | ||||
|       archive_url: 'https://api.github.com/repos/docker/test-docker-action/{archive_format}{/ref}', | ||||
|       archived: false, | ||||
|       assignees_url: 'https://api.github.com/repos/docker/test-docker-action/assignees{/user}', | ||||
|       blobs_url: 'https://api.github.com/repos/docker/test-docker-action/git/blobs{/sha}', | ||||
|       branches_url: 'https://api.github.com/repos/docker/test-docker-action/branches{/branch}', | ||||
|       clone_url: 'https://github.com/docker/test-docker-action.git', | ||||
|       collaborators_url: 'https://api.github.com/repos/docker/test-docker-action/collaborators{/collaborator}', | ||||
|       comments_url: 'https://api.github.com/repos/docker/test-docker-action/comments{/number}', | ||||
|       commits_url: 'https://api.github.com/repos/docker/test-docker-action/commits{/sha}', | ||||
|       compare_url: 'https://api.github.com/repos/docker/test-docker-action/compare/{base}...{head}', | ||||
|       contents_url: 'https://api.github.com/repos/docker/test-docker-action/contents/{+path}', | ||||
|       contributors_url: 'https://api.github.com/repos/docker/test-docker-action/contributors', | ||||
|       created_at: 1596792180, | ||||
|       default_branch: 'master', | ||||
|       deployments_url: 'https://api.github.com/repos/docker/test-docker-action/deployments', | ||||
|       description: 'Test "Docker" Actions', | ||||
|       disabled: false, | ||||
|       downloads_url: 'https://api.github.com/repos/docker/test-docker-action/downloads', | ||||
|       events_url: 'https://api.github.com/repos/docker/test-docker-action/events', | ||||
|       fork: false, | ||||
|       forks: 1, | ||||
|       forks_count: 1, | ||||
|       forks_url: 'https://api.github.com/repos/docker/test-docker-action/forks', | ||||
|       full_name: 'docker/test-docker-action', | ||||
|       git_commits_url: 'https://api.github.com/repos/docker/test-docker-action/git/commits{/sha}', | ||||
|       git_refs_url: 'https://api.github.com/repos/docker/test-docker-action/git/refs{/sha}', | ||||
|       git_tags_url: 'https://api.github.com/repos/docker/test-docker-action/git/tags{/sha}', | ||||
|       git_url: 'git://github.com/docker/test-docker-action.git', | ||||
|       has_downloads: true, | ||||
|       has_issues: true, | ||||
|       has_pages: false, | ||||
|       has_projects: true, | ||||
|       has_wiki: true, | ||||
|       homepage: '', | ||||
|       hooks_url: 'https://api.github.com/repos/docker/test-docker-action/hooks', | ||||
|       html_url: 'https://github.com/docker/test-docker-action', | ||||
|       id: 285789493, | ||||
|       is_template: false, | ||||
|       issue_comment_url: 'https://api.github.com/repos/docker/test-docker-action/issues/comments{/number}', | ||||
|       issue_events_url: 'https://api.github.com/repos/docker/test-docker-action/issues/events{/number}', | ||||
|       issues_url: 'https://api.github.com/repos/docker/test-docker-action/issues{/number}', | ||||
|       keys_url: 'https://api.github.com/repos/docker/test-docker-action/keys{/key_id}', | ||||
|       labels_url: 'https://api.github.com/repos/docker/test-docker-action/labels{/name}', | ||||
|       language: 'JavaScript', | ||||
|       languages_url: 'https://api.github.com/repos/docker/test-docker-action/languages', | ||||
|       license: { | ||||
|         key: 'mit', | ||||
|         name: 'MIT License', | ||||
|         node_id: 'MDc6TGljZW5zZTEz', | ||||
|         spdx_id: 'MIT', | ||||
|         url: 'https://api.github.com/licenses/mit' | ||||
|       }, | ||||
|       master_branch: 'master', | ||||
|       merges_url: 'https://api.github.com/repos/docker/test-docker-action/merges', | ||||
|       milestones_url: 'https://api.github.com/repos/docker/test-docker-action/milestones{/number}', | ||||
|       mirror_url: null, | ||||
|       name: 'test-docker-action', | ||||
|       node_id: 'MDEwOlJlcG9zaXRvcnkyODU3ODk0OTM=', | ||||
|       notifications_url: 'https://api.github.com/repos/docker/test-docker-action/notifications{?since,all,participating}', | ||||
|       open_issues: 6, | ||||
|       open_issues_count: 6, | ||||
|       organization: 'docker', | ||||
|       owner: { | ||||
|         avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4', | ||||
|         email: 'info@docker.com', | ||||
|         events_url: 'https://api.github.com/users/docker/events{/privacy}', | ||||
|         followers_url: 'https://api.github.com/users/docker/followers', | ||||
|         following_url: 'https://api.github.com/users/docker/following{/other_user}', | ||||
|         gists_url: 'https://api.github.com/users/docker/gists{/gist_id}', | ||||
|         gravatar_id: '', | ||||
|         html_url: 'https://github.com/docker', | ||||
|         id: 5429470, | ||||
|         login: 'docker', | ||||
|         name: 'docker', | ||||
|         node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=', | ||||
|         organizations_url: 'https://api.github.com/users/docker/orgs', | ||||
|         received_events_url: 'https://api.github.com/users/docker/received_events', | ||||
|         repos_url: 'https://api.github.com/users/docker/repos', | ||||
|         site_admin: false, | ||||
|         starred_url: 'https://api.github.com/users/docker/starred{/owner}{/repo}', | ||||
|         subscriptions_url: 'https://api.github.com/users/docker/subscriptions', | ||||
|         type: 'Organization', | ||||
|         url: 'https://api.github.com/users/docker' | ||||
|       }, | ||||
|       private: true, | ||||
|       pulls_url: 'https://api.github.com/repos/docker/test-docker-action/pulls{/number}', | ||||
|       pushed_at: 1650360446, | ||||
|       releases_url: 'https://api.github.com/repos/docker/test-docker-action/releases{/id}', | ||||
|       size: 796, | ||||
|       ssh_url: 'git@github.com:docker/test-docker-action.git', | ||||
|       stargazers: 0, | ||||
|       stargazers_count: 0, | ||||
|       stargazers_url: 'https://api.github.com/repos/docker/test-docker-action/stargazers', | ||||
|       statuses_url: 'https://api.github.com/repos/docker/test-docker-action/statuses/{sha}', | ||||
|       subscribers_url: 'https://api.github.com/repos/docker/test-docker-action/subscribers', | ||||
|       subscription_url: 'https://api.github.com/repos/docker/test-docker-action/subscription', | ||||
|       svn_url: 'https://github.com/docker/test-docker-action', | ||||
|       tags_url: 'https://api.github.com/repos/docker/test-docker-action/tags', | ||||
|       teams_url: 'https://api.github.com/repos/docker/test-docker-action/teams', | ||||
|       topics: [], | ||||
|       trees_url: 'https://api.github.com/repos/docker/test-docker-action/git/trees{/sha}', | ||||
|       updated_at: '2022-04-19T09:05:09Z', | ||||
|       url: 'https://github.com/docker/test-docker-action', | ||||
|       visibility: 'private', | ||||
|       watchers: 0, | ||||
|       watchers_count: 0 | ||||
|     }, | ||||
|     sender: { | ||||
|       avatar_url: 'https://avatars.githubusercontent.com/u/1951866?v=4', | ||||
|       events_url: 'https://api.github.com/users/crazy-max/events{/privacy}', | ||||
|       followers_url: 'https://api.github.com/users/crazy-max/followers', | ||||
|       following_url: 'https://api.github.com/users/crazy-max/following{/other_user}', | ||||
|       gists_url: 'https://api.github.com/users/crazy-max/gists{/gist_id}', | ||||
|       gravatar_id: '', | ||||
|       html_url: 'https://github.com/crazy-max', | ||||
|       id: 1951866, | ||||
|       login: 'crazy-max', | ||||
|       node_id: 'MDQ6VXNlcjE5NTE4NjY=', | ||||
|       organizations_url: 'https://api.github.com/users/crazy-max/orgs', | ||||
|       received_events_url: 'https://api.github.com/users/crazy-max/received_events', | ||||
|       repos_url: 'https://api.github.com/users/crazy-max/repos', | ||||
|       site_admin: false, | ||||
|       starred_url: 'https://api.github.com/users/crazy-max/starred{/owner}{/repo}', | ||||
|       subscriptions_url: 'https://api.github.com/users/crazy-max/subscriptions', | ||||
|       type: 'User', | ||||
|       url: 'https://api.github.com/users/crazy-max' | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export const getOctokit = jest.fn(); | ||||
| @@ -1,154 +0,0 @@ | ||||
| import * as fs from 'fs'; | ||||
| import * as path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
|  | ||||
| import * as buildx from '../src/buildx'; | ||||
| import * as context from '../src/context'; | ||||
| import * as docker from '../src/docker'; | ||||
|  | ||||
| const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep); | ||||
| const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9'; | ||||
|  | ||||
| jest.spyOn(context, 'tmpDir').mockImplementation((): string => { | ||||
|   const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep); | ||||
|   if (!fs.existsSync(tmpDir)) { | ||||
|     fs.mkdirSync(tmpDir, {recursive: true}); | ||||
|   } | ||||
|   return tmpDir; | ||||
| }); | ||||
|  | ||||
| jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => { | ||||
|   return tmpNameSync; | ||||
| }); | ||||
|  | ||||
| describe('getImageID', () => { | ||||
|   it('matches', async () => { | ||||
|     const imageIDFile = await buildx.getImageIDFile(); | ||||
|     console.log(`imageIDFile: ${imageIDFile}`); | ||||
|     await fs.writeFileSync(imageIDFile, digest); | ||||
|     const imageID = await buildx.getImageID(); | ||||
|     console.log(`imageID: ${imageID}`); | ||||
|     expect(imageID).toEqual(digest); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('isLocalOrTarExporter', () => { | ||||
|   // prettier-ignore | ||||
|   test.each([ | ||||
|     [ | ||||
|       [ | ||||
|         'type=registry,ref=user/app', | ||||
|       ], | ||||
|       false | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         'type=docker', | ||||
|       ], | ||||
|       false | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         'type=local,dest=./release-out' | ||||
|       ], | ||||
|       true | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         'type=tar,dest=/tmp/image.tar' | ||||
|       ], | ||||
|       true | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         'type=docker', | ||||
|         'type=tar,dest=/tmp/image.tar' | ||||
|       ], | ||||
|       true | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         '"type=tar","dest=/tmp/image.tar"' | ||||
|       ], | ||||
|       true | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         '" type= local" , dest=./release-out' | ||||
|       ], | ||||
|       true | ||||
|     ], | ||||
|     [ | ||||
|       [ | ||||
|         '.' | ||||
|       ], | ||||
|       true | ||||
|     ], | ||||
|   ])( | ||||
|     'given %p returns %p', | ||||
|     async (outputs: Array<string>, expected: boolean) => { | ||||
|       expect(buildx.isLocalOrTarExporter(outputs)).toEqual(expected); | ||||
|     } | ||||
|   ); | ||||
| }); | ||||
|  | ||||
| describe('getVersion', () => { | ||||
|   async function isDaemonRunning() { | ||||
|     return await docker.isDaemonRunning(); | ||||
|   } | ||||
|   (isDaemonRunning() ? it : it.skip)( | ||||
|     'valid', | ||||
|     async () => { | ||||
|       const version = await buildx.getVersion(); | ||||
|       console.log(`version: ${version}`); | ||||
|       expect(semver.valid(version)).not.toBeNull(); | ||||
|     }, | ||||
|     100000 | ||||
|   ); | ||||
| }); | ||||
|  | ||||
| describe('parseVersion', () => { | ||||
|   test.each([ | ||||
|     ['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'], | ||||
|     ['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'], | ||||
|     ['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'] | ||||
|   ])('given %p', async (stdout, expected) => { | ||||
|     expect(await buildx.parseVersion(stdout)).toEqual(expected); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('getSecret', () => { | ||||
|   test.each([ | ||||
|     ['A_SECRET=abcdef0123456789', false, 'A_SECRET', 'abcdef0123456789', false], | ||||
|     ['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789', false, 'GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789', false], | ||||
|     ['MY_KEY=c3RyaW5nLXdpdGgtZXF1YWxzCg==', false, 'MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==', false], | ||||
|     ['aaaaaaaa', false, '', '', true], | ||||
|     ['aaaaaaaa=', false, '', '', true], | ||||
|     ['=bbbbbbb', false, '', '', true], | ||||
|     [ | ||||
|       `foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`, | ||||
|       true, | ||||
|       'foo', | ||||
|       'bar', | ||||
|       false | ||||
|     ], | ||||
|     [`notfound=secret`, true, '', '', true] | ||||
|   ])('given %p key and %p secret', async (kvp, file, exKey, exValue, invalid) => { | ||||
|     try { | ||||
|       let secret: string; | ||||
|       if (file) { | ||||
|         secret = await buildx.getSecretFile(kvp); | ||||
|       } else { | ||||
|         secret = await buildx.getSecretString(kvp); | ||||
|       } | ||||
|       expect(true).toBe(!invalid); | ||||
|       console.log(`secret: ${secret}`); | ||||
|       expect(secret).toEqual(`id=${exKey},src=${tmpNameSync}`); | ||||
|       const secretValue = await fs.readFileSync(tmpNameSync, 'utf-8'); | ||||
|       console.log(`secretValue: ${secretValue}`); | ||||
|       expect(secretValue).toEqual(exValue); | ||||
|     } catch (err) { | ||||
|       expect(true).toBe(invalid); | ||||
|     } | ||||
|   }); | ||||
| }); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										362
									
								
								__tests__/fixtures/github-repo.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								__tests__/fixtures/github-repo.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,362 @@ | ||||
| { | ||||
|   "id": 1296269, | ||||
|   "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", | ||||
|   "name": "Hello-World", | ||||
|   "full_name": "octocat/Hello-World", | ||||
|   "owner": { | ||||
|     "login": "octocat", | ||||
|     "id": 1, | ||||
|     "node_id": "MDQ6VXNlcjE=", | ||||
|     "avatar_url": "https://github.com/images/error/octocat_happy.gif", | ||||
|     "gravatar_id": "", | ||||
|     "url": "https://api.github.com/users/octocat", | ||||
|     "html_url": "https://github.com/octocat", | ||||
|     "followers_url": "https://api.github.com/users/octocat/followers", | ||||
|     "following_url": "https://api.github.com/users/octocat/following{/other_user}", | ||||
|     "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", | ||||
|     "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", | ||||
|     "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", | ||||
|     "organizations_url": "https://api.github.com/users/octocat/orgs", | ||||
|     "repos_url": "https://api.github.com/users/octocat/repos", | ||||
|     "events_url": "https://api.github.com/users/octocat/events{/privacy}", | ||||
|     "received_events_url": "https://api.github.com/users/octocat/received_events", | ||||
|     "type": "User", | ||||
|     "site_admin": false | ||||
|   }, | ||||
|   "private": false, | ||||
|   "html_url": "https://github.com/octocat/Hello-World", | ||||
|   "description": "This your first repo!", | ||||
|   "fork": false, | ||||
|   "url": "https://api.github.com/repos/octocat/Hello-World", | ||||
|   "archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", | ||||
|   "assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}", | ||||
|   "blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", | ||||
|   "branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}", | ||||
|   "collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", | ||||
|   "comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}", | ||||
|   "commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}", | ||||
|   "compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", | ||||
|   "contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}", | ||||
|   "contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors", | ||||
|   "deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments", | ||||
|   "downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads", | ||||
|   "events_url": "http://api.github.com/repos/octocat/Hello-World/events", | ||||
|   "forks_url": "http://api.github.com/repos/octocat/Hello-World/forks", | ||||
|   "git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", | ||||
|   "git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", | ||||
|   "git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", | ||||
|   "git_url": "git:github.com/octocat/Hello-World.git", | ||||
|   "issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", | ||||
|   "issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}", | ||||
|   "issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}", | ||||
|   "keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}", | ||||
|   "labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}", | ||||
|   "languages_url": "http://api.github.com/repos/octocat/Hello-World/languages", | ||||
|   "merges_url": "http://api.github.com/repos/octocat/Hello-World/merges", | ||||
|   "milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}", | ||||
|   "notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", | ||||
|   "pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}", | ||||
|   "releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}", | ||||
|   "ssh_url": "git@github.com:octocat/Hello-World.git", | ||||
|   "stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers", | ||||
|   "statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}", | ||||
|   "subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers", | ||||
|   "subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription", | ||||
|   "tags_url": "http://api.github.com/repos/octocat/Hello-World/tags", | ||||
|   "teams_url": "http://api.github.com/repos/octocat/Hello-World/teams", | ||||
|   "trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", | ||||
|   "clone_url": "https://github.com/octocat/Hello-World.git", | ||||
|   "mirror_url": "git:git.example.com/octocat/Hello-World", | ||||
|   "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks", | ||||
|   "svn_url": "https://svn.github.com/octocat/Hello-World", | ||||
|   "homepage": "https://github.com", | ||||
|   "language": null, | ||||
|   "forks_count": 9, | ||||
|   "stargazers_count": 80, | ||||
|   "watchers_count": 80, | ||||
|   "size": 108, | ||||
|   "default_branch": "master", | ||||
|   "open_issues_count": 0, | ||||
|   "is_template": true, | ||||
|   "topics": [ | ||||
|     "octocat", | ||||
|     "atom", | ||||
|     "electron", | ||||
|     "api" | ||||
|   ], | ||||
|   "has_issues": true, | ||||
|   "has_projects": true, | ||||
|   "has_wiki": true, | ||||
|   "has_pages": false, | ||||
|   "has_downloads": true, | ||||
|   "archived": false, | ||||
|   "disabled": false, | ||||
|   "visibility": "public", | ||||
|   "pushed_at": "2011-01-26T19:06:43Z", | ||||
|   "created_at": "2011-01-26T19:01:12Z", | ||||
|   "updated_at": "2011-01-26T19:14:43Z", | ||||
|   "permissions": { | ||||
|     "pull": true, | ||||
|     "triage": true, | ||||
|     "push": false, | ||||
|     "maintain": false, | ||||
|     "admin": false | ||||
|   }, | ||||
|   "allow_rebase_merge": true, | ||||
|   "template_repository": null, | ||||
|   "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", | ||||
|   "allow_squash_merge": true, | ||||
|   "delete_branch_on_merge": true, | ||||
|   "allow_merge_commit": true, | ||||
|   "subscribers_count": 42, | ||||
|   "network_count": 0, | ||||
|   "license": { | ||||
|     "key": "mit", | ||||
|     "name": "MIT License", | ||||
|     "spdx_id": "MIT", | ||||
|     "url": "https://api.github.com/licenses/mit", | ||||
|     "node_id": "MDc6TGljZW5zZW1pdA==" | ||||
|   }, | ||||
|   "organization": { | ||||
|     "login": "octocat", | ||||
|     "id": 1, | ||||
|     "node_id": "MDQ6VXNlcjE=", | ||||
|     "avatar_url": "https://github.com/images/error/octocat_happy.gif", | ||||
|     "gravatar_id": "", | ||||
|     "url": "https://api.github.com/users/octocat", | ||||
|     "html_url": "https://github.com/octocat", | ||||
|     "followers_url": "https://api.github.com/users/octocat/followers", | ||||
|     "following_url": "https://api.github.com/users/octocat/following{/other_user}", | ||||
|     "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", | ||||
|     "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", | ||||
|     "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", | ||||
|     "organizations_url": "https://api.github.com/users/octocat/orgs", | ||||
|     "repos_url": "https://api.github.com/users/octocat/repos", | ||||
|     "events_url": "https://api.github.com/users/octocat/events{/privacy}", | ||||
|     "received_events_url": "https://api.github.com/users/octocat/received_events", | ||||
|     "type": "Organization", | ||||
|     "site_admin": false | ||||
|   }, | ||||
|   "parent": { | ||||
|     "id": 1296269, | ||||
|     "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", | ||||
|     "name": "Hello-World", | ||||
|     "full_name": "octocat/Hello-World", | ||||
|     "owner": { | ||||
|       "login": "octocat", | ||||
|       "id": 1, | ||||
|       "node_id": "MDQ6VXNlcjE=", | ||||
|       "avatar_url": "https://github.com/images/error/octocat_happy.gif", | ||||
|       "gravatar_id": "", | ||||
|       "url": "https://api.github.com/users/octocat", | ||||
|       "html_url": "https://github.com/octocat", | ||||
|       "followers_url": "https://api.github.com/users/octocat/followers", | ||||
|       "following_url": "https://api.github.com/users/octocat/following{/other_user}", | ||||
|       "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", | ||||
|       "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", | ||||
|       "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", | ||||
|       "organizations_url": "https://api.github.com/users/octocat/orgs", | ||||
|       "repos_url": "https://api.github.com/users/octocat/repos", | ||||
|       "events_url": "https://api.github.com/users/octocat/events{/privacy}", | ||||
|       "received_events_url": "https://api.github.com/users/octocat/received_events", | ||||
|       "type": "User", | ||||
|       "site_admin": false | ||||
|     }, | ||||
|     "private": false, | ||||
|     "html_url": "https://github.com/octocat/Hello-World", | ||||
|     "description": "This your first repo!", | ||||
|     "fork": false, | ||||
|     "url": "https://api.github.com/repos/octocat/Hello-World", | ||||
|     "archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", | ||||
|     "assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}", | ||||
|     "blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", | ||||
|     "branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}", | ||||
|     "collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", | ||||
|     "comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}", | ||||
|     "commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}", | ||||
|     "compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", | ||||
|     "contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}", | ||||
|     "contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors", | ||||
|     "deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments", | ||||
|     "downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads", | ||||
|     "events_url": "http://api.github.com/repos/octocat/Hello-World/events", | ||||
|     "forks_url": "http://api.github.com/repos/octocat/Hello-World/forks", | ||||
|     "git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", | ||||
|     "git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", | ||||
|     "git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", | ||||
|     "git_url": "git:github.com/octocat/Hello-World.git", | ||||
|     "issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", | ||||
|     "issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}", | ||||
|     "issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}", | ||||
|     "keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}", | ||||
|     "labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}", | ||||
|     "languages_url": "http://api.github.com/repos/octocat/Hello-World/languages", | ||||
|     "merges_url": "http://api.github.com/repos/octocat/Hello-World/merges", | ||||
|     "milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}", | ||||
|     "notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", | ||||
|     "pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}", | ||||
|     "releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}", | ||||
|     "ssh_url": "git@github.com:octocat/Hello-World.git", | ||||
|     "stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers", | ||||
|     "statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}", | ||||
|     "subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers", | ||||
|     "subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription", | ||||
|     "tags_url": "http://api.github.com/repos/octocat/Hello-World/tags", | ||||
|     "teams_url": "http://api.github.com/repos/octocat/Hello-World/teams", | ||||
|     "trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", | ||||
|     "clone_url": "https://github.com/octocat/Hello-World.git", | ||||
|     "mirror_url": "git:git.example.com/octocat/Hello-World", | ||||
|     "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks", | ||||
|     "svn_url": "https://svn.github.com/octocat/Hello-World", | ||||
|     "homepage": "https://github.com", | ||||
|     "language": null, | ||||
|     "forks_count": 9, | ||||
|     "stargazers_count": 80, | ||||
|     "watchers_count": 80, | ||||
|     "size": 108, | ||||
|     "default_branch": "master", | ||||
|     "open_issues_count": 0, | ||||
|     "is_template": true, | ||||
|     "topics": [ | ||||
|       "octocat", | ||||
|       "atom", | ||||
|       "electron", | ||||
|       "api" | ||||
|     ], | ||||
|     "has_issues": true, | ||||
|     "has_projects": true, | ||||
|     "has_wiki": true, | ||||
|     "has_pages": false, | ||||
|     "has_downloads": true, | ||||
|     "archived": false, | ||||
|     "disabled": false, | ||||
|     "visibility": "public", | ||||
|     "pushed_at": "2011-01-26T19:06:43Z", | ||||
|     "created_at": "2011-01-26T19:01:12Z", | ||||
|     "updated_at": "2011-01-26T19:14:43Z", | ||||
|     "permissions": { | ||||
|       "admin": false, | ||||
|       "push": false, | ||||
|       "pull": true | ||||
|     }, | ||||
|     "allow_rebase_merge": true, | ||||
|     "template_repository": null, | ||||
|     "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", | ||||
|     "allow_squash_merge": true, | ||||
|     "delete_branch_on_merge": true, | ||||
|     "allow_merge_commit": true, | ||||
|     "subscribers_count": 42, | ||||
|     "network_count": 0 | ||||
|   }, | ||||
|   "source": { | ||||
|     "id": 1296269, | ||||
|     "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", | ||||
|     "name": "Hello-World", | ||||
|     "full_name": "octocat/Hello-World", | ||||
|     "owner": { | ||||
|       "login": "octocat", | ||||
|       "id": 1, | ||||
|       "node_id": "MDQ6VXNlcjE=", | ||||
|       "avatar_url": "https://github.com/images/error/octocat_happy.gif", | ||||
|       "gravatar_id": "", | ||||
|       "url": "https://api.github.com/users/octocat", | ||||
|       "html_url": "https://github.com/octocat", | ||||
|       "followers_url": "https://api.github.com/users/octocat/followers", | ||||
|       "following_url": "https://api.github.com/users/octocat/following{/other_user}", | ||||
|       "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", | ||||
|       "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", | ||||
|       "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", | ||||
|       "organizations_url": "https://api.github.com/users/octocat/orgs", | ||||
|       "repos_url": "https://api.github.com/users/octocat/repos", | ||||
|       "events_url": "https://api.github.com/users/octocat/events{/privacy}", | ||||
|       "received_events_url": "https://api.github.com/users/octocat/received_events", | ||||
|       "type": "User", | ||||
|       "site_admin": false | ||||
|     }, | ||||
|     "private": false, | ||||
|     "html_url": "https://github.com/octocat/Hello-World", | ||||
|     "description": "This your first repo!", | ||||
|     "fork": false, | ||||
|     "url": "https://api.github.com/repos/octocat/Hello-World", | ||||
|     "archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", | ||||
|     "assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}", | ||||
|     "blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", | ||||
|     "branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}", | ||||
|     "collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", | ||||
|     "comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}", | ||||
|     "commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}", | ||||
|     "compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", | ||||
|     "contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}", | ||||
|     "contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors", | ||||
|     "deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments", | ||||
|     "downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads", | ||||
|     "events_url": "http://api.github.com/repos/octocat/Hello-World/events", | ||||
|     "forks_url": "http://api.github.com/repos/octocat/Hello-World/forks", | ||||
|     "git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", | ||||
|     "git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", | ||||
|     "git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", | ||||
|     "git_url": "git:github.com/octocat/Hello-World.git", | ||||
|     "issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", | ||||
|     "issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}", | ||||
|     "issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}", | ||||
|     "keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}", | ||||
|     "labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}", | ||||
|     "languages_url": "http://api.github.com/repos/octocat/Hello-World/languages", | ||||
|     "merges_url": "http://api.github.com/repos/octocat/Hello-World/merges", | ||||
|     "milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}", | ||||
|     "notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", | ||||
|     "pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}", | ||||
|     "releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}", | ||||
|     "ssh_url": "git@github.com:octocat/Hello-World.git", | ||||
|     "stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers", | ||||
|     "statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}", | ||||
|     "subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers", | ||||
|     "subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription", | ||||
|     "tags_url": "http://api.github.com/repos/octocat/Hello-World/tags", | ||||
|     "teams_url": "http://api.github.com/repos/octocat/Hello-World/teams", | ||||
|     "trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", | ||||
|     "clone_url": "https://github.com/octocat/Hello-World.git", | ||||
|     "mirror_url": "git:git.example.com/octocat/Hello-World", | ||||
|     "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks", | ||||
|     "svn_url": "https://svn.github.com/octocat/Hello-World", | ||||
|     "homepage": "https://github.com", | ||||
|     "language": null, | ||||
|     "forks_count": 9, | ||||
|     "stargazers_count": 80, | ||||
|     "watchers_count": 80, | ||||
|     "size": 108, | ||||
|     "default_branch": "master", | ||||
|     "open_issues_count": 0, | ||||
|     "is_template": true, | ||||
|     "topics": [ | ||||
|       "octocat", | ||||
|       "atom", | ||||
|       "electron", | ||||
|       "api" | ||||
|     ], | ||||
|     "has_issues": true, | ||||
|     "has_projects": true, | ||||
|     "has_wiki": true, | ||||
|     "has_pages": false, | ||||
|     "has_downloads": true, | ||||
|     "archived": false, | ||||
|     "disabled": false, | ||||
|     "visibility": "public", | ||||
|     "pushed_at": "2011-01-26T19:06:43Z", | ||||
|     "created_at": "2011-01-26T19:01:12Z", | ||||
|     "updated_at": "2011-01-26T19:14:43Z", | ||||
|     "permissions": { | ||||
|       "admin": false, | ||||
|       "push": false, | ||||
|       "pull": true | ||||
|     }, | ||||
|     "allow_rebase_merge": true, | ||||
|     "template_repository": null, | ||||
|     "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", | ||||
|     "allow_squash_merge": true, | ||||
|     "delete_branch_on_merge": true, | ||||
|     "allow_merge_commit": true, | ||||
|     "subscribers_count": 42, | ||||
|     "network_count": 0 | ||||
|   } | ||||
| } | ||||
| @@ -1 +1 @@ | ||||
| bar | ||||
| bar | ||||
|   | ||||
							
								
								
									
										94
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								action.yml
									
									
									
									
									
								
							| @@ -7,77 +7,117 @@ branding: | ||||
|   color: 'blue' | ||||
|  | ||||
| inputs: | ||||
|   add-hosts: | ||||
|     description: "List of a customs host-to-IP mapping (e.g., docker:10.180.0.1)" | ||||
|     required: false | ||||
|   allow: | ||||
|     description: "List of extra privileged entitlement (e.g., network.host,security.insecure)" | ||||
|     required: false | ||||
|   annotations: | ||||
|     description: "List of annotation to set to the image" | ||||
|     required: false | ||||
|   attests: | ||||
|     description: "List of attestation parameters (e.g., type=sbom,generator=image)" | ||||
|     required: false | ||||
|   build-args: | ||||
|     description: "List of build-time variables" | ||||
|     required: false | ||||
|   build-contexts: | ||||
|     description: "List of additional build contexts (e.g., name=path)" | ||||
|     required: false | ||||
|   builder: | ||||
|     description: "Builder instance" | ||||
|     required: false | ||||
|   cache-from: | ||||
|     description: "List of external cache sources for buildx (e.g., user/app:cache, type=local,src=path/to/dir)" | ||||
|     required: false | ||||
|   cache-to: | ||||
|     description: "List of cache export destinations for buildx (e.g., user/app:cache, type=local,dest=path/to/dir)" | ||||
|     required: false | ||||
|   cgroup-parent: | ||||
|     description: "Optional parent cgroup for the container used in the build" | ||||
|     required: false | ||||
|   context: | ||||
|     description: "Build's context is the set of files located in the specified PATH or URL" | ||||
|     required: false | ||||
|   file: | ||||
|     description: "Path to the Dockerfile" | ||||
|     required: false | ||||
|   build-args: | ||||
|     description: "List of build-time variables" | ||||
|     required: false | ||||
|   labels: | ||||
|     description: "List of metadata for an image" | ||||
|     required: false | ||||
|   tags: | ||||
|     description: "List of tags" | ||||
|     required: false | ||||
|   pull: | ||||
|     description: "Always attempt to pull a newer version of the image" | ||||
|   load: | ||||
|     description: "Load is a shorthand for --output=type=docker" | ||||
|     required: false | ||||
|     default: 'false' | ||||
|   target: | ||||
|     description: "Sets the target stage to build" | ||||
|     required: false | ||||
|   allow: | ||||
|     description: "List of extra privileged entitlement (eg. network.host,security.insecure)" | ||||
|   network: | ||||
|     description: "Set the networking mode for the RUN instructions during build" | ||||
|     required: false | ||||
|   no-cache: | ||||
|     description: "Do not use cache when building the image" | ||||
|     required: false | ||||
|     default: 'false' | ||||
|   no-cache-filters: | ||||
|     description: "Do not cache specified stages" | ||||
|     required: false | ||||
|   outputs: | ||||
|     description: "List of output destinations (format: type=local,dest=path)" | ||||
|     required: false | ||||
|   platforms: | ||||
|     description: "List of target platforms for build" | ||||
|     required: false | ||||
|   load: | ||||
|     description: "Load is a shorthand for --output=type=docker" | ||||
|   provenance: | ||||
|     description: "Generate provenance attestation for the build (shorthand for --attest=type=provenance)" | ||||
|     required: false | ||||
|   pull: | ||||
|     description: "Always attempt to pull all referenced images" | ||||
|     required: false | ||||
|     default: 'false' | ||||
|   push: | ||||
|     description: "Push is a shorthand for --output=type=registry" | ||||
|     required: false | ||||
|     default: 'false' | ||||
|   outputs: | ||||
|     description: "List of output destinations (format: type=local,dest=path)" | ||||
|     required: false | ||||
|   cache-from: | ||||
|     description: "List of external cache sources for buildx (eg. user/app:cache, type=local,src=path/to/dir)" | ||||
|     required: false | ||||
|   cache-to: | ||||
|     description: "List of cache export destinations for buildx (eg. user/app:cache, type=local,dest=path/to/dir)" | ||||
|   sbom: | ||||
|     description: "Generate SBOM attestation for the build (shorthand for --attest=type=sbom)" | ||||
|     required: false | ||||
|   secrets: | ||||
|     description: "List of secrets to expose to the build (eg. key=string, GIT_AUTH_TOKEN=mytoken)" | ||||
|     description: "List of secrets to expose to the build (e.g., key=string, GIT_AUTH_TOKEN=mytoken)" | ||||
|     required: false | ||||
|   secret-envs: | ||||
|     description: "List of secret env vars to expose to the build (e.g., key=envname, MY_SECRET=MY_ENV_VAR)" | ||||
|     required: false | ||||
|   secret-files: | ||||
|     description: "List of secret files to expose to the build (eg. key=filename, MY_SECRET=./secret.txt)" | ||||
|     description: "List of secret files to expose to the build (e.g., key=filename, MY_SECRET=./secret.txt)" | ||||
|     required: false | ||||
|   shm-size: | ||||
|     description: "Size of /dev/shm (e.g., 2g)" | ||||
|     required: false | ||||
|   ssh: | ||||
|     description: "List of SSH agent socket or keys to expose to the build" | ||||
|     required: false | ||||
|   tags: | ||||
|     description: "List of tags" | ||||
|     required: false | ||||
|   target: | ||||
|     description: "Sets the target stage to build" | ||||
|     required: false | ||||
|   ulimit: | ||||
|     description: "Ulimit options (e.g., nofile=1024:1024)" | ||||
|     required: false | ||||
|   github-token: | ||||
|     description: "GitHub Token used to authenticate against a repository for Git context" | ||||
|     default: ${{ github.token }} | ||||
|     required: false | ||||
|  | ||||
| outputs: | ||||
|   imageid: | ||||
|     description: 'Image ID' | ||||
|   digest: | ||||
|     description: 'Image content-addressable identifier also called a digest' | ||||
|     description: 'Image digest' | ||||
|   metadata: | ||||
|     description: 'Build result metadata' | ||||
|  | ||||
| runs: | ||||
|   using: 'node12' | ||||
|   using: 'node20' | ||||
|   main: 'dist/index.js' | ||||
|   post: 'dist/index.js' | ||||
|   | ||||
							
								
								
									
										3
									
								
								codecov.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								codecov.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| comment: false | ||||
| github_checks: | ||||
|   annotations: false | ||||
							
								
								
									
										80
									
								
								dev.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								dev.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
|  | ||||
| ARG NODE_VERSION=20 | ||||
|  | ||||
| FROM node:${NODE_VERSION}-alpine AS base | ||||
| RUN apk add --no-cache cpio findutils git | ||||
| WORKDIR /src | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/.yarn/cache <<EOT | ||||
|   corepack enable | ||||
|   yarn --version | ||||
|   yarn config set --home enableTelemetry 0 | ||||
| EOT | ||||
|  | ||||
| FROM base AS deps | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/.yarn/cache \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn install && mkdir /vendor && cp yarn.lock /vendor | ||||
|  | ||||
| FROM scratch AS vendor-update | ||||
| COPY --from=deps /vendor / | ||||
|  | ||||
| FROM deps AS vendor-validate | ||||
| RUN --mount=type=bind,target=.,rw <<EOT | ||||
|   set -e | ||||
|   git add -A | ||||
|   cp -rf /vendor/* . | ||||
|   if [ -n "$(git status --porcelain -- yarn.lock)" ]; then | ||||
|     echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"' | ||||
|     git status --porcelain -- yarn.lock | ||||
|     exit 1 | ||||
|   fi | ||||
| EOT | ||||
|  | ||||
| FROM deps AS build | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/.yarn/cache \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn run build && mkdir /out && cp -Rf dist /out/ | ||||
|  | ||||
| FROM scratch AS build-update | ||||
| COPY --from=build /out / | ||||
|  | ||||
| FROM build AS build-validate | ||||
| RUN --mount=type=bind,target=.,rw <<EOT | ||||
|   set -e | ||||
|   git add -A | ||||
|   cp -rf /out/* . | ||||
|   if [ -n "$(git status --porcelain -- dist)" ]; then | ||||
|     echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"' | ||||
|     git status --porcelain -- dist | ||||
|     exit 1 | ||||
|   fi | ||||
| EOT | ||||
|  | ||||
| FROM deps AS format | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/.yarn/cache \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn run format \ | ||||
|   && mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out | ||||
|  | ||||
| FROM scratch AS format-update | ||||
| COPY --from=format /out / | ||||
|  | ||||
| FROM deps AS lint | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/.yarn/cache \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn run lint | ||||
|  | ||||
| FROM deps AS test | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/.yarn/cache \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn run test --coverage --coverageDirectory=/tmp/coverage | ||||
|  | ||||
| FROM scratch AS test-coverage | ||||
| COPY --from=test /tmp/coverage / | ||||
							
								
								
									
										16610
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16610
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										3930
									
								
								dist/licenses.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3930
									
								
								dist/licenses.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								dist/sourcemap-register.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dist/sourcemap-register.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -3,40 +3,51 @@ group "default" { | ||||
| } | ||||
|  | ||||
| group "pre-checkin" { | ||||
|   targets = ["update-yarn", "format", "build"] | ||||
|   targets = ["vendor", "format", "build"] | ||||
| } | ||||
|  | ||||
| group "validate" { | ||||
| 	targets = ["validate-format", "validate-build", "validate-yarn"] | ||||
| } | ||||
|  | ||||
| target "update-yarn" { | ||||
|   target = "update-yarn" | ||||
|   output = ["."] | ||||
|   targets = ["lint", "build-validate", "vendor-validate"] | ||||
| } | ||||
|  | ||||
| target "build" { | ||||
|   target = "dist" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "build-update" | ||||
|   output = ["."] | ||||
| } | ||||
|  | ||||
| target "test" { | ||||
|   target = "test" | ||||
| target "build-validate" { | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "build-validate" | ||||
|   output = ["type=cacheonly"] | ||||
| } | ||||
|  | ||||
| target "format" { | ||||
|   target = "format" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "format-update" | ||||
|   output = ["."] | ||||
| } | ||||
|  | ||||
| target "validate-format" { | ||||
|   target = "validate-format" | ||||
| target "lint" { | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "lint" | ||||
|   output = ["type=cacheonly"] | ||||
| } | ||||
|  | ||||
| target "validate-build" { | ||||
|   target = "validate-build" | ||||
| target "vendor" { | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "vendor-update" | ||||
|   output = ["."] | ||||
| } | ||||
|  | ||||
| target "validate-yarn" { | ||||
| 	target = "validate-yarn" | ||||
| target "vendor-validate" { | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "vendor-validate" | ||||
|   output = ["type=cacheonly"] | ||||
| } | ||||
|  | ||||
| target "test" { | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "test-coverage" | ||||
|   output = ["./coverage"] | ||||
| } | ||||
|   | ||||
| @@ -1,107 +0,0 @@ | ||||
| # Cache | ||||
|  | ||||
| * [Registry cache](#registry-cache) | ||||
| * [GitHub cache](#github-cache) | ||||
|  | ||||
| > More info about buildx cache: https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue | ||||
|  | ||||
| ## Registry cache | ||||
|  | ||||
| You can import/export cache from a cache manifest or (special) image configuration on the registry. | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|           cache-from: type=registry,ref=user/app:latest | ||||
|           cache-to: type=inline | ||||
| ``` | ||||
|  | ||||
| ## GitHub cache | ||||
|  | ||||
| > :warning: At the moment caches are copied over the existing cache so it [keeps growing](https://github.com/docker/build-push-action/issues/252). | ||||
| > The `Move cache` step is used as a temporary fix (see https://github.com/moby/buildkit/issues/1896). | ||||
|  | ||||
| > :rocket: There is a new cache backend using GitHub cache being developed that will lighten your workflow. | ||||
| > More info: https://github.com/docker/buildx/pull/535 | ||||
|  | ||||
| You can leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows) | ||||
| using [actions/cache](https://github.com/actions/cache) with this action: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Cache Docker layers | ||||
|         uses: actions/cache@v2 | ||||
|         with: | ||||
|           path: /tmp/.buildx-cache | ||||
|           key: ${{ runner.os }}-buildx-${{ github.sha }} | ||||
|           restore-keys: | | ||||
|             ${{ runner.os }}-buildx- | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|           cache-from: type=local,src=/tmp/.buildx-cache | ||||
|           cache-to: type=local,dest=/tmp/.buildx-cache-new | ||||
|       - | ||||
|         # Temp fix | ||||
|         # https://github.com/docker/build-push-action/issues/252 | ||||
|         # https://github.com/moby/buildkit/issues/1896 | ||||
|         name: Move cache | ||||
|         run: | | ||||
|           rm -rf /tmp/.buildx-cache | ||||
|           mv /tmp/.buildx-cache-new /tmp/.buildx-cache | ||||
| ``` | ||||
| @@ -1,48 +0,0 @@ | ||||
| # Update DockerHub repo description | ||||
|  | ||||
| You can update the [DockerHub repository description](https://docs.docker.com/docker-hub/repos/) using | ||||
| a third party action called [DockerHub Description](https://github.com/peter-evans/dockerhub-description) | ||||
| with this action: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|       - | ||||
|         name: Update repo description | ||||
|         uses: peter-evans/dockerhub-description@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_PASSWORD }} | ||||
|           repository: user/app | ||||
| ``` | ||||
| @@ -1,35 +0,0 @@ | ||||
| # Export image to Docker | ||||
|  | ||||
| You may want your build result to be available in the Docker client through `docker images` to be able to use it | ||||
| in another step of your workflow: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           load: true | ||||
|           tags: myimage:latest | ||||
|       - | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker image inspect myimage:latest | ||||
| ``` | ||||
| @@ -1,44 +0,0 @@ | ||||
| # Isolated builders | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         id: builder1 | ||||
|       - | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         id: builder2 | ||||
|       - | ||||
|         name: Builder 1 name | ||||
|         run: echo ${{ steps.builder1.outputs.name }} | ||||
|       - | ||||
|         name: Builder 2 name | ||||
|         run: echo ${{ steps.builder2.outputs.name }} | ||||
|       - | ||||
|         name: Build against builder1 | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           builder: ${{ steps.builder1.outputs.name }} | ||||
|           context: . | ||||
|           target: mytarget1 | ||||
|       - | ||||
|         name: Build against builder2 | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           builder: ${{ steps.builder2.outputs.name }} | ||||
|           context: . | ||||
|           target: mytarget2 | ||||
| ``` | ||||
| @@ -1,44 +0,0 @@ | ||||
| # Local registry | ||||
|  | ||||
| For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
|         ports: | ||||
|           - 5000:5000 | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         with: | ||||
|           driver-opts: network=host | ||||
|       - | ||||
|         name: Build and push to local registry | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: localhost:5000/name/app:latest | ||||
|       - | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:latest | ||||
| ``` | ||||
| @@ -1,44 +0,0 @@ | ||||
| # Multi-platform image | ||||
|  | ||||
| You can build multi-platform images using the [`platforms` input](../../README.md#inputs) as described below. | ||||
|  | ||||
| > :bulb: List of available platforms will be displayed and available through our [setup-buildx](https://github.com/docker/setup-buildx-action#about) action. | ||||
|  | ||||
| > :bulb: If you want support for more platforms, you can use QEMU with our [setup-qemu](https://github.com/docker/setup-qemu-action) action. | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
| ``` | ||||
| @@ -1,57 +0,0 @@ | ||||
| # Push to multi-registries | ||||
|  | ||||
| * [Docker Hub and GHCR](#docker-hub-and-ghcr) | ||||
|  | ||||
| ## Docker Hub and GHCR | ||||
|  | ||||
| The following workflow will connect you to [DockerHub](https://github.com/docker/login-action#dockerhub) | ||||
| and [GitHub Container Registry](https://github.com/docker/login-action#github-container-registry) and push the | ||||
| image to these registries. | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Login to GitHub Container Registry | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ github.repository_owner }} | ||||
|           password: ${{ secrets.CR_PAT }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           push: true | ||||
|           tags: | | ||||
|             user/app:latest | ||||
|             user/app:1.0.0 | ||||
|             ghcr.io/user/app:latest | ||||
|             ghcr.io/user/app:1.0.0 | ||||
| ``` | ||||
| @@ -1,84 +0,0 @@ | ||||
| # Secrets | ||||
|  | ||||
| In the following example we will expose and use the [GITHUB_TOKEN secret](https://docs.github.com/en/actions/reference/authentication-in-a-workflow#about-the-github_token-secret) | ||||
| as provided by GitHub in your workflow. | ||||
|  | ||||
| First let's create our `Dockerfile` to use our secret: | ||||
|  | ||||
| ```Dockerfile | ||||
| #syntax=docker/dockerfile:1.2 | ||||
|  | ||||
| FROM alpine | ||||
| RUN --mount=type=secret,id=github_token \ | ||||
|   cat /run/secrets/github_token | ||||
| ``` | ||||
|  | ||||
| As you can see we have named our secret `github_token`. Here is the workflow you can use to expose this secret using | ||||
| the [`secrets` input](../../README.md#inputs): | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           tags: user/app:latest | ||||
|           secrets: | | ||||
|             "github_token=${{ secrets.GITHUB_TOKEN }}" | ||||
| ``` | ||||
|  | ||||
| > :bulb: You can also expose a secret file to the build with [`secret-files`](../../README.md#inputs) input: | ||||
| > ```yaml | ||||
| > secret-files: | | ||||
| >   "MY_SECRET=./secret.txt" | ||||
| > ``` | ||||
|  | ||||
| If you're using [GitHub secrets](https://docs.github.com/en/actions/reference/encrypted-secrets) and need to handle | ||||
| multi-line value, you will need to place the key-value pair between quotes: | ||||
|  | ||||
| ```yaml | ||||
| secrets: | | ||||
|   "MYSECRET=${{ secrets.GPG_KEY }}" | ||||
|   GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789 | ||||
|   "MYSECRET=aaaaaaaa | ||||
|   bbbbbbb | ||||
|   ccccccccc" | ||||
|   FOO=bar | ||||
|   "EMPTYLINE=aaaa | ||||
|    | ||||
|   bbbb | ||||
|   ccc" | ||||
|   "JSON_SECRET={""key1"":""value1"",""key2"":""value2""}" | ||||
| ``` | ||||
|  | ||||
| | Key                | Value                                            | | ||||
| |--------------------|--------------------------------------------------| | ||||
| | `MYSECRET`         | `***********************` | | ||||
| | `GIT_AUTH_TOKEN`   | `abcdefghi,jklmno=0123456789` | | ||||
| | `MYSECRET`         | `aaaaaaaa\nbbbbbbb\nccccccccc` | | ||||
| | `FOO`              | `bar` | | ||||
| | `EMPTYLINE`        | `aaaa\n\nbbbb\nccc` | | ||||
| | `JSON_SECRET`      | `{"key1":"value1","key2":"value2"}` | | ||||
|  | ||||
| > :bulb: All quote signs need to be doubled for escaping. | ||||
| @@ -1,70 +0,0 @@ | ||||
| # Handle tags and labels | ||||
|  | ||||
| If you come from [`v1`](https://github.com/docker/build-push-action/tree/releases/v1#readme) and want an | ||||
| "automatic" tag management and [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md) | ||||
| for labels, you can do it in a dedicated step. The following workflow will use the [Docker meta action](https://github.com/crazy-max/ghaction-docker-meta) | ||||
| to handle tags and labels based on GitHub actions events and Git metadata. | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * *' # everyday at 10am | ||||
|   push: | ||||
|     branches: | ||||
|       - '**' | ||||
|     tags: | ||||
|       - 'v*.*.*' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: docker_meta | ||||
|         uses: crazy-max/ghaction-docker-meta@v1 | ||||
|         with: | ||||
|           # list of Docker images to use as base name for tags | ||||
|           images: | | ||||
|             name/app | ||||
|             ghcr.io/username/app | ||||
|           # add git short SHA as Docker tag | ||||
|           tag-sha: true | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         if: github.event_name != 'pull_request' | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Login to GHCR | ||||
|         if: github.event_name != 'pull_request' | ||||
|         uses: docker/login-action@v1 | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ secrets.GHCR_USERNAME }} | ||||
|           password: ${{ secrets.GHCR_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: ${{ github.event_name != 'pull_request' }} | ||||
|           tags: ${{ steps.docker_meta.outputs.tags }} | ||||
|           labels: ${{ steps.docker_meta.outputs.labels }} | ||||
| ``` | ||||
| @@ -1,12 +0,0 @@ | ||||
| module.exports = { | ||||
|   clearMocks: false, | ||||
|   moduleFileExtensions: ['js', 'ts'], | ||||
|   setupFiles: ["dotenv/config"], | ||||
|   testEnvironment: 'node', | ||||
|   testMatch: ['**/*.test.ts'], | ||||
|   testRunner: 'jest-circus/runner', | ||||
|   transform: { | ||||
|     '^.+\\.ts$': 'ts-jest' | ||||
|   }, | ||||
|   verbose: false | ||||
| } | ||||
							
								
								
									
										30
									
								
								jest.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								jest.config.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| import fs from 'fs'; | ||||
| import os from 'os'; | ||||
| import path from 'path'; | ||||
|  | ||||
| const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-action-')); | ||||
|  | ||||
| process.env = Object.assign({}, process.env, { | ||||
|   TEMP: tmpDir, | ||||
|   GITHUB_REPOSITORY: 'docker/build-push-action', | ||||
|   RUNNER_TEMP: path.join(tmpDir, 'runner-temp'), | ||||
|   RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache') | ||||
| }) as { | ||||
|   [key: string]: string; | ||||
| }; | ||||
|  | ||||
| module.exports = { | ||||
|   clearMocks: false, | ||||
|   testEnvironment: 'node', | ||||
|   moduleFileExtensions: ['js', 'ts'], | ||||
|   testMatch: ['**/*.test.ts'], | ||||
|   transform: { | ||||
|     '^.+\\.ts$': 'ts-jest' | ||||
|   }, | ||||
|   moduleNameMapper: { | ||||
|     '^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs' | ||||
|   }, | ||||
|   collectCoverageFrom: ['src/**/{!(main.ts),}.ts'], | ||||
|   coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__mocks__/', '__tests__/'], | ||||
|   verbose: true | ||||
| }; | ||||
							
								
								
									
										59
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,13 +1,16 @@ | ||||
| { | ||||
|   "name": "docker-build-push", | ||||
|   "description": "Build and push Docker images", | ||||
|   "main": "lib/main.js", | ||||
|   "main": "src/main.ts", | ||||
|   "scripts": { | ||||
|     "build": "tsc && ncc build", | ||||
|     "format": "prettier --write **/*.ts", | ||||
|     "format-check": "prettier --check **/*.ts", | ||||
|     "test": "jest --coverage", | ||||
|     "pre-checkin": "yarn run format && yarn run build" | ||||
|     "build": "ncc build --source-map --minify --license licenses.txt", | ||||
|     "lint": "yarn run prettier && yarn run eslint", | ||||
|     "format": "yarn run prettier:fix && yarn run eslint:fix", | ||||
|     "eslint": "eslint --max-warnings=0 .", | ||||
|     "eslint:fix": "eslint --fix .", | ||||
|     "prettier": "prettier --check \"./**/*.ts\"", | ||||
|     "prettier:fix": "prettier --write \"./**/*.ts\"", | ||||
|     "test": "jest" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
| @@ -19,35 +22,27 @@ | ||||
|     "build", | ||||
|     "push" | ||||
|   ], | ||||
|   "author": "Docker", | ||||
|   "contributors": [ | ||||
|     { | ||||
|       "name": "CrazyMax", | ||||
|       "url": "https://crazymax.dev" | ||||
|     } | ||||
|   ], | ||||
|   "author": "Docker Inc.", | ||||
|   "license": "Apache-2.0", | ||||
|   "packageManager": "yarn@3.6.3", | ||||
|   "dependencies": { | ||||
|     "@actions/core": "^1.2.6", | ||||
|     "@actions/exec": "^1.0.4", | ||||
|     "@actions/github": "^4.0.0", | ||||
|     "csv-parse": "^4.15.1", | ||||
|     "semver": "^7.3.4", | ||||
|     "tmp": "^0.2.1" | ||||
|     "@actions/core": "^1.10.1", | ||||
|     "@docker/actions-toolkit": "0.37.1", | ||||
|     "handlebars": "^4.7.7" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@types/csv-parse": "^1.2.2", | ||||
|     "@types/jest": "^26.0.3", | ||||
|     "@types/node": "^14.0.14", | ||||
|     "@types/tmp": "^0.2.0", | ||||
|     "@vercel/ncc": "^0.23.0", | ||||
|     "dotenv": "^8.2.0", | ||||
|     "jest": "^26.1.0", | ||||
|     "jest-circus": "^26.1.0", | ||||
|     "jest-runtime": "^26.1.0", | ||||
|     "prettier": "^2.0.5", | ||||
|     "ts-jest": "^26.1.1", | ||||
|     "typescript": "^3.9.5", | ||||
|     "typescript-formatter": "^7.2.2" | ||||
|     "@types/node": "^20.12.12", | ||||
|     "@typescript-eslint/eslint-plugin": "^7.9.0", | ||||
|     "@typescript-eslint/parser": "^7.9.0", | ||||
|     "@vercel/ncc": "^0.38.1", | ||||
|     "eslint": "^8.57.0", | ||||
|     "eslint-config-prettier": "^9.1.0", | ||||
|     "eslint-plugin-jest": "^28.5.0", | ||||
|     "eslint-plugin-prettier": "^5.1.3", | ||||
|     "jest": "^29.7.0", | ||||
|     "prettier": "^3.2.5", | ||||
|     "ts-jest": "^29.1.2", | ||||
|     "ts-node": "^10.9.2", | ||||
|     "typescript": "^5.4.5" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										106
									
								
								src/buildx.ts
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								src/buildx.ts
									
									
									
									
									
								
							| @@ -1,106 +0,0 @@ | ||||
| import csvparse from 'csv-parse/lib/sync'; | ||||
| import fs from 'fs'; | ||||
| import path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
|  | ||||
| import * as context from './context'; | ||||
| import * as exec from './exec'; | ||||
|  | ||||
| export async function getImageIDFile(): Promise<string> { | ||||
|   return path.join(context.tmpDir(), 'iidfile').split(path.sep).join(path.posix.sep); | ||||
| } | ||||
|  | ||||
| export async function getImageID(): Promise<string | undefined> { | ||||
|   const iidFile = await getImageIDFile(); | ||||
|   if (!fs.existsSync(iidFile)) { | ||||
|     return undefined; | ||||
|   } | ||||
|   return fs.readFileSync(iidFile, {encoding: 'utf-8'}); | ||||
| } | ||||
|  | ||||
| export async function getSecretString(kvp: string): Promise<string> { | ||||
|   return getSecret(kvp, false); | ||||
| } | ||||
|  | ||||
| export async function getSecretFile(kvp: string): Promise<string> { | ||||
|   return getSecret(kvp, true); | ||||
| } | ||||
|  | ||||
| export async function getSecret(kvp: string, file: boolean): Promise<string> { | ||||
|   const delimiterIndex = kvp.indexOf('='); | ||||
|   const key = kvp.substring(0, delimiterIndex); | ||||
|   let value = kvp.substring(delimiterIndex + 1); | ||||
|   if (key.length == 0 || value.length == 0) { | ||||
|     throw new Error(`${kvp} is not a valid secret`); | ||||
|   } | ||||
|  | ||||
|   if (file) { | ||||
|     if (!fs.existsSync(value)) { | ||||
|       throw new Error(`secret file ${value} not found`); | ||||
|     } | ||||
|     value = fs.readFileSync(value, {encoding: 'utf-8'}); | ||||
|   } | ||||
|  | ||||
|   const secretFile = context.tmpNameSync({ | ||||
|     tmpdir: context.tmpDir() | ||||
|   }); | ||||
|   fs.writeFileSync(secretFile, value); | ||||
|  | ||||
|   return `id=${key},src=${secretFile}`; | ||||
| } | ||||
|  | ||||
| export function isLocalOrTarExporter(outputs: string[]): Boolean { | ||||
|   for (let output of csvparse(outputs.join(`\n`), { | ||||
|     delimiter: ',', | ||||
|     trim: true, | ||||
|     columns: false, | ||||
|     relaxColumnCount: true | ||||
|   })) { | ||||
|     // Local if no type is defined | ||||
|     // https://github.com/docker/buildx/blob/d2bf42f8b4784d83fde17acb3ed84703ddc2156b/build/output.go#L29-L43 | ||||
|     if (output.length == 1 && !output[0].startsWith('type=')) { | ||||
|       return true; | ||||
|     } | ||||
|     for (let [key, value] of output.map(chunk => chunk.split('=').map(item => item.trim()))) { | ||||
|       if (key == 'type' && (value == 'local' || value == 'tar')) { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| export function hasGitAuthToken(secrets: string[]): Boolean { | ||||
|   for (let secret of secrets) { | ||||
|     if (secret.startsWith('GIT_AUTH_TOKEN=')) { | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| export async function isAvailable(): Promise<Boolean> { | ||||
|   return await exec.exec(`docker`, ['buildx'], true).then(res => { | ||||
|     if (res.stderr != '' && !res.success) { | ||||
|       return false; | ||||
|     } | ||||
|     return res.success; | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export async function getVersion(): Promise<string> { | ||||
|   return await exec.exec(`docker`, ['buildx', 'version'], true).then(res => { | ||||
|     if (res.stderr != '' && !res.success) { | ||||
|       throw new Error(res.stderr); | ||||
|     } | ||||
|     return parseVersion(res.stdout); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export async function parseVersion(stdout: string): Promise<string> { | ||||
|   const matches = /\sv?([0-9.]+)/.exec(stdout); | ||||
|   if (!matches) { | ||||
|     throw new Error(`Cannot parse Buildx version`); | ||||
|   } | ||||
|   return semver.clean(matches[1]); | ||||
| } | ||||
							
								
								
									
										387
									
								
								src/context.ts
									
									
									
									
									
								
							
							
						
						
									
										387
									
								
								src/context.ts
									
									
									
									
									
								
							| @@ -1,202 +1,285 @@ | ||||
| import csvparse from 'csv-parse/lib/sync'; | ||||
| import * as fs from 'fs'; | ||||
| import * as os from 'os'; | ||||
| import * as path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
| import * as tmp from 'tmp'; | ||||
|  | ||||
| import * as core from '@actions/core'; | ||||
| import * as github from '@actions/github'; | ||||
| import * as handlebars from 'handlebars'; | ||||
|  | ||||
| import * as buildx from './buildx'; | ||||
|  | ||||
| let _defaultContext, _tmpDir: string; | ||||
| import {Build} from '@docker/actions-toolkit/lib/buildx/build'; | ||||
| import {Context} from '@docker/actions-toolkit/lib/context'; | ||||
| import {GitHub} from '@docker/actions-toolkit/lib/github'; | ||||
| import {Toolkit} from '@docker/actions-toolkit/lib/toolkit'; | ||||
| import {Util} from '@docker/actions-toolkit/lib/util'; | ||||
|  | ||||
| export interface Inputs { | ||||
|   'add-hosts': string[]; | ||||
|   allow: string[]; | ||||
|   annotations: string[]; | ||||
|   attests: string[]; | ||||
|   'build-args': string[]; | ||||
|   'build-contexts': string[]; | ||||
|   builder: string; | ||||
|   'cache-from': string[]; | ||||
|   'cache-to': string[]; | ||||
|   'cgroup-parent': string; | ||||
|   context: string; | ||||
|   file: string; | ||||
|   buildArgs: string[]; | ||||
|   labels: string[]; | ||||
|   tags: string[]; | ||||
|   pull: boolean; | ||||
|   target: string; | ||||
|   allow: string[]; | ||||
|   noCache: boolean; | ||||
|   builder: string; | ||||
|   platforms: string[]; | ||||
|   load: boolean; | ||||
|   push: boolean; | ||||
|   network: string; | ||||
|   'no-cache': boolean; | ||||
|   'no-cache-filters': string[]; | ||||
|   outputs: string[]; | ||||
|   cacheFrom: string[]; | ||||
|   cacheTo: string[]; | ||||
|   platforms: string[]; | ||||
|   provenance: string; | ||||
|   pull: boolean; | ||||
|   push: boolean; | ||||
|   sbom: string; | ||||
|   secrets: string[]; | ||||
|   secretFiles: string[]; | ||||
|   githubToken: string; | ||||
|   'secret-envs': string[]; | ||||
|   'secret-files': string[]; | ||||
|   'shm-size': string; | ||||
|   ssh: string[]; | ||||
|   tags: string[]; | ||||
|   target: string; | ||||
|   ulimit: string[]; | ||||
|   'github-token': string; | ||||
| } | ||||
|  | ||||
| export function defaultContext(): string { | ||||
|   if (!_defaultContext) { | ||||
|     _defaultContext = `https://github.com/${github.context.repo.owner}/${ | ||||
|       github.context.repo.repo | ||||
|     }.git#${github.context?.ref?.replace(/^refs\//, '')}`; | ||||
|   } | ||||
|   return _defaultContext; | ||||
| } | ||||
|  | ||||
| export function tmpDir(): string { | ||||
|   if (!_tmpDir) { | ||||
|     _tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-')).split(path.sep).join(path.posix.sep); | ||||
|   } | ||||
|   return _tmpDir; | ||||
| } | ||||
|  | ||||
| export function tmpNameSync(options?: tmp.TmpNameOptions): string { | ||||
|   return tmp.tmpNameSync(options); | ||||
| } | ||||
|  | ||||
| export async function getInputs(defaultContext: string): Promise<Inputs> { | ||||
| export async function getInputs(): Promise<Inputs> { | ||||
|   return { | ||||
|     context: core.getInput('context') || defaultContext, | ||||
|     file: core.getInput('file'), | ||||
|     buildArgs: await getInputList('build-args', true), | ||||
|     labels: await getInputList('labels', true), | ||||
|     tags: await getInputList('tags'), | ||||
|     pull: /true/i.test(core.getInput('pull')), | ||||
|     target: core.getInput('target'), | ||||
|     allow: await getInputList('allow'), | ||||
|     noCache: /true/i.test(core.getInput('no-cache')), | ||||
|     'add-hosts': Util.getInputList('add-hosts'), | ||||
|     allow: Util.getInputList('allow'), | ||||
|     annotations: Util.getInputList('annotations', {ignoreComma: true}), | ||||
|     attests: Util.getInputList('attests', {ignoreComma: true}), | ||||
|     'build-args': Util.getInputList('build-args', {ignoreComma: true}), | ||||
|     'build-contexts': Util.getInputList('build-contexts', {ignoreComma: true}), | ||||
|     builder: core.getInput('builder'), | ||||
|     platforms: await getInputList('platforms'), | ||||
|     load: /true/i.test(core.getInput('load')), | ||||
|     push: /true/i.test(core.getInput('push')), | ||||
|     outputs: await getInputList('outputs', true), | ||||
|     cacheFrom: await getInputList('cache-from', true), | ||||
|     cacheTo: await getInputList('cache-to', true), | ||||
|     secrets: await getInputList('secrets', true), | ||||
|     secretFiles: await getInputList('secret-files', true), | ||||
|     githubToken: core.getInput('github-token'), | ||||
|     ssh: await getInputList('ssh') | ||||
|     'cache-from': Util.getInputList('cache-from', {ignoreComma: true}), | ||||
|     'cache-to': Util.getInputList('cache-to', {ignoreComma: true}), | ||||
|     'cgroup-parent': core.getInput('cgroup-parent'), | ||||
|     context: core.getInput('context') || Context.gitContext(), | ||||
|     file: core.getInput('file'), | ||||
|     labels: Util.getInputList('labels', {ignoreComma: true}), | ||||
|     load: core.getBooleanInput('load'), | ||||
|     network: core.getInput('network'), | ||||
|     'no-cache': core.getBooleanInput('no-cache'), | ||||
|     'no-cache-filters': Util.getInputList('no-cache-filters'), | ||||
|     outputs: Util.getInputList('outputs', {ignoreComma: true, quote: false}), | ||||
|     platforms: Util.getInputList('platforms'), | ||||
|     provenance: Build.getProvenanceInput('provenance'), | ||||
|     pull: core.getBooleanInput('pull'), | ||||
|     push: core.getBooleanInput('push'), | ||||
|     sbom: core.getInput('sbom'), | ||||
|     secrets: Util.getInputList('secrets', {ignoreComma: true}), | ||||
|     'secret-envs': Util.getInputList('secret-envs'), | ||||
|     'secret-files': Util.getInputList('secret-files', {ignoreComma: true}), | ||||
|     'shm-size': core.getInput('shm-size'), | ||||
|     ssh: Util.getInputList('ssh'), | ||||
|     tags: Util.getInputList('tags'), | ||||
|     target: core.getInput('target'), | ||||
|     ulimit: Util.getInputList('ulimit', {ignoreComma: true}), | ||||
|     'github-token': core.getInput('github-token') | ||||
|   }; | ||||
| } | ||||
|  | ||||
| export async function getArgs(inputs: Inputs, defaultContext: string, buildxVersion: string): Promise<Array<string>> { | ||||
|   let args: Array<string> = ['buildx']; | ||||
|   args.push.apply(args, await getBuildArgs(inputs, defaultContext, buildxVersion)); | ||||
|   args.push.apply(args, await getCommonArgs(inputs)); | ||||
|   args.push(inputs.context); | ||||
|   return args; | ||||
| export function sanitizeInputs(inputs: Inputs) { | ||||
|   const res = {}; | ||||
|   for (const key of Object.keys(inputs)) { | ||||
|     if (key === 'github-token') { | ||||
|       continue; | ||||
|     } | ||||
|     const value: string | string[] | boolean = inputs[key]; | ||||
|     if (typeof value === 'boolean' && value === false) { | ||||
|       continue; | ||||
|     } else if (Array.isArray(value) && value.length === 0) { | ||||
|       continue; | ||||
|     } else if (!value) { | ||||
|       continue; | ||||
|     } | ||||
|     res[key] = value; | ||||
|   } | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersion: string): Promise<Array<string>> { | ||||
|   let args: Array<string> = ['build']; | ||||
|   await asyncForEach(inputs.buildArgs, async buildArg => { | ||||
| export async function getArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> { | ||||
|   const context = handlebars.compile(inputs.context)({ | ||||
|     defaultContext: Context.gitContext() | ||||
|   }); | ||||
|   // prettier-ignore | ||||
|   return [ | ||||
|     ...await getBuildArgs(inputs, context, toolkit), | ||||
|     ...await getCommonArgs(inputs, toolkit), | ||||
|     context | ||||
|   ]; | ||||
| } | ||||
|  | ||||
| async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit): Promise<Array<string>> { | ||||
|   const args: Array<string> = ['build']; | ||||
|   await Util.asyncForEach(inputs['add-hosts'], async addHost => { | ||||
|     args.push('--add-host', addHost); | ||||
|   }); | ||||
|   if (inputs.allow.length > 0) { | ||||
|     args.push('--allow', inputs.allow.join(',')); | ||||
|   } | ||||
|   if (await toolkit.buildx.versionSatisfies('>=0.12.0')) { | ||||
|     await Util.asyncForEach(inputs.annotations, async annotation => { | ||||
|       args.push('--annotation', annotation); | ||||
|     }); | ||||
|   } else if (inputs.annotations.length > 0) { | ||||
|     core.warning("Annotations are only supported by buildx >= 0.12.0; the input 'annotations' is ignored."); | ||||
|   } | ||||
|   await Util.asyncForEach(inputs['build-args'], async buildArg => { | ||||
|     args.push('--build-arg', buildArg); | ||||
|   }); | ||||
|   await asyncForEach(inputs.labels, async label => { | ||||
|   if (await toolkit.buildx.versionSatisfies('>=0.8.0')) { | ||||
|     await Util.asyncForEach(inputs['build-contexts'], async buildContext => { | ||||
|       args.push('--build-context', buildContext); | ||||
|     }); | ||||
|   } else if (inputs['build-contexts'].length > 0) { | ||||
|     core.warning("Build contexts are only supported by buildx >= 0.8.0; the input 'build-contexts' is ignored."); | ||||
|   } | ||||
|   await Util.asyncForEach(inputs['cache-from'], async cacheFrom => { | ||||
|     args.push('--cache-from', cacheFrom); | ||||
|   }); | ||||
|   await Util.asyncForEach(inputs['cache-to'], async cacheTo => { | ||||
|     args.push('--cache-to', cacheTo); | ||||
|   }); | ||||
|   if (inputs['cgroup-parent']) { | ||||
|     args.push('--cgroup-parent', inputs['cgroup-parent']); | ||||
|   } | ||||
|   await Util.asyncForEach(inputs['secret-envs'], async secretEnv => { | ||||
|     try { | ||||
|       args.push('--secret', Build.resolveSecretEnv(secretEnv)); | ||||
|     } catch (err) { | ||||
|       core.warning(err.message); | ||||
|     } | ||||
|   }); | ||||
|   if (inputs.file) { | ||||
|     args.push('--file', inputs.file); | ||||
|   } | ||||
|   if (!Build.hasLocalExporter(inputs.outputs) && !Build.hasTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || (await toolkit.buildx.versionSatisfies('>=0.4.2')))) { | ||||
|     args.push('--iidfile', toolkit.buildxBuild.getImageIDFilePath()); | ||||
|   } | ||||
|   await Util.asyncForEach(inputs.labels, async label => { | ||||
|     args.push('--label', label); | ||||
|   }); | ||||
|   await asyncForEach(inputs.tags, async tag => { | ||||
|   await Util.asyncForEach(inputs['no-cache-filters'], async noCacheFilter => { | ||||
|     args.push('--no-cache-filter', noCacheFilter); | ||||
|   }); | ||||
|   await Util.asyncForEach(inputs.outputs, async output => { | ||||
|     args.push('--output', output); | ||||
|   }); | ||||
|   if (inputs.platforms.length > 0) { | ||||
|     args.push('--platform', inputs.platforms.join(',')); | ||||
|   } | ||||
|   if (await toolkit.buildx.versionSatisfies('>=0.10.0')) { | ||||
|     args.push(...(await getAttestArgs(inputs, toolkit))); | ||||
|   } else { | ||||
|     core.warning("Attestations are only supported by buildx >= 0.10.0; the inputs 'attests', 'provenance' and 'sbom' are ignored."); | ||||
|   } | ||||
|   await Util.asyncForEach(inputs.secrets, async secret => { | ||||
|     try { | ||||
|       args.push('--secret', Build.resolveSecretString(secret)); | ||||
|     } catch (err) { | ||||
|       core.warning(err.message); | ||||
|     } | ||||
|   }); | ||||
|   await Util.asyncForEach(inputs['secret-files'], async secretFile => { | ||||
|     try { | ||||
|       args.push('--secret', Build.resolveSecretFile(secretFile)); | ||||
|     } catch (err) { | ||||
|       core.warning(err.message); | ||||
|     } | ||||
|   }); | ||||
|   if (inputs['github-token'] && !Build.hasGitAuthTokenSecret(inputs.secrets) && context.startsWith(Context.gitContext())) { | ||||
|     args.push('--secret', Build.resolveSecretString(`GIT_AUTH_TOKEN=${inputs['github-token']}`)); | ||||
|   } | ||||
|   if (inputs['shm-size']) { | ||||
|     args.push('--shm-size', inputs['shm-size']); | ||||
|   } | ||||
|   await Util.asyncForEach(inputs.ssh, async ssh => { | ||||
|     args.push('--ssh', ssh); | ||||
|   }); | ||||
|   await Util.asyncForEach(inputs.tags, async tag => { | ||||
|     args.push('--tag', tag); | ||||
|   }); | ||||
|   if (inputs.target) { | ||||
|     args.push('--target', inputs.target); | ||||
|   } | ||||
|   if (inputs.allow.length > 0) { | ||||
|     args.push('--allow', inputs.allow.join(',')); | ||||
|   } | ||||
|   if (inputs.platforms.length > 0) { | ||||
|     args.push('--platform', inputs.platforms.join(',')); | ||||
|   } | ||||
|   await asyncForEach(inputs.outputs, async output => { | ||||
|     args.push('--output', output); | ||||
|   await Util.asyncForEach(inputs.ulimit, async ulimit => { | ||||
|     args.push('--ulimit', ulimit); | ||||
|   }); | ||||
|   if ( | ||||
|     !buildx.isLocalOrTarExporter(inputs.outputs) && | ||||
|     (inputs.platforms.length == 0 || semver.satisfies(buildxVersion, '>=0.4.2')) | ||||
|   ) { | ||||
|     args.push('--iidfile', await buildx.getImageIDFile()); | ||||
|   } | ||||
|   await asyncForEach(inputs.cacheFrom, async cacheFrom => { | ||||
|     args.push('--cache-from', cacheFrom); | ||||
|   }); | ||||
|   await asyncForEach(inputs.cacheTo, async cacheTo => { | ||||
|     args.push('--cache-to', cacheTo); | ||||
|   }); | ||||
|   await asyncForEach(inputs.secrets, async secret => { | ||||
|     try { | ||||
|       args.push('--secret', await buildx.getSecretString(secret)); | ||||
|     } catch (err) { | ||||
|       core.warning(err.message); | ||||
|     } | ||||
|   }); | ||||
|   await asyncForEach(inputs.secretFiles, async secretFile => { | ||||
|     try { | ||||
|       args.push('--secret', await buildx.getSecretFile(secretFile)); | ||||
|     } catch (err) { | ||||
|       core.warning(err.message); | ||||
|     } | ||||
|   }); | ||||
|   if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && inputs.context == defaultContext) { | ||||
|     args.push('--secret', await buildx.getSecretString(`GIT_AUTH_TOKEN=${inputs.githubToken}`)); | ||||
|   } | ||||
|   await asyncForEach(inputs.ssh, async ssh => { | ||||
|     args.push('--ssh', ssh); | ||||
|   }); | ||||
|   if (inputs.file) { | ||||
|     args.push('--file', inputs.file); | ||||
|   } | ||||
|   return args; | ||||
| } | ||||
|  | ||||
| async function getCommonArgs(inputs: Inputs): Promise<Array<string>> { | ||||
|   let args: Array<string> = []; | ||||
|   if (inputs.noCache) { | ||||
|     args.push('--no-cache'); | ||||
|   } | ||||
| async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> { | ||||
|   const args: Array<string> = []; | ||||
|   if (inputs.builder) { | ||||
|     args.push('--builder', inputs.builder); | ||||
|   } | ||||
|   if (inputs.pull) { | ||||
|     args.push('--pull'); | ||||
|   } | ||||
|   if (inputs.load) { | ||||
|     args.push('--load'); | ||||
|   } | ||||
|   if (await toolkit.buildx.versionSatisfies('>=0.6.0')) { | ||||
|     args.push('--metadata-file', toolkit.buildxBuild.getMetadataFilePath()); | ||||
|   } | ||||
|   if (inputs.network) { | ||||
|     args.push('--network', inputs.network); | ||||
|   } | ||||
|   if (inputs['no-cache']) { | ||||
|     args.push('--no-cache'); | ||||
|   } | ||||
|   if (inputs.pull) { | ||||
|     args.push('--pull'); | ||||
|   } | ||||
|   if (inputs.push) { | ||||
|     args.push('--push'); | ||||
|   } | ||||
|   return args; | ||||
| } | ||||
|  | ||||
| export async function getInputList(name: string, ignoreComma?: boolean): Promise<string[]> { | ||||
|   let res: Array<string> = []; | ||||
| async function getAttestArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> { | ||||
|   const args: Array<string> = []; | ||||
|  | ||||
|   const items = core.getInput(name); | ||||
|   if (items == '') { | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   for (let output of (await csvparse(items, { | ||||
|     columns: false, | ||||
|     relaxColumnCount: true, | ||||
|     skipLinesWithEmptyValues: true | ||||
|   })) as Array<string[]>) { | ||||
|     if (output.length == 1) { | ||||
|       res.push(output[0]); | ||||
|       continue; | ||||
|     } else if (!ignoreComma) { | ||||
|       res.push(...output); | ||||
|       continue; | ||||
|   // check if provenance attestation is set in attests input | ||||
|   let hasAttestProvenance = false; | ||||
|   await Util.asyncForEach(inputs.attests, async (attest: string) => { | ||||
|     if (Build.hasAttestationType('provenance', attest)) { | ||||
|       hasAttestProvenance = true; | ||||
|     } | ||||
|     res.push(output.join(',')); | ||||
|   }); | ||||
|  | ||||
|   let provenanceSet = false; | ||||
|   let sbomSet = false; | ||||
|   if (inputs.provenance) { | ||||
|     args.push('--attest', Build.resolveAttestationAttrs(`type=provenance,${inputs.provenance}`)); | ||||
|     provenanceSet = true; | ||||
|   } else if (!hasAttestProvenance && (await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !Build.hasDockerExporter(inputs.outputs, inputs.load)) { | ||||
|     // if provenance not specified in provenance or attests inputs and BuildKit | ||||
|     // version compatible for attestation, set default provenance. Also needs | ||||
|     // to make sure user doesn't want to explicitly load the image to docker. | ||||
|     if (GitHub.context.payload.repository?.private ?? false) { | ||||
|       // if this is a private repository, we set the default provenance | ||||
|       // attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603 | ||||
|       args.push('--attest', `type=provenance,${Build.resolveProvenanceAttrs(`mode=min,inline-only=true`)}`); | ||||
|     } else { | ||||
|       // for a public repository, we set max provenance mode. | ||||
|       args.push('--attest', `type=provenance,${Build.resolveProvenanceAttrs(`mode=max`)}`); | ||||
|     } | ||||
|   } | ||||
|   if (inputs.sbom) { | ||||
|     args.push('--attest', Build.resolveAttestationAttrs(`type=sbom,${inputs.sbom}`)); | ||||
|     sbomSet = true; | ||||
|   } | ||||
|  | ||||
|   return res.filter(item => item).map(pat => pat.trim()); | ||||
|   // set attests but check if provenance or sbom types already set as | ||||
|   // provenance and sbom inputs take precedence over attests input. | ||||
|   await Util.asyncForEach(inputs.attests, async (attest: string) => { | ||||
|     if (!Build.hasAttestationType('provenance', attest) && !Build.hasAttestationType('sbom', attest)) { | ||||
|       args.push('--attest', Build.resolveAttestationAttrs(attest)); | ||||
|     } else if (!provenanceSet && Build.hasAttestationType('provenance', attest)) { | ||||
|       args.push('--attest', Build.resolveProvenanceAttrs(attest)); | ||||
|     } else if (!sbomSet && Build.hasAttestationType('sbom', attest)) { | ||||
|       args.push('--attest', attest); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   return args; | ||||
| } | ||||
|  | ||||
| export const asyncForEach = async (array, callback) => { | ||||
|   for (let index = 0; index < array.length; index++) { | ||||
|     await callback(array[index], index, array); | ||||
|   } | ||||
| }; | ||||
|   | ||||
| @@ -1,7 +0,0 @@ | ||||
| import * as exec from './exec'; | ||||
|  | ||||
| export async function isDaemonRunning(): Promise<boolean> { | ||||
|   return await exec.exec(`docker`, ['version', '--format', '{{.Server.Os}}'], true).then(res => { | ||||
|     return !res.stdout.includes(' ') && res.success; | ||||
|   }); | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/exec.ts
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/exec.ts
									
									
									
									
									
								
							| @@ -1,34 +0,0 @@ | ||||
| import * as aexec from '@actions/exec'; | ||||
| import {ExecOptions} from '@actions/exec'; | ||||
|  | ||||
| export interface ExecResult { | ||||
|   success: boolean; | ||||
|   stdout: string; | ||||
|   stderr: string; | ||||
| } | ||||
|  | ||||
| export const exec = async (command: string, args: string[] = [], silent?: boolean): Promise<ExecResult> => { | ||||
|   let stdout: string = ''; | ||||
|   let stderr: string = ''; | ||||
|  | ||||
|   const options: ExecOptions = { | ||||
|     silent: silent, | ||||
|     ignoreReturnCode: true | ||||
|   }; | ||||
|   options.listeners = { | ||||
|     stdout: (data: Buffer) => { | ||||
|       stdout += data.toString(); | ||||
|     }, | ||||
|     stderr: (data: Buffer) => { | ||||
|       stderr += data.toString(); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   const returnCode: number = await aexec.exec(command, args, options); | ||||
|  | ||||
|   return { | ||||
|     success: returnCode === 0, | ||||
|     stdout: stdout.trim(), | ||||
|     stderr: stderr.trim() | ||||
|   }; | ||||
| }; | ||||
							
								
								
									
										302
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										302
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -1,56 +1,284 @@ | ||||
| import * as fs from 'fs'; | ||||
| import * as os from 'os'; | ||||
| import * as buildx from './buildx'; | ||||
| import * as context from './context'; | ||||
| import * as exec from './exec'; | ||||
| import * as path from 'path'; | ||||
| import * as stateHelper from './state-helper'; | ||||
| import * as core from '@actions/core'; | ||||
| import * as actionsToolkit from '@docker/actions-toolkit'; | ||||
|  | ||||
| async function run(): Promise<void> { | ||||
|   try { | ||||
|     if (os.platform() !== 'linux') { | ||||
|       throw new Error(`Only supported on linux platform`); | ||||
|     } | ||||
| import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx'; | ||||
| import {History as BuildxHistory} from '@docker/actions-toolkit/lib/buildx/history'; | ||||
| import {Context} from '@docker/actions-toolkit/lib/context'; | ||||
| import {Docker} from '@docker/actions-toolkit/lib/docker/docker'; | ||||
| import {Exec} from '@docker/actions-toolkit/lib/exec'; | ||||
| import {GitHub} from '@docker/actions-toolkit/lib/github'; | ||||
| import {Toolkit} from '@docker/actions-toolkit/lib/toolkit'; | ||||
| import {Util} from '@docker/actions-toolkit/lib/util'; | ||||
|  | ||||
|     if (!(await buildx.isAvailable())) { | ||||
|       throw new Error(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`); | ||||
|     } | ||||
|     stateHelper.setTmpDir(context.tmpDir()); | ||||
| import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder'; | ||||
| import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker'; | ||||
| import {UploadArtifactResponse} from '@docker/actions-toolkit/lib/types/github'; | ||||
|  | ||||
|     const buildxVersion = await buildx.getVersion(); | ||||
|     core.info(`📣 Buildx version: ${buildxVersion}`); | ||||
| import * as context from './context'; | ||||
|  | ||||
|     const defContext = context.defaultContext(); | ||||
|     let inputs: context.Inputs = await context.getInputs(defContext); | ||||
| actionsToolkit.run( | ||||
|   // main | ||||
|   async () => { | ||||
|     const startedTime = new Date(); | ||||
|     const inputs: context.Inputs = await context.getInputs(); | ||||
|     core.debug(`inputs: ${JSON.stringify(inputs)}`); | ||||
|     stateHelper.setInputs(inputs); | ||||
|  | ||||
|     core.info(`🏃 Starting build...`); | ||||
|     const args: string[] = await context.getArgs(inputs, defContext, buildxVersion); | ||||
|     await exec.exec('docker', args).then(res => { | ||||
|       if (res.stderr != '' && !res.success) { | ||||
|         throw new Error(`buildx call failed with: ${res.stderr.match(/(.*)\s*$/)![0]}`); | ||||
|     const toolkit = new Toolkit(); | ||||
|  | ||||
|     await core.group(`GitHub Actions runtime token ACs`, async () => { | ||||
|       try { | ||||
|         await GitHub.printActionsRuntimeTokenACs(); | ||||
|       } catch (e) { | ||||
|         core.warning(e.message); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     const imageID = await buildx.getImageID(); | ||||
|     if (imageID) { | ||||
|       core.info('🛒 Extracting digest...'); | ||||
|       core.info(`${imageID}`); | ||||
|       core.setOutput('digest', imageID); | ||||
|     await core.group(`Docker info`, async () => { | ||||
|       try { | ||||
|         await Docker.printVersion(); | ||||
|         await Docker.printInfo(); | ||||
|       } catch (e) { | ||||
|         core.info(e.message); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     await core.group(`Proxy configuration`, async () => { | ||||
|       let dockerConfig: ConfigFile | undefined; | ||||
|       let dockerConfigMalformed = false; | ||||
|       try { | ||||
|         dockerConfig = await Docker.configFile(); | ||||
|       } catch (e) { | ||||
|         dockerConfigMalformed = true; | ||||
|         core.warning(`Unable to parse config file ${path.join(Docker.configDir, 'config.json')}: ${e}`); | ||||
|       } | ||||
|       if (dockerConfig && dockerConfig.proxies) { | ||||
|         for (const host in dockerConfig.proxies) { | ||||
|           let prefix = ''; | ||||
|           if (Object.keys(dockerConfig.proxies).length > 1) { | ||||
|             prefix = '  '; | ||||
|             core.info(host); | ||||
|           } | ||||
|           for (const key in dockerConfig.proxies[host]) { | ||||
|             core.info(`${prefix}${key}: ${dockerConfig.proxies[host][key]}`); | ||||
|           } | ||||
|         } | ||||
|       } else if (!dockerConfigMalformed) { | ||||
|         core.info('No proxy configuration found'); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     if (!(await toolkit.buildx.isAvailable())) { | ||||
|       core.setFailed(`Docker buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     stateHelper.setTmpDir(Context.tmpDir()); | ||||
|  | ||||
|     await core.group(`Buildx version`, async () => { | ||||
|       await toolkit.buildx.printVersion(); | ||||
|     }); | ||||
|  | ||||
|     let builder: BuilderInfo; | ||||
|     await core.group(`Builder info`, async () => { | ||||
|       builder = await toolkit.builder.inspect(inputs.builder); | ||||
|       core.info(JSON.stringify(builder, null, 2)); | ||||
|     }); | ||||
|  | ||||
|     const args: string[] = await context.getArgs(inputs, toolkit); | ||||
|     core.debug(`context.getArgs: ${JSON.stringify(args)}`); | ||||
|  | ||||
|     const buildCmd = await toolkit.buildx.getCommand(args); | ||||
|     core.debug(`buildCmd.command: ${buildCmd.command}`); | ||||
|     core.debug(`buildCmd.args: ${JSON.stringify(buildCmd.args)}`); | ||||
|  | ||||
|     let err: Error | undefined; | ||||
|     await Exec.getExecOutput(buildCmd.command, buildCmd.args, { | ||||
|       ignoreReturnCode: true, | ||||
|       env: Object.assign({}, process.env, { | ||||
|         BUILDX_METADATA_WARNINGS: 'true' | ||||
|       }) as { | ||||
|         [key: string]: string; | ||||
|       } | ||||
|     }).then(res => { | ||||
|       if (res.stderr.length > 0 && res.exitCode != 0) { | ||||
|         err = Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     const imageID = toolkit.buildxBuild.resolveImageID(); | ||||
|     const metadata = toolkit.buildxBuild.resolveMetadata(); | ||||
|     const digest = toolkit.buildxBuild.resolveDigest(metadata); | ||||
|     if (imageID) { | ||||
|       await core.group(`ImageID`, async () => { | ||||
|         core.info(imageID); | ||||
|         core.setOutput('imageid', imageID); | ||||
|       }); | ||||
|     } | ||||
|     if (digest) { | ||||
|       await core.group(`Digest`, async () => { | ||||
|         core.info(digest); | ||||
|         core.setOutput('digest', digest); | ||||
|       }); | ||||
|     } | ||||
|     if (metadata) { | ||||
|       await core.group(`Metadata`, async () => { | ||||
|         const metadatadt = JSON.stringify(metadata, null, 2); | ||||
|         core.info(metadatadt); | ||||
|         core.setOutput('metadata', metadatadt); | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     let ref: string | undefined; | ||||
|     await core.group(`Reference`, async () => { | ||||
|       ref = await buildRef(toolkit, startedTime, inputs.builder); | ||||
|       if (ref) { | ||||
|         core.info(ref); | ||||
|         stateHelper.setBuildRef(ref); | ||||
|       } else { | ||||
|         core.info('No build reference found'); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     if (buildChecksAnnotationsEnabled()) { | ||||
|       const warnings = toolkit.buildxBuild.resolveWarnings(metadata); | ||||
|       if (ref && warnings && warnings.length > 0) { | ||||
|         const annotations = await Buildx.convertWarningsToGitHubAnnotations(warnings, [ref]); | ||||
|         core.debug(`annotations: ${JSON.stringify(annotations, null, 2)}`); | ||||
|         if (annotations && annotations.length > 0) { | ||||
|           await core.group(`Generating GitHub annotations (${annotations.length} build checks found)`, async () => { | ||||
|             for (const annotation of annotations) { | ||||
|               core.warning(annotation.message, annotation); | ||||
|             } | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     await core.group(`Check build summary support`, async () => { | ||||
|       if (!buildSummaryEnabled()) { | ||||
|         core.info('Build summary disabled'); | ||||
|       } else if (GitHub.isGHES) { | ||||
|         core.warning('Build summary is not yet supported on GHES'); | ||||
|       } else if (!(await toolkit.buildx.versionSatisfies('>=0.13.0'))) { | ||||
|         core.warning('Build summary requires Buildx >= 0.13.0'); | ||||
|       } else if (builder && builder.driver === 'cloud') { | ||||
|         core.warning('Build summary is not yet supported with Docker Build Cloud'); | ||||
|       } else if (!ref) { | ||||
|         core.warning('Build summary requires a build reference'); | ||||
|       } else { | ||||
|         core.info('Build summary supported!'); | ||||
|         stateHelper.setSummarySupported(); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     if (err) { | ||||
|       throw err; | ||||
|     } | ||||
|   }, | ||||
|   // post | ||||
|   async () => { | ||||
|     if (stateHelper.isSummarySupported) { | ||||
|       await core.group(`Generating build summary`, async () => { | ||||
|         try { | ||||
|           const recordUploadEnabled = buildRecordUploadEnabled(); | ||||
|           let recordRetentionDays: number | undefined; | ||||
|           if (recordUploadEnabled) { | ||||
|             recordRetentionDays = buildRecordRetentionDays(); | ||||
|           } | ||||
|  | ||||
|           const buildxHistory = new BuildxHistory(); | ||||
|           const exportRes = await buildxHistory.export({ | ||||
|             refs: stateHelper.buildRef ? [stateHelper.buildRef] : [] | ||||
|           }); | ||||
|           core.info(`Build record written to ${exportRes.dockerbuildFilename} (${Util.formatFileSize(exportRes.dockerbuildSize)})`); | ||||
|  | ||||
|           let uploadRes: UploadArtifactResponse | undefined; | ||||
|           if (recordUploadEnabled) { | ||||
|             uploadRes = await GitHub.uploadArtifact({ | ||||
|               filename: exportRes.dockerbuildFilename, | ||||
|               mimeType: 'application/gzip', | ||||
|               retentionDays: recordRetentionDays | ||||
|             }); | ||||
|           } | ||||
|  | ||||
|           await GitHub.writeBuildSummary({ | ||||
|             exportRes: exportRes, | ||||
|             uploadRes: uploadRes, | ||||
|             inputs: stateHelper.inputs | ||||
|           }); | ||||
|         } catch (e) { | ||||
|           core.warning(e.message); | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|     if (stateHelper.tmpDir.length > 0) { | ||||
|       await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => { | ||||
|         fs.rmSync(stateHelper.tmpDir, {recursive: true}); | ||||
|       }); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     core.setFailed(error.message); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| async function buildRef(toolkit: Toolkit, since: Date, builder?: string): Promise<string> { | ||||
|   // get ref from metadata file | ||||
|   const ref = toolkit.buildxBuild.resolveRef(); | ||||
|   if (ref) { | ||||
|     return ref; | ||||
|   } | ||||
|   // otherwise, look for the very first build ref since the build has started | ||||
|   if (!builder) { | ||||
|     const currentBuilder = await toolkit.builder.inspect(); | ||||
|     builder = currentBuilder.name; | ||||
|   } | ||||
|   const refs = Buildx.refs({ | ||||
|     dir: Buildx.refsDir, | ||||
|     builderName: builder, | ||||
|     since: since | ||||
|   }); | ||||
|   return Object.keys(refs).length > 0 ? Object.keys(refs)[0] : ''; | ||||
| } | ||||
|  | ||||
| async function cleanup(): Promise<void> { | ||||
|   if (stateHelper.tmpDir.length > 0) { | ||||
|     core.info(`🚿 Removing temp folder ${stateHelper.tmpDir}`); | ||||
|     fs.rmdirSync(stateHelper.tmpDir, {recursive: true}); | ||||
| function buildChecksAnnotationsEnabled(): boolean { | ||||
|   if (process.env.DOCKER_BUILD_CHECKS_ANNOTATIONS) { | ||||
|     return Util.parseBool(process.env.DOCKER_BUILD_CHECKS_ANNOTATIONS); | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| if (!stateHelper.IsPost) { | ||||
|   run(); | ||||
| } else { | ||||
|   cleanup(); | ||||
| function buildSummaryEnabled(): boolean { | ||||
|   if (process.env.DOCKER_BUILD_NO_SUMMARY) { | ||||
|     core.warning('DOCKER_BUILD_NO_SUMMARY is deprecated. Set DOCKER_BUILD_SUMMARY to false instead.'); | ||||
|     return !Util.parseBool(process.env.DOCKER_BUILD_NO_SUMMARY); | ||||
|   } else if (process.env.DOCKER_BUILD_SUMMARY) { | ||||
|     return Util.parseBool(process.env.DOCKER_BUILD_SUMMARY); | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| function buildRecordUploadEnabled(): boolean { | ||||
|   if (process.env.DOCKER_BUILD_RECORD_UPLOAD) { | ||||
|     return Util.parseBool(process.env.DOCKER_BUILD_RECORD_UPLOAD); | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| function buildRecordRetentionDays(): number | undefined { | ||||
|   let val: string | undefined; | ||||
|   if (process.env.DOCKER_BUILD_EXPORT_RETENTION_DAYS) { | ||||
|     core.warning('DOCKER_BUILD_EXPORT_RETENTION_DAYS is deprecated. Use DOCKER_BUILD_RECORD_RETENTION_DAYS instead.'); | ||||
|     val = process.env.DOCKER_BUILD_EXPORT_RETENTION_DAYS; | ||||
|   } else if (process.env.DOCKER_BUILD_RECORD_RETENTION_DAYS) { | ||||
|     val = process.env.DOCKER_BUILD_RECORD_RETENTION_DAYS; | ||||
|   } | ||||
|   if (val) { | ||||
|     const res = parseInt(val); | ||||
|     if (isNaN(res)) { | ||||
|       throw Error(`Invalid build record retention days: ${val}`); | ||||
|     } | ||||
|     return res; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,24 @@ | ||||
| import * as core from '@actions/core'; | ||||
|  | ||||
| export const IsPost = !!process.env['STATE_isPost']; | ||||
| import {Inputs, sanitizeInputs} from './context'; | ||||
|  | ||||
| export const tmpDir = process.env['STATE_tmpDir'] || ''; | ||||
| export const inputs = process.env['STATE_inputs'] ? JSON.parse(process.env['STATE_inputs']) : undefined; | ||||
| export const buildRef = process.env['STATE_buildRef'] || ''; | ||||
| export const isSummarySupported = !!process.env['STATE_isSummarySupported']; | ||||
|  | ||||
| export function setTmpDir(tmpDir: string) { | ||||
|   core.saveState('tmpDir', tmpDir); | ||||
| } | ||||
|  | ||||
| if (!IsPost) { | ||||
|   core.saveState('isPost', 'true'); | ||||
| export function setInputs(inputs: Inputs) { | ||||
|   core.saveState('inputs', JSON.stringify(sanitizeInputs(inputs))); | ||||
| } | ||||
|  | ||||
| export function setBuildRef(buildRef: string) { | ||||
|   core.saveState('buildRef', buildRef); | ||||
| } | ||||
|  | ||||
| export function setSummarySupported() { | ||||
|   core.saveState('isSummarySupported', 'true'); | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM alpine | ||||
|  | ||||
| RUN echo "Hello world!" | ||||
|   | ||||
							
								
								
									
										3
									
								
								test/addhost.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/addhost.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM busybox | ||||
| RUN cat /etc/hosts | ||||
							
								
								
									
										3
									
								
								test/cgroup.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/cgroup.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM alpine | ||||
| RUN cat /proc/self/cgroup | ||||
							
								
								
									
										19
									
								
								test/go/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/go/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
|  | ||||
| FROM golang:alpine AS base | ||||
| ENV CGO_ENABLED=0 | ||||
| RUN apk add --no-cache file git | ||||
| WORKDIR /src | ||||
|  | ||||
| FROM base AS build | ||||
| RUN --mount=type=bind,target=/src \ | ||||
|     --mount=type=cache,target=/root/.cache/go-build \ | ||||
|     go build -ldflags "-s -w" -o /usr/bin/app . | ||||
|  | ||||
| FROM scratch AS binary | ||||
| COPY --from=build /usr/bin/app /bin/app | ||||
|  | ||||
| FROM alpine AS image | ||||
| COPY --from=build /usr/bin/app /bin/app | ||||
| EXPOSE 8080 | ||||
| ENTRYPOINT ["/bin/app"] | ||||
							
								
								
									
										3
									
								
								test/go/go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/go/go.mod
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| module github.com/docker/build-push-action/test/go | ||||
|  | ||||
| go 1.18 | ||||
							
								
								
									
										14
									
								
								test/go/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/go/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||||
| 		fmt.Fprintf(w, "Hello, Go!") | ||||
| 	}) | ||||
| 	log.Fatal(http.ListenAndServe(":8080", nil)) | ||||
| } | ||||
							
								
								
									
										12
									
								
								test/lint.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/lint.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| frOM busybox as base | ||||
| cOpy lint.Dockerfile . | ||||
|  | ||||
| from scratch | ||||
| MAINTAINER moby@example.com | ||||
| COPy --from=base \ | ||||
|   /lint.Dockerfile \ | ||||
|   / | ||||
|  | ||||
| CMD [ "echo", "Hello, Norway!" ] | ||||
| CMD [ "echo", "Hello, Sweden!" ] | ||||
| ENTRYPOINT my-program start | ||||
| @@ -1,9 +1,8 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM --platform=$BUILDPLATFORM golang:alpine AS build | ||||
| 
 | ||||
| ARG TARGETPLATFORM | ||||
| ARG BUILDPLATFORM | ||||
| RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log | ||||
| 
 | ||||
| RUN apk --update --no-cache add \ | ||||
|     shadow \ | ||||
|     sudo \ | ||||
| @@ -17,6 +16,5 @@ RUN sudo chown buildx. /log | ||||
| USER root | ||||
| 
 | ||||
| FROM alpine | ||||
| 
 | ||||
| COPY --from=build /log /log | ||||
| RUN ls -al /log | ||||
| @@ -1,3 +1,4 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM --platform=$BUILDPLATFORM golang:alpine AS build | ||||
| 
 | ||||
| ARG TARGETPLATFORM | ||||
							
								
								
									
										4
									
								
								test/named-context-base.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								test/named-context-base.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
|  | ||||
| FROM debian | ||||
| RUN echo "Hello debian!" | ||||
							
								
								
									
										4
									
								
								test/named-context.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								test/named-context.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
|  | ||||
| FROM alpine | ||||
| RUN cat /etc/*release | ||||
							
								
								
									
										9
									
								
								test/nocachefilter.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								test/nocachefilter.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM busybox AS base | ||||
| RUN echo "Hello world!" > /hello | ||||
|  | ||||
| FROM alpine AS build | ||||
| COPY --from=base /hello /hello | ||||
| RUN uname -a | ||||
|  | ||||
| FROM build | ||||
							
								
								
									
										9
									
								
								test/proxy.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								test/proxy.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM alpine | ||||
| RUN apk add --no-cache curl net-tools | ||||
| ARG HTTP_PROXY | ||||
| ARG HTTPS_PROXY | ||||
| RUN printenv HTTP_PROXY | ||||
| RUN printenv HTTPS_PROXY | ||||
| RUN netstat -aptn | ||||
| RUN curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy $HTTP_PROXY -v --insecure --head https://www.google.com | ||||
							
								
								
									
										4
									
								
								test/secret.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								test/secret.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM busybox | ||||
| RUN --mount=type=secret,id=MYSECRET \ | ||||
|   echo "MYSECRET=$(cat /run/secrets/MYSECRET)" | ||||
							
								
								
									
										3
									
								
								test/shmsize.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/shmsize.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM busybox | ||||
| RUN mount | grep /dev/shm | ||||
							
								
								
									
										3
									
								
								test/ulimit.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/ulimit.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM busybox | ||||
| RUN ulimit -a | ||||
| @@ -1,21 +1,22 @@ | ||||
| { | ||||
|   "compilerOptions": { | ||||
|     "esModuleInterop": true, | ||||
|     "target": "es6", | ||||
|     "module": "commonjs", | ||||
|     "lib": [ | ||||
|       "es6", | ||||
|       "dom" | ||||
|     ], | ||||
|     "strict": true, | ||||
|     "newLine": "lf", | ||||
|     "outDir": "./lib", | ||||
|     "rootDir": "./src", | ||||
|     "strict": true, | ||||
|     "forceConsistentCasingInFileNames": true, | ||||
|     "noImplicitAny": false, | ||||
|     "esModuleInterop": true, | ||||
|     "sourceMap": true | ||||
|     "resolveJsonModule": true, | ||||
|     "useUnknownInCatchVariables": false, | ||||
|   }, | ||||
|   "exclude": [ | ||||
|     "./__mocks__/**/*", | ||||
|     "./__tests__/**/*", | ||||
|     "./lib/**/*", | ||||
|     "node_modules", | ||||
|     "**/*.test.ts" | ||||
|     "jest.config.ts" | ||||
|   ] | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user