Compare commits
	
		
			201 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 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 | 
							
								
								
									
										23
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.eslintrc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| { | ||||
|   "env": { | ||||
|     "node": true, | ||||
|     "es2021": true, | ||||
|     "jest/globals": true | ||||
|   }, | ||||
|   "extends": [ | ||||
|     "eslint:recommended", | ||||
|     "plugin:@typescript-eslint/recommended", | ||||
|     "plugin:jest/recommended", | ||||
|     "plugin:prettier/recommended" | ||||
|   ], | ||||
|   "parser": "@typescript-eslint/parser", | ||||
|   "parserOptions": { | ||||
|     "ecmaVersion": "latest", | ||||
|     "sourceType": "module" | ||||
|   }, | ||||
|   "plugins": [ | ||||
|     "@typescript-eslint", | ||||
|     "jest", | ||||
|     "prettier" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							| @@ -5,7 +5,7 @@ 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). | ||||
| Before submitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md). | ||||
|  | ||||
| ### Behaviour | ||||
|  | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								.github/build-push-action.png
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								.github/build-push-action.png
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 19 KiB | 
							
								
								
									
										8
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							| @@ -5,8 +5,8 @@ updates: | ||||
|     schedule: | ||||
|       interval: "daily" | ||||
|     labels: | ||||
|       - ":game_die: dependencies" | ||||
|       - ":robot: bot" | ||||
|       - "dependencies" | ||||
|       - "bot" | ||||
|   - package-ecosystem: "npm" | ||||
|     directory: "/" | ||||
|     schedule: | ||||
| @@ -14,5 +14,5 @@ updates: | ||||
|     allow: | ||||
|       - dependency-type: "production" | ||||
|     labels: | ||||
|       - ":game_die: dependencies" | ||||
|       - ":robot: bot" | ||||
|       - "dependencies" | ||||
|       - "bot" | ||||
|   | ||||
							
								
								
									
										539
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										539
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -2,12 +2,25 @@ name: ci | ||||
|  | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|     inputs: | ||||
|       buildx-version: | ||||
|         description: 'Buildx version or Git context' | ||||
|         default: 'latest' | ||||
|         required: false | ||||
|       buildkit-image: | ||||
|         description: 'BuildKit image' | ||||
|         default: 'moby/buildkit:buildx-stable-1' | ||||
|         required: false | ||||
|   push: | ||||
|     branches: | ||||
|       - master | ||||
|       - 'master' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - master | ||||
|       - 'master' | ||||
|  | ||||
| env: | ||||
|   BUILDX_VERSION: latest | ||||
|   BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1 | ||||
|  | ||||
| jobs: | ||||
|   minimal: | ||||
| @@ -15,21 +28,21 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|         with: | ||||
|           path: action | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./action | ||||
|         with: | ||||
|           file: ./test/Dockerfile | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   git-context: | ||||
|     runs-on: ubuntu-latest | ||||
| @@ -41,19 +54,21 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|         with: | ||||
|           path: action | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: latest | ||||
|           driver-opts: network=host | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
| @@ -70,9 +85,6 @@ jobs: | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:1.0.0 | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest | ||||
|         run: | | ||||
| @@ -80,10 +92,6 @@ jobs: | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   git-context-secret: | ||||
|     runs-on: ubuntu-latest | ||||
| @@ -95,18 +103,21 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|         with: | ||||
|           path: action | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           driver-opts: network=host | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
| @@ -133,9 +144,6 @@ jobs: | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:1.0.0 | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest | ||||
|         run: | | ||||
| @@ -143,19 +151,9 @@ jobs: | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   path-context: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         buildx-version: | ||||
|           - "" | ||||
|           - latest | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
| @@ -164,17 +162,19 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ matrix.buildx-version }} | ||||
|           driver-opts: network=host | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
| @@ -191,9 +191,6 @@ jobs: | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:1.0.0 | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest | ||||
|         run: | | ||||
| @@ -201,17 +198,13 @@ jobs: | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   error: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Stop docker | ||||
|         run: | | ||||
| @@ -232,23 +225,23 @@ jobs: | ||||
|             echo "::error::Should have failed" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   error-buildx: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         id: docker_build | ||||
| @@ -268,10 +261,6 @@ jobs: | ||||
|             echo "::error::Should have failed" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   docker-driver: | ||||
|     runs-on: ubuntu-latest | ||||
| @@ -283,7 +272,7 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Build | ||||
|         id: docker_build | ||||
| @@ -293,17 +282,13 @@ jobs: | ||||
|           file: ./test/Dockerfile | ||||
|           push: true | ||||
|           tags: localhost:5000/name/app:latest | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   export-docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
| @@ -316,20 +301,43 @@ jobs: | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker image inspect myimage:latest | ||||
|  | ||||
|   secret: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: . | ||||
|           file: ./test/secret.Dockerfile | ||||
|           secrets: | | ||||
|             MYSECRET=foo | ||||
|             INVALID_SECRET= | ||||
|  | ||||
|   network: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: List networks | ||||
|         run: docker network ls | ||||
| @@ -340,19 +348,154 @@ jobs: | ||||
|           context: ./test | ||||
|           tags: name/app:latest | ||||
|           network: host | ||||
|  | ||||
|   shm-size: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/shmsize.Dockerfile | ||||
|           tags: name/app:latest | ||||
|           shm-size: 2g | ||||
|  | ||||
|   ulimit: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/ulimit.Dockerfile | ||||
|           tags: name/app:latest | ||||
|           ulimit: | | ||||
|             nofile=1024:1024 | ||||
|             nproc=3 | ||||
|  | ||||
|   cgroup-parent: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/cgroup.Dockerfile | ||||
|           tags: name/app:latest | ||||
|           cgroup-parent: foo | ||||
|  | ||||
|   add-hosts: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/addhost.Dockerfile | ||||
|           tags: name/app:latest | ||||
|           add-hosts: | | ||||
|             docker:10.180.0.1 | ||||
|             foo:10.0.0.1 | ||||
|  | ||||
|   build-contexts: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/buildcontext.Dockerfile | ||||
|           build-contexts: | | ||||
|             alpine=docker-image://debian:stable-slim | ||||
|           tags: name/app:latest | ||||
|  | ||||
|   no-cache-filters: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/nocachefilter.Dockerfile | ||||
|           no-cache-filters: build | ||||
|           tags: name/app:latest | ||||
|           cache-from: type=gha,scope=nocachefilter | ||||
|           cache-to: type=gha,scope=nocachefilter,mode=max | ||||
|  | ||||
|   multi: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         buildx-version: | ||||
|           - "" | ||||
|           - latest | ||||
|         dockerfile: | ||||
|           - multi | ||||
|           - multi-sudo | ||||
| @@ -364,17 +507,19 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ matrix.buildx-version }} | ||||
|           driver-opts: network=host | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
| @@ -392,9 +537,6 @@ jobs: | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:1.0.0 | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest | ||||
|         run: | | ||||
| @@ -402,10 +544,94 @@ jobs: | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|  | ||||
|   digest: | ||||
|     runs-on: ubuntu-latest | ||||
|     env: | ||||
|       DOCKER_IMAGE: localhost:5000/name/app | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         driver: | ||||
|           - docker | ||||
|           - docker-container | ||||
|         load: | ||||
|           - true | ||||
|           - false | ||||
|         push: | ||||
|           - true | ||||
|           - false | ||||
|         exclude: | ||||
|           - driver: docker | ||||
|             load: true | ||||
|             push: true | ||||
|           - driver: docker-container | ||||
|             load: true | ||||
|             push: true | ||||
|           - driver: docker | ||||
|             load: false | ||||
|             push: false | ||||
|           - driver: docker-container | ||||
|             load: false | ||||
|             push: false | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
|         ports: | ||||
|           - 5000:5000 | ||||
|     steps: | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver: ${{ matrix.driver }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|       - | ||||
|         name: Build | ||||
|         id: docker_build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           load: ${{ matrix.load }} | ||||
|           push: ${{ matrix.push }} | ||||
|           tags: ${{ env.DOCKER_IMAGE }}:latest | ||||
|           platforms: ${{ matrix.platforms }} | ||||
|       - | ||||
|         name: Docker images | ||||
|         run: | | ||||
|           docker image ls --no-trunc | ||||
|       - | ||||
|         name: Check digest | ||||
|         if: ${{ matrix.push }} | ||||
|         run: | | ||||
|           if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Check manifest | ||||
|         if: ${{ matrix.push }} | ||||
|         run: | | ||||
|           set -x | ||||
|           docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}@${{ steps.docker_build.outputs.digest }} --format '{{json .}}' | ||||
|       - | ||||
|         name: Check image ID | ||||
|         run: | | ||||
|           if [ -z "${{ steps.docker_build.outputs.imageid }}" ]; then | ||||
|             echo "::error::Image ID should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Inspect image | ||||
|         if: ${{ matrix.load }} | ||||
|         run: | | ||||
|           set -x | ||||
|           docker image inspect ${{ steps.docker_build.outputs.imageid }} | ||||
|  | ||||
|   registry-cache: | ||||
|     runs-on: ubuntu-latest | ||||
| @@ -417,17 +643,19 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Build and push (1) | ||||
|         id: docker_build | ||||
| @@ -447,9 +675,6 @@ jobs: | ||||
|         name: Inspect (1) | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:latest | ||||
|       - | ||||
|         name: Image digest (1) | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest (1) | ||||
|         run: | | ||||
| @@ -480,9 +705,6 @@ jobs: | ||||
|         name: Inspect (2) | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:latest | ||||
|       - | ||||
|         name: Image digest (2) | ||||
|         run: echo ${{ steps.docker_build2.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest (2) | ||||
|         run: | | ||||
| @@ -498,15 +720,9 @@ jobs: | ||||
|             echo "::error::Digests should be identical" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   github-cache-first: | ||||
|   github-cache: | ||||
|     runs-on: ubuntu-latest | ||||
|     outputs: | ||||
|       digest: ${{ steps.docker_build.outputs.digest }} | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
| @@ -515,135 +731,58 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|       - | ||||
|         name: Cache Docker layers | ||||
|         uses: actions/cache@v2 | ||||
|         with: | ||||
|           path: /tmp/.buildx-cache | ||||
|           key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }} | ||||
|           restore-keys: | | ||||
|             ${{ runner.os }}-buildx-ghcache- | ||||
|       - | ||||
|         name: Erase cache | ||||
|         run: | | ||||
|           rm -rf /tmp/.buildx-cache/* | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|           buildkitd-flags: --debug | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/multi.Dockerfile | ||||
|           builder: ${{ steps.buildx.outputs.name }} | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           push: true | ||||
|           tags: | | ||||
|             localhost:5000/name/app:latest | ||||
|             localhost:5000/name/app:1.0.0 | ||||
|           cache-from: type=local,src=/tmp/.buildx-cache | ||||
|           cache-to: type=local,dest=/tmp/.buildx-cache | ||||
|           cache-from: type=gha,scope=ci-${{ matrix.buildx_version }} | ||||
|           cache-to: type=gha,scope=ci-${{ matrix.buildx_version }} | ||||
|       - | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:1.0.0 | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest | ||||
|         run: | | ||||
|           if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   github-cache-hit: | ||||
|   standalone: | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: github-cache-first | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
|         ports: | ||||
|           - 5000:5000 | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         name: Uninstall moby cli | ||||
|         run: | | ||||
|           sudo apt-get purge -y moby-cli moby-buildx | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         id: buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Cache Docker layers | ||||
|         uses: actions/cache@v2 | ||||
|         id: cache | ||||
|         with: | ||||
|           path: /tmp/.buildx-cache | ||||
|           key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }} | ||||
|           restore-keys: | | ||||
|             ${{ runner.os }}-buildx-ghcache- | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
|         name: Build | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/multi.Dockerfile | ||||
|           builder: ${{ steps.buildx.outputs.name }} | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           push: true | ||||
|           tags: | | ||||
|             localhost:5000/name/app:latest | ||||
|             localhost:5000/name/app:1.0.0 | ||||
|           cache-from: type=local,src=/tmp/.buildx-cache | ||||
|           cache-to: type=local,dest=/tmp/.buildx-cache | ||||
|       - | ||||
|         name: Inspect | ||||
|         run: | | ||||
|           docker buildx imagetools inspect localhost:5000/name/app:1.0.0 | ||||
|       - | ||||
|         name: Image digest | ||||
|         run: echo ${{ steps.docker_build.outputs.digest }} | ||||
|       - | ||||
|         name: Check digest | ||||
|         run: | | ||||
|           if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then | ||||
|             echo "::error::Digest should not be empty" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Compare digests | ||||
|         run: | | ||||
|           echo Compare "${{ needs.github-cache-first.outputs.digest }}" with "${{ steps.docker_build.outputs.digest }}" | ||||
|           if [ "${{ needs.github-cache-first.outputs.digest }}" != "${{ steps.docker_build.outputs.digest }}" ]; then | ||||
|             echo "::error::Digests should be identical" | ||||
|             exit 1 | ||||
|           fi | ||||
|       - | ||||
|         name: Cache hit | ||||
|         run: echo ${{ steps.cache.outputs.cache-hit }} | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|           file: ./test/Dockerfile | ||||
|   | ||||
							
								
								
									
										40
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							| @@ -2,14 +2,27 @@ name: e2e | ||||
|  | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|     inputs: | ||||
|       buildx-version: | ||||
|         description: 'Buildx version or Git context' | ||||
|         default: 'latest' | ||||
|         required: false | ||||
|       buildkit-image: | ||||
|         description: 'BuildKit image' | ||||
|         default: 'moby/buildkit:buildx-stable-1' | ||||
|         required: false | ||||
|   schedule: | ||||
|     - cron: '0 10 * * *' # everyday at 10am | ||||
|     - cron: '0 10 * * *' | ||||
|   push: | ||||
|     branches: | ||||
|       - master | ||||
|       - 'master' | ||||
|     tags: | ||||
|       - v* | ||||
|  | ||||
| env: | ||||
|   BUILDX_VERSION: latest | ||||
|   BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1 | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
| @@ -52,26 +65,35 @@ jobs: | ||||
|             slug: gcr.io/sandbox-298914/test-docker-action | ||||
|             username_secret: GCR_USERNAME | ||||
|             password_secret: GCR_JSON_KEY | ||||
|           - | ||||
|             registry: officialgithubactions.azurecr.io | ||||
|             slug: officialgithubactions.azurecr.io/test-docker-action | ||||
|             username_secret: AZURE_CLIENT_ID | ||||
|             password_secret: AZURE_CLIENT_SECRET | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: meta | ||||
|         uses: docker/metadata-action@v3 | ||||
|         uses: docker/metadata-action@v4 | ||||
|         with: | ||||
|           images: ${{ matrix.slug }} | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||
|           driver-opts: | | ||||
|             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||
|       - | ||||
|         name: Login to Registry | ||||
|         if: github.event_name != 'pull_request' | ||||
|         uses: docker/login-action@v1 | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: ${{ matrix.registry }} | ||||
|           username: ${{ secrets[matrix.username_secret] }} | ||||
| @@ -99,7 +121,3 @@ jobs: | ||||
|         if: github.event_name != 'pull_request' | ||||
|         run: | | ||||
|           docker buildx imagetools inspect ${{ matrix.slug }}:${{ steps.meta.outputs.version }} | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|   | ||||
							
								
								
									
										14
									
								
								.github/workflows/example.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/example.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,9 +1,9 @@ | ||||
| # This workflow is provided just as an usage example and not for repo testing/verification | ||||
| # This workflow is provided just as an example and not for repo testing/verification | ||||
| name: example | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * 0' # everyday sunday at 10am | ||||
|     - cron: '0 10 * * 0' | ||||
|   push: | ||||
|     branches: | ||||
|       - '**' | ||||
| @@ -25,11 +25,11 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: meta | ||||
|         uses: docker/metadata-action@v3 | ||||
|         uses: docker/metadata-action@v4 | ||||
|         with: | ||||
|           images: ${{ env.DOCKER_IMAGE }} | ||||
|           tags: | | ||||
| @@ -42,7 +42,7 @@ jobs: | ||||
|             type=sha | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           driver-opts: network=host | ||||
|       - | ||||
| @@ -72,7 +72,3 @@ jobs: | ||||
|         if: github.event_name != 'pull_request' | ||||
|         run: | | ||||
|           docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta.outputs.version }} | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|   | ||||
							
								
								
									
										8
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -14,19 +14,19 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Validate | ||||
|         uses: docker/bake-action@v1 | ||||
|         uses: docker/bake-action@v2 | ||||
|         with: | ||||
|           targets: validate | ||||
|       - | ||||
|         name: Test | ||||
|         uses: docker/bake-action@v1 | ||||
|         uses: docker/bake-action@v2 | ||||
|         with: | ||||
|           targets: test | ||||
|       - | ||||
|         name: Upload coverage | ||||
|         uses: codecov/codecov-action@v1 | ||||
|         uses: codecov/codecov-action@v3 | ||||
|         with: | ||||
|           file: ./coverage/clover.xml | ||||
|   | ||||
							
								
								
									
										38
									
								
								.github/workflows/virtual-env.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								.github/workflows/virtual-env.yml
									
									
									
									
										vendored
									
									
								
							| @@ -3,7 +3,17 @@ name: virtual-env | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * *' # everyday at 10am | ||||
|     - cron: '0 10 * * *' | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|     paths: | ||||
|       - '.github/workflows/virtual-env.yml' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - 'master' | ||||
|     paths: | ||||
|       - '.github/workflows/virtual-env.yml' | ||||
|  | ||||
| jobs: | ||||
|   os: | ||||
| @@ -13,25 +23,49 @@ jobs: | ||||
|       matrix: | ||||
|         os: | ||||
|           - ubuntu-latest | ||||
|           - ubuntu-22.04 | ||||
|           - ubuntu-20.04 | ||||
|           - ubuntu-18.04 | ||||
|           - ubuntu-16.04 | ||||
|     steps: | ||||
|       - | ||||
|         name: File system | ||||
|         run: df -ah | ||||
|       - | ||||
|         name: Mounts | ||||
|         run: mount | ||||
|       - | ||||
|         name: Node info | ||||
|         run: node -p process | ||||
|       - | ||||
|         name: NPM version | ||||
|         run: npm version | ||||
|       - | ||||
|         name: List install packages | ||||
|         run: apt list --installed | ||||
|       - | ||||
|         name: Docker daemon conf | ||||
|         run: | | ||||
|           cat /etc/docker/daemon.json | ||||
|       - | ||||
|         name: Docker info | ||||
|         run: docker info | ||||
|       - | ||||
|         name: Docker version | ||||
|         run: docker version | ||||
|       - | ||||
|         name: Cgroups | ||||
|         run: | | ||||
|           sudo apt-get install -y cgroup-tools | ||||
|           lscgroup | ||||
|       - | ||||
|         name: buildx version | ||||
|         run: docker buildx version | ||||
|       - | ||||
|         name: containerd version | ||||
|         run: containerd --version | ||||
|       - | ||||
|         name: Docker images | ||||
|         run: docker image ls | ||||
|       - | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| { | ||||
|   "printWidth": 120, | ||||
|   "printWidth": 240, | ||||
|   "tabWidth": 2, | ||||
|   "useTabs": false, | ||||
|   "semi": true, | ||||
|   | ||||
							
								
								
									
										223
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										223
									
								
								README.md
									
									
									
									
									
								
							| @@ -4,20 +4,12 @@ | ||||
| [](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. | ||||
| 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,51 +23,51 @@ ___ | ||||
|   * [Secrets](docs/advanced/secrets.md) | ||||
|   * [Isolated builders](docs/advanced/isolated-builders.md) | ||||
|   * [Push to multi-registries](docs/advanced/push-multi-registries.md) | ||||
|   * [Copy between registries](docs/advanced/copy-between-registries.md)   | ||||
|   * [Copy between registries](docs/advanced/copy-between-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) | ||||
|   * [Share built image between jobs](docs/advanced/share-image-jobs.md) | ||||
|   * [Test your image before pushing it](docs/advanced/test-before-push.md) | ||||
|   * [Named contexts](docs/advanced/named-contexts.md) | ||||
|   * [Handle tags and labels](docs/advanced/tags-labels.md) | ||||
|   * [Update DockerHub repo description](docs/advanced/dockerhub-desc.md) | ||||
|   * [Update Docker Hub repo description](docs/advanced/dockerhub-desc.md) | ||||
| * [Customizing](#customizing) | ||||
|   * [inputs](#inputs) | ||||
|   * [outputs](#outputs) | ||||
| * [Troubleshooting](#troubleshooting) | ||||
| * [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot) | ||||
| * [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/blob/master/docs/reference/buildx_create.md#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/login-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' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -83,37 +75,67 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         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@v3 | ||||
|         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 | ||||
|       - | ||||
|         # Setting up Docker Buildx with docker-container driver is required | ||||
|         # at the moment to be able to use a subdirectory with Git context | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: "{{defaultContext}}:mysubdir" | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
| ``` | ||||
|  | ||||
| > **Warning** | ||||
| > | ||||
| > Subdirectory for Git context is available from [BuildKit v0.9.0](https://github.com/moby/buildkit/releases/tag/v0.9.0). | ||||
| > If you're using the `docker` builder (default if `setup-buildx-action` not used), | ||||
| > then BuildKit in Docker Engine will be used. As Docker Engine < v22.x.x embeds | ||||
| > Buildkit 0.8.2 at the moment, it does not support this feature. It's therefore | ||||
| > required to use the `setup-buildx-action` at the moment. | ||||
|  | ||||
| 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](docs/advanced/secrets.md) named | ||||
| `GIT_AUTH_TOKEN` to be able to authenticate against it with Buildx: | ||||
|  | ||||
| ```yaml | ||||
|       - | ||||
|         name: Build and push | ||||
|         id: docker_build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
| @@ -121,9 +143,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 | ||||
| @@ -132,7 +151,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -140,22 +159,22 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1 | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
| @@ -170,13 +189,13 @@ jobs: | ||||
| * [Push to multi-registries](docs/advanced/push-multi-registries.md) | ||||
| * [Copy between registries](docs/advanced/copy-between-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) | ||||
| * [Share built image between jobs](docs/advanced/share-image-jobs.md) | ||||
| * [Test your image before pushing it](docs/advanced/test-before-push.md) | ||||
| * [Named contexts](docs/advanced/named-contexts.md) | ||||
| * [Handle tags and labels](docs/advanced/tags-labels.md) | ||||
| * [Update DockerHub repo description](docs/advanced/dockerhub-desc.md) | ||||
| * [Update Docker Hub repo description](docs/advanced/dockerhub-desc.md) | ||||
|  | ||||
| ## Customizing | ||||
|  | ||||
| @@ -196,53 +215,55 @@ Following inputs can be used as `step.with` keys | ||||
| > tags: name/app:latest,name/app:1.0.0 | ||||
| > ``` | ||||
|  | ||||
| | Name                | Type     | Description                        | | ||||
| |---------------------|----------|------------------------------------| | ||||
| | `allow`             | List/CSV | List of [extra privileged entitlement](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#allow) (eg. `network.host,security.insecure`) | | ||||
| | `builder`           | String   | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) | | ||||
| | `build-args`        | List     | List of build-time variables | | ||||
| | `cache-from`        | List     | List of [external cache sources](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from) (eg. `type=local,src=path/to/dir`) | | ||||
| | `cache-to`          | List     | List of [cache export destinations](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-to) (eg. `type=local,dest=path/to/dir`) | | ||||
| | `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://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#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`) | | ||||
| | `outputs`           | List     | List of [output destinations](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#output) (format: `type=local,dest=path`) | | ||||
| | `platforms`         | List/CSV | List of [target platforms](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#platform) for build | | ||||
| | `pull`              | Bool     | Always attempt to pull a newer version of the image (default `false`) | | ||||
| | `push`              | Bool     | [Push](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#push) is a shorthand for `--output=type=registry` (default `false`) | | ||||
| | `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 | | ||||
| | `tags`              | List/CSV | List of tags | | ||||
| | `target`            | String   | Sets the target stage to 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`)                         | | ||||
| | `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                                                                 | | ||||
| | `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`)                                     | | ||||
| | `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-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 }}`)                                                            | | ||||
|  | ||||
| > **Note** | ||||
| > | ||||
| > * ¹ multiple `outputs` are [not yet supported](https://github.com/moby/buildkit/issues/1555) | ||||
|  | ||||
| ### outputs | ||||
|  | ||||
| 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 | | ||||
|  | ||||
| ## 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" | ||||
| ``` | ||||
| Want to contribute? Awesome! You can find information about contributing to | ||||
| this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| * [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) | ||||
|  | ||||
| ## Cannot push to a registry | ||||
|  | ||||
| @@ -14,9 +15,11 @@ 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. | ||||
|  | ||||
| ### BuildKit container logs | ||||
|  | ||||
| @@ -25,8 +28,9 @@ action step and attach BuildKit container logs to your issue. | ||||
|  | ||||
| ### 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. | ||||
| 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 | ||||
| @@ -40,21 +44,21 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         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@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
| @@ -69,3 +73,65 @@ 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@v3 | ||||
|   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@v3 | ||||
|   with: | ||||
|     context: . | ||||
|     push: true | ||||
|     tags: ${{ steps.repo_slug.outputs.result }}:latest | ||||
| ``` | ||||
|   | ||||
							
								
								
									
										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` input to support multi-platform builds | ||||
| * Add `allow` input | ||||
| * Add `load` input | ||||
| * Add `outputs` input | ||||
| * Add `cache-from` input (`cache_froms` removed) | ||||
| * Add `cache-to` 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. | ||||
| @@ -1,13 +1,17 @@ | ||||
| import {describe, expect, it, jest, test} from '@jest/globals'; | ||||
| import * as fs from 'fs'; | ||||
| import * as path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
|  | ||||
| import * as exec from '@actions/exec'; | ||||
| 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'; | ||||
| const imageID = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9'; | ||||
| const metadata = `{ | ||||
|   "containerimage.config.digest": "sha256:059b68a595b22564a1cbc167af369349fdc2ecc1f7bc092c2235cbf601a795fd", | ||||
|   "containerimage.digest": "sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c" | ||||
| }`; | ||||
|  | ||||
| jest.spyOn(context, 'tmpDir').mockImplementation((): string => { | ||||
|   const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep); | ||||
| @@ -24,96 +28,92 @@ jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => { | ||||
| 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); | ||||
|     await fs.writeFileSync(imageIDFile, imageID); | ||||
|     const expected = await buildx.getImageID(); | ||||
|     expect(expected).toEqual(imageID); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('getMetadata', () => { | ||||
|   it('matches', async () => { | ||||
|     const metadataFile = await buildx.getMetadataFile(); | ||||
|     await fs.writeFileSync(metadataFile, metadata); | ||||
|     const expected = await buildx.getMetadata(); | ||||
|     expect(expected).toEqual(metadata); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('getDigest', () => { | ||||
|   it('matches', async () => { | ||||
|     const metadataFile = await buildx.getMetadataFile(); | ||||
|     await fs.writeFileSync(metadataFile, metadata); | ||||
|     const expected = await buildx.getDigest(metadata); | ||||
|     expect(expected).toEqual('sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c'); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| 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); | ||||
|     } | ||||
|   ); | ||||
|     [['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('isAvailable', () => { | ||||
|   const execSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|   buildx.isAvailable(); | ||||
|  | ||||
|   // eslint-disable-next-line jest/no-standalone-expect | ||||
|   expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], { | ||||
|     silent: true, | ||||
|     ignoreReturnCode: true | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('isAvailable standalone', () => { | ||||
|   const execSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|   buildx.isAvailable(true); | ||||
|  | ||||
|   // eslint-disable-next-line jest/no-standalone-expect | ||||
|   expect(execSpy).toHaveBeenCalledWith(`buildx`, [], { | ||||
|     silent: true, | ||||
|     ignoreReturnCode: true | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| 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 | ||||
|   ); | ||||
|   it('valid', async () => { | ||||
|     const version = await buildx.getVersion(); | ||||
|     expect(semver.valid(version)).not.toBeNull(); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| 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'] | ||||
|     ['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'], | ||||
|     ['github.com/docker/buildx f117971 f11797113e5a9b86bd976329c5dbb8a8bfdfadfa', 'f117971'] | ||||
|   ])('given %p', async (stdout, expected) => { | ||||
|     expect(await buildx.parseVersion(stdout)).toEqual(expected); | ||||
|     expect(buildx.parseVersion(stdout)).toEqual(expected); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('satisfies', () => { | ||||
|   test.each([ | ||||
|     ['0.4.1', '>=0.3.2', true], | ||||
|     ['bda4882a65349ca359216b135896bddc1d92461c', '>0.1.0', false], | ||||
|     ['f117971', '>0.6.0', true] | ||||
|   ])('given %p', async (version, range, expected) => { | ||||
|     expect(buildx.satisfies(version, range)).toBe(expected); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| @@ -125,13 +125,7 @@ describe('getSecret', () => { | ||||
|     ['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 | ||||
|     ], | ||||
|     [`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 { | ||||
| @@ -142,12 +136,10 @@ describe('getSecret', () => { | ||||
|         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); | ||||
|       expect(fs.readFileSync(tmpNameSync, 'utf-8')).toEqual(exValue); | ||||
|     } catch (err) { | ||||
|       // eslint-disable-next-line jest/no-conditional-expect | ||||
|       expect(true).toBe(invalid); | ||||
|     } | ||||
|   }); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {beforeEach, describe, expect, it, jest, test} from '@jest/globals'; | ||||
| import * as fs from 'fs'; | ||||
| import * as os from 'os'; | ||||
| import * as path from 'path'; | ||||
|  | ||||
| import * as context from '../src/context'; | ||||
| @@ -140,24 +140,32 @@ describe('getArgs', () => { | ||||
|   // prettier-ignore | ||||
|   test.each([ | ||||
|     [ | ||||
|       0, | ||||
|       '0.4.1', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       1, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['build-args', 'MY_ARG=val1,val2,val3\nARG=val'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--build-arg', 'MY_ARG=val1,val2,val3', | ||||
|         '--build-arg', 'ARG=val', | ||||
| @@ -166,28 +174,36 @@ describe('getArgs', () => { | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       2, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['tags', 'name/app:7.4, name/app:latest'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--tag', 'name/app:7.4', | ||||
|         '--tag', 'name/app:latest', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         'https://github.com/docker/build-push-action.git#refs/heads/test-jest' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       3, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['labels', 'org.opencontainers.image.title=buildkit\norg.opencontainers.image.description=concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit'], | ||||
|         ['outputs', 'type=local,dest=./release-out'] | ||||
|         ['outputs', 'type=local,dest=./release-out'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--label', 'org.opencontainers.image.title=buildkit', | ||||
|         '--label', 'org.opencontainers.image.description=concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit', | ||||
| @@ -196,38 +212,50 @@ describe('getArgs', () => { | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       4, | ||||
|       '0.4.1', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['platforms', 'linux/amd64,linux/arm64'] | ||||
|         ['platforms', 'linux/amd64,linux/arm64'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       5, | ||||
|       '0.4.1', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'] | ||||
|         ['context', '.'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       6, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
| @@ -235,13 +263,17 @@ describe('getArgs', () => { | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       7, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['github-token', 'abcdefghijklmno0123456789'], | ||||
|         ['outputs', '.'] | ||||
|         ['outputs', '.'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--output', '.', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
| @@ -249,6 +281,7 @@ describe('getArgs', () => { | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       8, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'], | ||||
| @@ -257,21 +290,24 @@ describe('getArgs', () => { | ||||
|         ['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['builder', 'builder-git-context-2'], | ||||
|         ['push', 'true'] | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'true'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--builder', 'builder-git-context-2', | ||||
|         '--push', | ||||
|         'https://github.com/docker/build-push-action.git#refs/heads/master' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       9, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'], | ||||
| @@ -288,24 +324,27 @@ bbbb | ||||
| ccc"`], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['builder', 'builder-git-context-2'], | ||||
|         ['push', 'true'] | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'true'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--secret', 'id=MYSECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--secret', 'id=FOO,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--secret', 'id=EMPTYLINE,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--builder', 'builder-git-context-2', | ||||
|         '--push', | ||||
|         'https://github.com/docker/build-push-action.git#refs/heads/master' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       10, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'], | ||||
| @@ -322,24 +361,27 @@ bbbb | ||||
| ccc`], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['builder', 'builder-git-context-2'], | ||||
|         ['push', 'true'] | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'true'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--platform', 'linux/amd64,linux/arm64', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--secret', 'id=MYSECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--secret', 'id=FOO,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--secret', 'id=EMPTYLINE,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--builder', 'builder-git-context-2', | ||||
|         '--push', | ||||
|         'https://github.com/docker/build-push-action.git#refs/heads/master' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       11, | ||||
|       '0.5.1', | ||||
|       new Map<string, string>([ | ||||
|         ['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'], | ||||
| @@ -348,14 +390,16 @@ ccc`], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['builder', 'builder-git-context-2'], | ||||
|         ['network', 'host'], | ||||
|         ['push', 'true'] | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'true'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--secret', 'id=MY_SECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--builder', 'builder-git-context-2', | ||||
|         '--network', 'host', | ||||
|         '--push', | ||||
| @@ -363,32 +407,126 @@ ccc`], | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       12, | ||||
|       '0.4.2', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['labels', 'org.opencontainers.image.title=filter_results_top_n\norg.opencontainers.image.description=Reference implementation of operation "filter results (top-n)"'], | ||||
|         ['outputs', 'type=local,dest=./release-out'] | ||||
|         ['outputs', 'type=local,dest=./release-out'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--label', 'org.opencontainers.image.title=filter_results_top_n', | ||||
|         '--label', 'org.opencontainers.image.description=Reference implementation of operation "filter results (top-n)"', | ||||
|         '--output', 'type=local,dest=./release-out', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       13, | ||||
|       '0.6.0', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['tag', 'localhost:5000/name/app:latest'], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['add-hosts', 'docker:10.180.0.1,foo:10.0.0.1'], | ||||
|         ['network', 'host'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'true'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'build', | ||||
|         '--add-host', 'docker:10.180.0.1', | ||||
|         '--add-host', 'foo:10.0.0.1', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||
|         '--network', 'host', | ||||
|         '--push', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       14, | ||||
|       '0.7.0', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['add-hosts', 'docker:10.180.0.1\nfoo:10.0.0.1'], | ||||
|         ['cgroup-parent', 'foo'], | ||||
|         ['shm-size', '2g'], | ||||
|         ['ulimit', `nofile=1024:1024 | ||||
| nproc=3`], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'build', | ||||
|         '--add-host', 'docker:10.180.0.1', | ||||
|         '--add-host', 'foo:10.0.0.1', | ||||
|         '--cgroup-parent', 'foo', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--shm-size', '2g', | ||||
|         '--ulimit', 'nofile=1024:1024', | ||||
|         '--ulimit', 'nproc=3', | ||||
|         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       15, | ||||
|       '0.7.0', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '{{defaultContext}}:docker'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||
|         'https://github.com/docker/build-push-action.git#refs/heads/test-jest:docker' | ||||
|       ] | ||||
|     ], | ||||
|     [ | ||||
|       16, | ||||
|       '0.8.2', | ||||
|       new Map<string, string>([ | ||||
|         ['github-token', 'abcdefghijklmno0123456789'], | ||||
|         ['context', '{{defaultContext}}:subdir'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'false'], | ||||
|         ['pull', 'false'], | ||||
|       ]), | ||||
|       [ | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest', | ||||
|         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||
|         'https://github.com/docker/build-push-action.git#refs/heads/test-jest:subdir' | ||||
|       ] | ||||
|     ] | ||||
|   ])( | ||||
|     'given %p with %p as inputs, returns %p', | ||||
|     async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => { | ||||
|       await inputs.forEach((value: string, name: string) => { | ||||
|     '[%d] given %p with %p as inputs, returns %p', | ||||
|     async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => { | ||||
|       inputs.forEach((value: string, name: string) => { | ||||
|         setInput(name, value); | ||||
|       }); | ||||
|       const defContext = context.defaultContext(); | ||||
|       const inp = await context.getInputs(defContext); | ||||
|       console.log(inp); | ||||
|       const res = await context.getArgs(inp, defContext, buildxVersion); | ||||
|       console.log(res); | ||||
|       expect(res).toEqual(expected); | ||||
|     } | ||||
|   ); | ||||
| @@ -398,63 +536,54 @@ describe('getInputList', () => { | ||||
|   it('single line correctly', async () => { | ||||
|     await setInput('foo', 'bar'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar']); | ||||
|   }); | ||||
|  | ||||
|   it('multiline correctly', async () => { | ||||
|     setInput('foo', 'bar\nbaz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
|  | ||||
|   it('empty lines correctly', async () => { | ||||
|     setInput('foo', 'bar\n\nbaz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
|  | ||||
|   it('comma correctly', async () => { | ||||
|     setInput('foo', 'bar,baz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
|  | ||||
|   it('empty result correctly', async () => { | ||||
|     setInput('foo', 'bar,baz,'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
|  | ||||
|   it('different new lines correctly', async () => { | ||||
|     setInput('foo', 'bar\r\nbaz'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz']); | ||||
|   }); | ||||
|  | ||||
|   it('different new lines and comma correctly', async () => { | ||||
|     setInput('foo', 'bar\r\nbaz,bat'); | ||||
|     const res = await context.getInputList('foo'); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['bar', 'baz', 'bat']); | ||||
|   }); | ||||
|  | ||||
|   it('multiline and ignoring comma correctly', async () => { | ||||
|     setInput('cache-from', 'user/app:cache\ntype=local,src=path/to/dir'); | ||||
|     const res = await context.getInputList('cache-from', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']); | ||||
|   }); | ||||
|  | ||||
|   it('different new lines and ignoring comma correctly', async () => { | ||||
|     setInput('cache-from', 'user/app:cache\r\ntype=local,src=path/to/dir'); | ||||
|     const res = await context.getInputList('cache-from', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']); | ||||
|   }); | ||||
|  | ||||
| @@ -468,7 +597,6 @@ ccccccccc" | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       `MYSECRET=aaaaaaaa | ||||
| @@ -492,7 +620,6 @@ bbbb | ||||
| ccc"` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       `MYSECRET=aaaaaaaa | ||||
| @@ -516,14 +643,7 @@ ccccccccc | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       'MYSECRET=aaaaaaaa', | ||||
|       'bbbbbbb', | ||||
|       'ccccccccc', | ||||
|       'FOO=bar' | ||||
|     ]); | ||||
|     expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']); | ||||
|   }); | ||||
|  | ||||
|   it('large multiline values', async () => { | ||||
| @@ -533,7 +653,6 @@ FOO=bar` | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([`GPG_KEY=${pgp}`, 'FOO=bar']); | ||||
|   }); | ||||
|  | ||||
| @@ -547,11 +666,10 @@ ccccccccc" | ||||
| FOO=bar` | ||||
|     ); | ||||
|     const res = await context.getInputList('secrets', true); | ||||
|     console.log(res); | ||||
|     expect(res).toEqual([ | ||||
|       'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', | ||||
|       `MYSECRET=aaaaaaaa | ||||
| bbbb\"bbb | ||||
| bbbb"bbb | ||||
| ccccccccc`, | ||||
|       'FOO=bar' | ||||
|     ]); | ||||
| @@ -571,28 +689,7 @@ describe('asyncForEach', () => { | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('setOutput', () => { | ||||
|   beforeEach(() => { | ||||
|     process.stdout.write = jest.fn(); | ||||
|   }); | ||||
|  | ||||
|   it('setOutput produces the correct command', () => { | ||||
|     context.setOutput('some output', 'some value'); | ||||
|     assertWriteCalls([`::set-output name=some output::some value${os.EOL}`]); | ||||
|   }); | ||||
|  | ||||
|   it('setOutput handles bools', () => { | ||||
|     context.setOutput('some output', false); | ||||
|     assertWriteCalls([`::set-output name=some output::false${os.EOL}`]); | ||||
|   }); | ||||
|  | ||||
|   it('setOutput handles numbers', () => { | ||||
|     context.setOutput('some output', 1.01); | ||||
|     assertWriteCalls([`::set-output name=some output::1.01${os.EOL}`]); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| // See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67 | ||||
| // See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89 | ||||
| function getInputName(name: string): string { | ||||
|   return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`; | ||||
| } | ||||
| @@ -600,11 +697,3 @@ function getInputName(name: string): string { | ||||
| function setInput(name: string, value: string): void { | ||||
|   process.env[getInputName(name)] = value; | ||||
| } | ||||
|  | ||||
| // Assert that process.stdout.write calls called only with the given arguments. | ||||
| function assertWriteCalls(calls: string[]): void { | ||||
|   expect(process.stdout.write).toHaveBeenCalledTimes(calls.length); | ||||
|   for (let i = 0; i < calls.length; i++) { | ||||
|     expect(process.stdout.write).toHaveBeenNthCalledWith(i + 1, calls[i]); | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								__tests__/docker.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								__tests__/docker.test.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| import {describe, expect, it, jest} from '@jest/globals'; | ||||
| import * as docker from '../src/docker'; | ||||
| import * as exec from '@actions/exec'; | ||||
|  | ||||
| describe('isAvailable', () => { | ||||
|   it('cli', () => { | ||||
|     const execSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|     docker.isAvailable(); | ||||
|  | ||||
|     // eslint-disable-next-line jest/no-standalone-expect | ||||
|     expect(execSpy).toHaveBeenCalledWith(`docker`, undefined, { | ||||
|       silent: true, | ||||
|       ignoreReturnCode: true | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										38
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								action.yml
									
									
									
									
									
								
							| @@ -7,20 +7,29 @@ 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 (eg. network.host,security.insecure)" | ||||
|     description: "List of extra privileged entitlement (e.g., network.host,security.insecure)" | ||||
|     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 (eg. user/app:cache, type=local,src=path/to/dir)" | ||||
|     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 (eg. user/app:cache, type=local,dest=path/to/dir)" | ||||
|     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" | ||||
| @@ -42,6 +51,9 @@ inputs: | ||||
|     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 | ||||
| @@ -49,7 +61,7 @@ inputs: | ||||
|     description: "List of target platforms for build" | ||||
|     required: false | ||||
|   pull: | ||||
|     description: "Always attempt to pull a newer version of the image" | ||||
|     description: "Always attempt to pull all referenced images" | ||||
|     required: false | ||||
|     default: 'false' | ||||
|   push: | ||||
| @@ -57,10 +69,13 @@ inputs: | ||||
|     required: false | ||||
|     default: '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-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" | ||||
| @@ -71,16 +86,23 @@ inputs: | ||||
|   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: 'node16' | ||||
|   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 | ||||
							
								
								
									
										78
									
								
								dev.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								dev.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
|  | ||||
| ARG NODE_VERSION=16 | ||||
| ARG DOCKER_VERSION=20.10.13 | ||||
| ARG BUILDX_VERSION=0.8.0 | ||||
|  | ||||
| FROM node:${NODE_VERSION}-alpine AS base | ||||
| RUN apk add --no-cache cpio findutils git | ||||
| WORKDIR /src | ||||
|  | ||||
| FROM base AS deps | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --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/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/node_modules \ | ||||
|   yarn run format \ | ||||
|   && mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | 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/node_modules \ | ||||
|   yarn run lint | ||||
|  | ||||
| FROM docker:${DOCKER_VERSION} as docker | ||||
| FROM docker/buildx-bin:${BUILDX_VERSION} as buildx | ||||
|  | ||||
| FROM deps AS test | ||||
| ENV RUNNER_TEMP=/tmp/github_runner | ||||
| ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   --mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \ | ||||
|   --mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \ | ||||
|   yarn run test --coverageDirectory=/tmp/coverage | ||||
|  | ||||
| FROM scratch AS test-coverage | ||||
| COPY --from=test /tmp/coverage / | ||||
							
								
								
									
										16962
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16962
									
								
								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
											
										
									
								
							
							
								
								
									
										1058
									
								
								dist/licenses.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1058
									
								
								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
											
										
									
								
							| @@ -1,13 +1,3 @@ | ||||
| variable "NODE_VERSION" { | ||||
|   default = "12" | ||||
| } | ||||
|  | ||||
| target "node-version" { | ||||
|   args = { | ||||
|     NODE_VERSION = NODE_VERSION | ||||
|   } | ||||
| } | ||||
|  | ||||
| group "default" { | ||||
|   targets = ["build"] | ||||
| } | ||||
| @@ -17,51 +7,47 @@ group "pre-checkin" { | ||||
| } | ||||
|  | ||||
| group "validate" { | ||||
|   targets = ["format-validate", "build-validate", "vendor-validate"] | ||||
|   targets = ["lint", "build-validate", "vendor-validate"] | ||||
| } | ||||
|  | ||||
| target "build" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/build.Dockerfile" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "build-update" | ||||
|   output = ["."] | ||||
| } | ||||
|  | ||||
| target "build-validate" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/build.Dockerfile" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "build-validate" | ||||
|   output = ["type=cacheonly"] | ||||
| } | ||||
|  | ||||
| target "format" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/build.Dockerfile" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "format-update" | ||||
|   output = ["."] | ||||
| } | ||||
|  | ||||
| target "format-validate" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/build.Dockerfile" | ||||
|   target = "format-validate" | ||||
| target "lint" { | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "lint" | ||||
|   output = ["type=cacheonly"] | ||||
| } | ||||
|  | ||||
| target "vendor-update" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/vendor.Dockerfile" | ||||
|   target = "update" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "vendor-update" | ||||
|   output = ["."] | ||||
| } | ||||
|  | ||||
| target "vendor-validate" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/vendor.Dockerfile" | ||||
|   target = "validate" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "vendor-validate" | ||||
|   output = ["type=cacheonly"] | ||||
| } | ||||
|  | ||||
| target "test" { | ||||
|   inherits = ["node-version"] | ||||
|   dockerfile = "./hack/test.Dockerfile" | ||||
|   dockerfile = "dev.Dockerfile" | ||||
|   target = "test-coverage" | ||||
|   output = ["./coverage"] | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,21 @@ | ||||
| # Cache | ||||
|  | ||||
| * [Inline cache](#inline-cache) | ||||
| * [Registry cache](#registry-cache) | ||||
| * [GitHub cache](#github-cache) | ||||
|   * [Cache backend API](#cache-backend-api) | ||||
|   * [Local cache](#local-cache) | ||||
|  | ||||
| > More info about buildx cache: https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from | ||||
| > **Note** | ||||
| > | ||||
| > See [our guide](https://github.com/docker/buildx/blob/master/docs/guides/cache/index.md) | ||||
| > for more details about cache storage backends. | ||||
|  | ||||
| ## Registry cache | ||||
| ## Inline cache | ||||
|  | ||||
| You can import/export cache from a cache manifest or (special) image configuration on the registry. | ||||
| In most cases you want to use the [`type=inline` cache exporter](https://github.com/docker/buildx/blob/master/docs/guides/cache/inline.md). | ||||
| However, note that the `inline` cache exporter only supports `min` cache mode. To enable `max` cache mode, push the | ||||
| image and the cache separately by using the `registry` cache exporter as shown in the [next example](#registry-cache). | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
| @@ -15,7 +23,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -23,19 +31,19 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
| @@ -44,16 +52,10 @@ jobs: | ||||
|           cache-to: type=inline | ||||
| ``` | ||||
|  | ||||
| ## GitHub cache | ||||
| ## Registry 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: | ||||
| You can import/export cache from a cache manifest or (special) image configuration on the registry with the | ||||
| [`type=registry` cache exporter](https://github.com/docker/buildx/blob/master/docs/guides/cache/registry.md). | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
| @@ -61,7 +63,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -69,33 +71,131 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|           cache-from: type=registry,ref=user/app:buildcache | ||||
|           cache-to: type=registry,ref=user/app:buildcache,mode=max | ||||
| ``` | ||||
|  | ||||
| ## GitHub cache | ||||
|  | ||||
| ### Cache backend API | ||||
|  | ||||
| > **Warning** | ||||
| > | ||||
| > This cache exporter is considered EXPERIMENTAL until further notice. Please | ||||
| > provide feedback on [BuildKit repository](https://github.com/moby/buildkit) | ||||
| > if you encounter any issues. | ||||
|  | ||||
| [GitHub Actions cache exporter](https://github.com/docker/buildx/blob/master/docs/guides/cache/gha.md) | ||||
| backend uses the [GitHub Cache API](https://github.com/tonistiigi/go-actions-cache/blob/master/api.md) | ||||
| to fetch and upload cache blobs. That's why this type of cache should be | ||||
| exclusively used in a GitHub Action workflow as the `url` (`$ACTIONS_CACHE_URL`) | ||||
| and `token` (`$ACTIONS_RUNTIME_TOKEN`) attributes are populated when a workflow | ||||
| is started. | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|           cache-from: type=gha | ||||
|           cache-to: type=gha,mode=max | ||||
| ``` | ||||
|  | ||||
| ### Local 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 workaround (see [moby/buildkit#1896](https://github.com/moby/buildkit/issues/1896) for more info). | ||||
|  | ||||
| You can also leverage [GitHub cache](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows) | ||||
| using the [actions/cache](https://github.com/actions/cache) and [`type=local` cache exporter](https://github.com/docker/buildx/blob/master/docs/guides/cache/local.md) | ||||
| with this action: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Cache Docker layers | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         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  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         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 | ||||
|           cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max | ||||
|       - | ||||
|         # Temp fix | ||||
|         # https://github.com/docker/build-push-action/issues/252 | ||||
|   | ||||
| @@ -1,10 +1,8 @@ | ||||
| # Copy images between registries | ||||
|  | ||||
| Multi-platform images built using buildx can be copied from one registry to another without | ||||
| changing the image SHA using the [tag-push-action](https://github.com/akhilerm/tag-push-action). | ||||
|  | ||||
| The following workflow will first push the image to dockerhub, run some tests using the images | ||||
| and then push to quay and ghcr | ||||
| [Multi-platform images](https://docs.docker.com/build/building/multi-platform/) | ||||
| built using Buildx can be copied from one registry to another using the | ||||
| [`imagetools create` command](https://docs.docker.com/engine/reference/commandline/buildx_imagetools_create/): | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
| @@ -12,7 +10,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -20,36 +18,29 @@ jobs: | ||||
|     steps: | ||||
|       -  | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - # quay and ghcr logins for pushing image after testing | ||||
|         name: Login to Quay Registry | ||||
|         uses: docker/login-action@v1  | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: quay.io | ||||
|           username: ${{ secrets.QUAY_USERNAME }} | ||||
|           password: ${{ secrets.QUAY_TOKEN }} | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Login to GitHub Container Registry | ||||
|         uses: docker/login-action@v1 | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ github.repository_owner }} | ||||
|           password: ${{ secrets.GITHUB_TOKEN }} | ||||
|       - | ||||
|         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 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
| @@ -57,17 +48,11 @@ jobs: | ||||
|           tags: | | ||||
|             user/app:latest | ||||
|             user/app:1.0.0 | ||||
|       - # run tests using image from docker hub | ||||
|         name: Run Tests | ||||
|         run: make tests | ||||
|       - # copy multiplatform image from dockerhub to quay and ghcr | ||||
|         name: Push Image to multiple registries | ||||
|         uses: akhilerm/tag-push-action@v1.0.0 | ||||
|         with: | ||||
|           src: docker.io/user/app:1.0.0 | ||||
|           dst: | | ||||
|             quay.io/user/app:latest | ||||
|             quay.io/user/app:1.0.0 | ||||
|             ghcr.io/user/app:latest | ||||
|             ghcr.io/user/app:1.0.0 | ||||
|       - | ||||
|         name: Push image to GHCR | ||||
|         run: | | ||||
|           docker buildx imagetools create \ | ||||
|             --tag ghcr.io/user/app:latest \ | ||||
|             --tag ghcr.io/user/app:1.0.0 \ | ||||
|             user/app:latest | ||||
| ``` | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # Update DockerHub repo description | ||||
| # Update Docker Hub 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) | ||||
| You can update the [Docker Hub repository description](https://docs.docker.com/docker-hub/repos/) | ||||
| using a third party action called [Docker Hub Description](https://github.com/peter-evans/dockerhub-description) | ||||
| with this action: | ||||
|  | ||||
| ```yaml | ||||
| @@ -10,7 +10,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -18,22 +18,22 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # 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: | ||||
| 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 | ||||
| @@ -9,7 +9,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -17,13 +17,13 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           load: true | ||||
|   | ||||
| @@ -6,7 +6,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -14,12 +14,12 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         id: builder1 | ||||
|       - | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         id: builder2 | ||||
|       - | ||||
|         name: Builder 1 name | ||||
| @@ -29,14 +29,14 @@ jobs: | ||||
|         run: echo ${{ steps.builder2.outputs.name }} | ||||
|       - | ||||
|         name: Build against builder1 | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           builder: ${{ steps.builder1.outputs.name }} | ||||
|           context: . | ||||
|           target: mytarget1 | ||||
|       - | ||||
|         name: Build against builder2 | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           builder: ${{ steps.builder2.outputs.name }} | ||||
|           context: . | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| # Local registry | ||||
|  | ||||
| For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into: | ||||
| For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) | ||||
| to push images into: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
| @@ -8,7 +9,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -21,18 +22,18 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|         with: | ||||
|           driver-opts: network=host | ||||
|       - | ||||
|         name: Build and push to local registry | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|   | ||||
| @@ -1,10 +1,14 @@ | ||||
| # Multi-platform image | ||||
|  | ||||
| You can build multi-platform images using the [`platforms` input](../../README.md#inputs) as described below. | ||||
| You can build [multi-platform images](https://docs.docker.com/build/building/multi-platform/) | ||||
| 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. | ||||
| > **Note** | ||||
| > | ||||
| > * List of available platforms will be displayed and available through our | ||||
| >   [setup-buildx](https://github.com/docker/setup-buildx-action#about) action. | ||||
| > * 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 | ||||
| @@ -12,7 +16,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -20,22 +24,22 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|   | ||||
							
								
								
									
										98
									
								
								docs/advanced/named-contexts.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								docs/advanced/named-contexts.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| # Named contexts | ||||
|  | ||||
| You can define [additional build contexts](https://docs.docker.com/engine/reference/commandline/buildx_build/#build-context) | ||||
| that can be accessed in your Dockerfile with `FROM name` or `--from=name`. When | ||||
| Dockerfile defines a stage with the same name it is overwritten. | ||||
|  | ||||
| This can be useful with GitHub Actions to reuse results from other builds or | ||||
| pin an image to a spcific tag in your workflow. | ||||
|  | ||||
| * [Pin image to a specific tag](#pin-image-to-a-specific-tag) | ||||
| * [Usage of the built image in other build steps](#usage-of-the-built-image-in-other-build-steps) | ||||
|  | ||||
| ## Pin image to a specific tag | ||||
|  | ||||
| Replace `alpine:latest` with a pinned one: | ||||
|  | ||||
| ```dockerfile | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM alpine | ||||
| RUN echo "Hello World" | ||||
| ``` | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Build | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           build-contexts: | | ||||
|             alpine=docker-image://alpine:3.16 | ||||
|           tags: myimage:latest | ||||
| ``` | ||||
|  | ||||
| ## Usage of the built image in other build steps | ||||
|  | ||||
| By default, the [`setup-buildx` action](https://github.com/docker/setup-buildx-action#about) | ||||
| uses `docker-container` as a build driver, so built Docker images are not | ||||
| available in the builder container. | ||||
|  | ||||
| With named contexts you can reuse the built image: | ||||
|  | ||||
| ```dockerfile | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM alpine | ||||
| RUN echo "Hello World" | ||||
| ``` | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Build base image | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: base | ||||
|           load: true | ||||
|           tags: my-base-image:latest | ||||
|       - | ||||
|         name: Build | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           build-contexts: | | ||||
|             alpine=docker-image://my-base-image:latest | ||||
|           tags: myimage:latest | ||||
| ``` | ||||
| @@ -1,12 +1,8 @@ | ||||
| # 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. | ||||
| The following workflow will connect you to [Docker Hub](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 | ||||
| @@ -14,7 +10,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -22,29 +18,29 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Login to GitHub Container Registry | ||||
|         uses: docker/login-action@v1  | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ github.repository_owner }} | ||||
|           password: ${{ secrets.GITHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|   | ||||
| @@ -1,20 +1,19 @@ | ||||
| # 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) | ||||
| In the following example we will expose and use the [GITHUB_TOKEN secret](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#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 | ||||
|  | ||||
| ```dockerfile | ||||
| # syntax=docker/dockerfile:1 | ||||
| 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): | ||||
| 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 | ||||
| @@ -22,7 +21,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -30,16 +29,16 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Build | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
| @@ -48,14 +47,17 @@ jobs: | ||||
|             "github_token=${{ secrets.GITHUB_TOKEN }}" | ||||
| ``` | ||||
|  | ||||
| > :bulb: You can also expose a secret file to the build with [`secret-files`](../../README.md#inputs) input: | ||||
| > **Note** | ||||
| > | ||||
| > You can also expose a secret file to the build with the [`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: | ||||
| If you're using [GitHub secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) | ||||
| and need to handle multi-line value, you will need to place the key-value pair | ||||
| between quotes: | ||||
|  | ||||
| ```yaml | ||||
| secrets: | | ||||
| @@ -72,13 +74,15 @@ secrets: | | ||||
|   "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` | | ||||
| | 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. | ||||
| > **Note** | ||||
| > | ||||
| > All quote signs need to be doubled for escaping. | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| # Share built image between jobs | ||||
|  | ||||
| As each job is isolated in its own runner you cannot use your built image between jobs (except for [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners)). | ||||
| However, you can [pass data between jobs in a workflow](https://docs.github.com/en/actions/guides/storing-workflow-data-as-artifacts#passing-data-between-jobs-in-a-workflow) | ||||
| using the [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact) | ||||
| As each job is isolated in its own runner you cannot use your built image | ||||
| between jobs (except for [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners)). | ||||
| However, you can [pass data between jobs in a workflow](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts#passing-data-between-jobs-in-a-workflow) | ||||
| using the [actions/upload-artifact](https://github.com/actions/upload-artifact) | ||||
| and [actions/download-artifact](https://github.com/actions/download-artifact) | ||||
| actions: | ||||
|  | ||||
| ```yaml | ||||
| @@ -11,7 +13,7 @@ name: ci | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
| @@ -19,20 +21,20 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Build and export | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           tags: myimage:latest | ||||
|           outputs: type=docker,dest=/tmp/myimage.tar | ||||
|       - | ||||
|         name: Upload artifact | ||||
|         uses: actions/upload-artifact@v2 | ||||
|         uses: actions/upload-artifact@v3 | ||||
|         with: | ||||
|           name: myimage | ||||
|           path: /tmp/myimage.tar | ||||
| @@ -43,10 +45,10 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Download artifact | ||||
|         uses: actions/download-artifact@v2 | ||||
|         uses: actions/download-artifact@v3 | ||||
|         with: | ||||
|           name: myimage | ||||
|           path: /tmp | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| # 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 metadata action](https://github.com/docker/metadata-action) | ||||
| to handle tags and labels based on GitHub actions events and Git metadata. | ||||
| If you 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 metadata action](https://github.com/docker/metadata-action) to | ||||
| handle tags and labels based on GitHub actions events and Git metadata: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   schedule: | ||||
|     - cron: '0 10 * * *' # everyday at 10am | ||||
|     - cron: '0 10 * * *' | ||||
|   push: | ||||
|     branches: | ||||
|       - '**' | ||||
| @@ -18,7 +18,7 @@ on: | ||||
|       - 'v*.*.*' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - 'master' | ||||
|       - 'main' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
| @@ -26,11 +26,11 @@ jobs: | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Docker meta | ||||
|         id: meta | ||||
|         uses: docker/metadata-action@v3 | ||||
|         uses: docker/metadata-action@v4 | ||||
|         with: | ||||
|           # list of Docker images to use as base name for tags | ||||
|           images: | | ||||
| @@ -47,28 +47,28 @@ jobs: | ||||
|             type=sha | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         name: Login to Docker Hub | ||||
|         if: github.event_name != 'pull_request' | ||||
|         uses: docker/login-action@v1  | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Login to GHCR | ||||
|         if: github.event_name != 'pull_request' | ||||
|         uses: docker/login-action@v1 | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ github.repository_owner }} | ||||
|           password: ${{ secrets.GITHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           push: ${{ github.event_name != 'pull_request' }} | ||||
|   | ||||
							
								
								
									
										66
									
								
								docs/advanced/test-before-push.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								docs/advanced/test-before-push.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| # Test your image before pushing it | ||||
|  | ||||
| In some cases, you might want to validate that the image works as expected | ||||
| before pushing it. | ||||
|  | ||||
| The workflow below will be composed of several steps to achieve this: | ||||
| * Build and export the image to Docker | ||||
| * Test your image | ||||
| * Multi-platform build and push the image | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'main' | ||||
|  | ||||
| env: | ||||
|   TEST_TAG: user/myapp:test | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|       - | ||||
|         name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and export to Docker | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           load: true | ||||
|           tags: ${{ env.TEST_TAG }} | ||||
|       - | ||||
|         name: Test | ||||
|         run: | | ||||
|           docker run --rm ${{ env.TEST_TAG }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v3 | ||||
|         with: | ||||
|           context: . | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           push: true | ||||
|           tags: ${{ env.TEST_TAG }} | ||||
| ``` | ||||
|  | ||||
| > **Note** | ||||
| > | ||||
| > Build time will not be increased with this workflow because internal cache | ||||
| > for `linux/amd64` will be used from previous step on `Build and push` step | ||||
| > so only `linux/arm64` will be actually built. | ||||
| @@ -1,42 +0,0 @@ | ||||
| # syntax=docker/dockerfile:1.2 | ||||
| ARG NODE_VERSION | ||||
|  | ||||
| FROM node:${NODE_VERSION}-alpine AS base | ||||
| RUN apk add --no-cache cpio findutils git | ||||
| WORKDIR /src | ||||
|  | ||||
| FROM base AS deps | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn install | ||||
|  | ||||
| FROM deps AS build | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --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 \ | ||||
|   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 | ||||
|  | ||||
| FROM deps AS format | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn run format \ | ||||
|   && mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out | ||||
|  | ||||
| FROM scratch AS format-update | ||||
| COPY --from=format /out / | ||||
|  | ||||
| FROM deps AS format-validate | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn run format-check \ | ||||
| @@ -1,23 +0,0 @@ | ||||
| # syntax=docker/dockerfile:1.2 | ||||
| ARG NODE_VERSION | ||||
|  | ||||
| FROM node:${NODE_VERSION}-alpine AS base | ||||
| RUN apk add --no-cache git | ||||
| WORKDIR /src | ||||
|  | ||||
| FROM base AS deps | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn install | ||||
|  | ||||
| FROM deps AS test | ||||
| ENV RUNNER_TEMP=/tmp/github_runner | ||||
| ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   --mount=type=bind,from=crazymax/docker,source=/usr/libexec/docker/cli-plugins/docker-buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \ | ||||
|   --mount=type=bind,from=crazymax/docker,source=/usr/local/bin/docker,target=/usr/bin/docker \ | ||||
|   yarn run test --coverageDirectory=/tmp/coverage | ||||
|  | ||||
| FROM scratch AS test-coverage | ||||
| COPY --from=test /tmp/coverage / | ||||
| @@ -1,23 +0,0 @@ | ||||
| # syntax=docker/dockerfile:1.2 | ||||
| ARG NODE_VERSION | ||||
|  | ||||
| FROM node:${NODE_VERSION}-alpine AS base | ||||
| RUN apk add --no-cache git | ||||
| WORKDIR /src | ||||
|  | ||||
| FROM base AS vendored | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   --mount=type=cache,target=/src/node_modules \ | ||||
|   yarn install && mkdir /out && cp yarn.lock /out | ||||
|  | ||||
| FROM scratch AS update | ||||
| COPY --from=vendored /out / | ||||
|  | ||||
| FROM vendored AS validate | ||||
| RUN --mount=type=bind,target=.,rw \ | ||||
|   git add -A && cp -rf /out/* .; \ | ||||
|   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 | ||||
| @@ -1,12 +1,13 @@ | ||||
| module.exports = { | ||||
|   clearMocks: false, | ||||
|   moduleFileExtensions: ['js', 'ts'], | ||||
|   setupFiles: ["dotenv/config"], | ||||
|   testEnvironment: 'node', | ||||
|   setupFiles: ['dotenv/config'], | ||||
|   testMatch: ['**/*.test.ts'], | ||||
|   testRunner: 'jest-circus/runner', | ||||
|   transform: { | ||||
|     '^.+\\.ts$': 'ts-jest' | ||||
|   }, | ||||
|   verbose: false | ||||
| } | ||||
|   moduleNameMapper: { | ||||
|     '^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs' | ||||
|   }, | ||||
|   verbose: true | ||||
| }; | ||||
							
								
								
									
										47
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								package.json
									
									
									
									
									
								
							| @@ -3,11 +3,11 @@ | ||||
|   "description": "Build and push Docker images", | ||||
|   "main": "lib/main.js", | ||||
|   "scripts": { | ||||
|     "build": "tsc && ncc build", | ||||
|     "format": "prettier --write **/*.ts", | ||||
|     "format-check": "prettier --check **/*.ts", | ||||
|     "build": "ncc build src/main.ts --source-map --minify --license licenses.txt", | ||||
|     "lint": "eslint src/**/*.ts __tests__/**/*.ts", | ||||
|     "format": "eslint --fix src/**/*.ts __tests__/**/*.ts", | ||||
|     "test": "jest --coverage", | ||||
|     "pre-checkin": "yarn run format && yarn run build" | ||||
|     "all": "yarn run build && yarn run format && yarn test" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
| @@ -28,26 +28,31 @@ | ||||
|   ], | ||||
|   "license": "Apache-2.0", | ||||
|   "dependencies": { | ||||
|     "@actions/core": "^1.3.0", | ||||
|     "@actions/exec": "^1.0.4", | ||||
|     "@actions/github": "^5.0.0", | ||||
|     "csv-parse": "^4.15.4", | ||||
|     "semver": "^7.3.5", | ||||
|     "@actions/core": "^1.10.0", | ||||
|     "@actions/exec": "^1.1.1", | ||||
|     "@actions/github": "^5.1.1", | ||||
|     "csv-parse": "^5.3.0", | ||||
|     "handlebars": "^4.7.7", | ||||
|     "semver": "^7.3.7", | ||||
|     "tmp": "^0.2.1" | ||||
|   }, | ||||
|   "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": "^16.11.26", | ||||
|     "@types/semver": "^7.3.9", | ||||
|     "@types/tmp": "^0.2.3", | ||||
|     "@typescript-eslint/eslint-plugin": "^5.14.0", | ||||
|     "@typescript-eslint/parser": "^5.14.0", | ||||
|     "@vercel/ncc": "^0.33.3", | ||||
|     "dotenv": "^16.0.0", | ||||
|     "eslint": "^8.11.0", | ||||
|     "eslint-config-prettier": "^8.5.0", | ||||
|     "eslint-plugin-jest": "^26.1.1", | ||||
|     "eslint-plugin-prettier": "^4.0.0", | ||||
|     "jest": "^27.2.5", | ||||
|     "prettier": "^2.3.1", | ||||
|     "ts-jest": "^27.1.2", | ||||
|     "ts-node": "^10.7.0", | ||||
|     "typescript": "^4.4.4" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										107
									
								
								src/buildx.ts
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								src/buildx.ts
									
									
									
									
									
								
							| @@ -1,10 +1,10 @@ | ||||
| import csvparse from 'csv-parse/lib/sync'; | ||||
| import {parse} from 'csv-parse/sync'; | ||||
| import fs from 'fs'; | ||||
| import path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
| import * as exec from '@actions/exec'; | ||||
|  | ||||
| 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); | ||||
| @@ -15,7 +15,34 @@ export async function getImageID(): Promise<string | undefined> { | ||||
|   if (!fs.existsSync(iidFile)) { | ||||
|     return undefined; | ||||
|   } | ||||
|   return fs.readFileSync(iidFile, {encoding: 'utf-8'}); | ||||
|   return fs.readFileSync(iidFile, {encoding: 'utf-8'}).trim(); | ||||
| } | ||||
|  | ||||
| export async function getMetadataFile(): Promise<string> { | ||||
|   return path.join(context.tmpDir(), 'metadata-file').split(path.sep).join(path.posix.sep); | ||||
| } | ||||
|  | ||||
| export async function getMetadata(): Promise<string | undefined> { | ||||
|   const metadataFile = await getMetadataFile(); | ||||
|   if (!fs.existsSync(metadataFile)) { | ||||
|     return undefined; | ||||
|   } | ||||
|   const content = fs.readFileSync(metadataFile, {encoding: 'utf-8'}).trim(); | ||||
|   if (content === 'null') { | ||||
|     return undefined; | ||||
|   } | ||||
|   return content; | ||||
| } | ||||
|  | ||||
| export async function getDigest(metadata: string | undefined): Promise<string | undefined> { | ||||
|   if (metadata === undefined) { | ||||
|     return undefined; | ||||
|   } | ||||
|   const metadataJSON = JSON.parse(metadata); | ||||
|   if (metadataJSON['containerimage.digest']) { | ||||
|     return metadataJSON['containerimage.digest']; | ||||
|   } | ||||
|   return undefined; | ||||
| } | ||||
|  | ||||
| export async function getSecretString(kvp: string): Promise<string> { | ||||
| @@ -49,19 +76,20 @@ export async function getSecret(kvp: string, file: boolean): Promise<string> { | ||||
|   return `id=${key},src=${secretFile}`; | ||||
| } | ||||
|  | ||||
| export function isLocalOrTarExporter(outputs: string[]): Boolean { | ||||
|   for (let output of csvparse(outputs.join(`\n`), { | ||||
| export function isLocalOrTarExporter(outputs: string[]): boolean { | ||||
|   const records = parse(outputs.join(`\n`), { | ||||
|     delimiter: ',', | ||||
|     trim: true, | ||||
|     columns: false, | ||||
|     relaxColumnCount: true | ||||
|   })) { | ||||
|   }); | ||||
|   for (const record of records) { | ||||
|     // 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=')) { | ||||
|     if (record.length == 1 && !record[0].startsWith('type=')) { | ||||
|       return true; | ||||
|     } | ||||
|     for (let [key, value] of output.map(chunk => chunk.split('=').map(item => item.trim()))) { | ||||
|     for (const [key, value] of record.map(chunk => chunk.split('=').map(item => item.trim()))) { | ||||
|       if (key == 'type' && (value == 'local' || value == 'tar')) { | ||||
|         return true; | ||||
|       } | ||||
| @@ -70,8 +98,8 @@ export function isLocalOrTarExporter(outputs: string[]): Boolean { | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| export function hasGitAuthToken(secrets: string[]): Boolean { | ||||
|   for (let secret of secrets) { | ||||
| export function hasGitAuthToken(secrets: string[]): boolean { | ||||
|   for (const secret of secrets) { | ||||
|     if (secret.startsWith('GIT_AUTH_TOKEN=')) { | ||||
|       return true; | ||||
|     } | ||||
| @@ -79,28 +107,55 @@ export function hasGitAuthToken(secrets: string[]): Boolean { | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| export async function isAvailable(): Promise<Boolean> { | ||||
|   return await exec.exec(`docker`, ['buildx'], true).then(res => { | ||||
|     if (res.stderr != '' && !res.success) { | ||||
| export async function isAvailable(standalone?: boolean): Promise<boolean> { | ||||
|   const cmd = getCommand([], standalone); | ||||
|   return await exec | ||||
|     .getExecOutput(cmd.command, cmd.args, { | ||||
|       ignoreReturnCode: true, | ||||
|       silent: true | ||||
|     }) | ||||
|     .then(res => { | ||||
|       if (res.stderr.length > 0 && res.exitCode != 0) { | ||||
|         return false; | ||||
|       } | ||||
|       return res.exitCode == 0; | ||||
|     }) | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
|     .catch(error => { | ||||
|       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 getVersion(standalone?: boolean): Promise<string> { | ||||
|   const cmd = getCommand(['version'], standalone); | ||||
|   return await exec | ||||
|     .getExecOutput(cmd.command, cmd.args, { | ||||
|       ignoreReturnCode: true, | ||||
|       silent: true | ||||
|     }) | ||||
|     .then(res => { | ||||
|       if (res.stderr.length > 0 && res.exitCode != 0) { | ||||
|         throw new Error(res.stderr.trim()); | ||||
|       } | ||||
|       return parseVersion(res.stdout.trim()); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| export async function parseVersion(stdout: string): Promise<string> { | ||||
|   const matches = /\sv?([0-9.]+)/.exec(stdout); | ||||
| export function parseVersion(stdout: string): string { | ||||
|   const matches = /\sv?([0-9a-f]{7}|[0-9.]+)/.exec(stdout); | ||||
|   if (!matches) { | ||||
|     throw new Error(`Cannot parse buildx version`); | ||||
|   } | ||||
|   return semver.clean(matches[1]); | ||||
|   return matches[1]; | ||||
| } | ||||
|  | ||||
| export function satisfies(version: string, range: string): boolean { | ||||
|   return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null; | ||||
| } | ||||
|  | ||||
| export function getCommand(args: Array<string>, standalone?: boolean) { | ||||
|   return { | ||||
|     command: standalone ? 'buildx' : 'docker', | ||||
|     args: standalone ? args : ['buildx', ...args] | ||||
|   }; | ||||
| } | ||||
|   | ||||
							
								
								
									
										160
									
								
								src/context.ts
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								src/context.ts
									
									
									
									
									
								
							| @@ -1,39 +1,42 @@ | ||||
| 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 {issueCommand} from '@actions/core/lib/command'; | ||||
| import * as github from '@actions/github'; | ||||
|  | ||||
| import * as buildx from './buildx'; | ||||
| import * as core from '@actions/core'; | ||||
| import * as github from '@actions/github'; | ||||
| import {parse} from 'csv-parse/sync'; | ||||
| import * as handlebars from 'handlebars'; | ||||
|  | ||||
| let _defaultContext, _tmpDir: string; | ||||
|  | ||||
| export interface Inputs { | ||||
|   addHosts: string[]; | ||||
|   allow: string[]; | ||||
|   buildArgs: string[]; | ||||
|   buildContexts: string[]; | ||||
|   builder: string; | ||||
|   cacheFrom: string[]; | ||||
|   cacheTo: string[]; | ||||
|   cgroupParent: string; | ||||
|   context: string; | ||||
|   file: string; | ||||
|   labels: string[]; | ||||
|   load: boolean; | ||||
|   network: string; | ||||
|   noCache: boolean; | ||||
|   noCacheFilters: string[]; | ||||
|   outputs: string[]; | ||||
|   platforms: string[]; | ||||
|   pull: boolean; | ||||
|   push: boolean; | ||||
|   secrets: string[]; | ||||
|   secretFiles: string[]; | ||||
|   shmSize: string; | ||||
|   ssh: string[]; | ||||
|   tags: string[]; | ||||
|   target: string; | ||||
|   ulimit: string[]; | ||||
|   githubToken: string; | ||||
| } | ||||
|  | ||||
| @@ -46,9 +49,7 @@ export function defaultContext(): string { | ||||
|     if (github.context.sha && !ref.startsWith(`refs/pull/`)) { | ||||
|       ref = github.context.sha; | ||||
|     } | ||||
|     _defaultContext = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${ | ||||
|       github.context.repo.repo | ||||
|     }.git#${ref}`; | ||||
|     _defaultContext = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}.git#${ref}`; | ||||
|   } | ||||
|   return _defaultContext; | ||||
| } | ||||
| @@ -66,66 +67,61 @@ export function tmpNameSync(options?: tmp.TmpNameOptions): string { | ||||
|  | ||||
| export async function getInputs(defaultContext: string): Promise<Inputs> { | ||||
|   return { | ||||
|     addHosts: await getInputList('add-hosts'), | ||||
|     allow: await getInputList('allow'), | ||||
|     buildArgs: await getInputList('build-args', true), | ||||
|     buildContexts: await getInputList('build-contexts', true), | ||||
|     builder: core.getInput('builder'), | ||||
|     cacheFrom: await getInputList('cache-from', true), | ||||
|     cacheTo: await getInputList('cache-to', true), | ||||
|     cgroupParent: core.getInput('cgroup-parent'), | ||||
|     context: core.getInput('context') || defaultContext, | ||||
|     file: core.getInput('file'), | ||||
|     labels: await getInputList('labels', true), | ||||
|     load: /true/i.test(core.getInput('load')), | ||||
|     load: core.getBooleanInput('load'), | ||||
|     network: core.getInput('network'), | ||||
|     noCache: /true/i.test(core.getInput('no-cache')), | ||||
|     noCache: core.getBooleanInput('no-cache'), | ||||
|     noCacheFilters: await getInputList('no-cache-filters'), | ||||
|     outputs: await getInputList('outputs', true), | ||||
|     platforms: await getInputList('platforms'), | ||||
|     pull: /true/i.test(core.getInput('pull')), | ||||
|     push: /true/i.test(core.getInput('push')), | ||||
|     pull: core.getBooleanInput('pull'), | ||||
|     push: core.getBooleanInput('push'), | ||||
|     secrets: await getInputList('secrets', true), | ||||
|     secretFiles: await getInputList('secret-files', true), | ||||
|     shmSize: core.getInput('shm-size'), | ||||
|     ssh: await getInputList('ssh'), | ||||
|     tags: await getInputList('tags'), | ||||
|     target: core.getInput('target'), | ||||
|     ulimit: await getInputList('ulimit', true), | ||||
|     githubToken: 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; | ||||
|   const context = handlebars.compile(inputs.context)({defaultContext}); | ||||
|   // prettier-ignore | ||||
|   return [ | ||||
|     ...await getBuildArgs(inputs, defaultContext, context, buildxVersion), | ||||
|     ...await getCommonArgs(inputs, buildxVersion), | ||||
|     context | ||||
|   ]; | ||||
| } | ||||
|  | ||||
| async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersion: string): Promise<Array<string>> { | ||||
|   let args: Array<string> = ['build']; | ||||
|   await asyncForEach(inputs.buildArgs, async buildArg => { | ||||
|     args.push('--build-arg', buildArg); | ||||
| async function getBuildArgs(inputs: Inputs, defaultContext: string, context: string, buildxVersion: string): Promise<Array<string>> { | ||||
|   const args: Array<string> = ['build']; | ||||
|   await asyncForEach(inputs.addHosts, async addHost => { | ||||
|     args.push('--add-host', addHost); | ||||
|   }); | ||||
|   await asyncForEach(inputs.labels, async label => { | ||||
|     args.push('--label', label); | ||||
|   }); | ||||
|   await 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 asyncForEach(inputs.buildArgs, async buildArg => { | ||||
|     args.push('--build-arg', buildArg); | ||||
|   }); | ||||
|   if ( | ||||
|     !buildx.isLocalOrTarExporter(inputs.outputs) && | ||||
|     (inputs.platforms.length == 0 || semver.satisfies(buildxVersion, '>=0.4.2')) | ||||
|   ) { | ||||
|     args.push('--iidfile', await buildx.getImageIDFile()); | ||||
|   if (buildx.satisfies(buildxVersion, '>=0.8.0')) { | ||||
|     await asyncForEach(inputs.buildContexts, async buildContext => { | ||||
|       args.push('--build-context', buildContext); | ||||
|     }); | ||||
|   } | ||||
|   await asyncForEach(inputs.cacheFrom, async cacheFrom => { | ||||
|     args.push('--cache-from', cacheFrom); | ||||
| @@ -133,6 +129,27 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio | ||||
|   await asyncForEach(inputs.cacheTo, async cacheTo => { | ||||
|     args.push('--cache-to', cacheTo); | ||||
|   }); | ||||
|   if (inputs.cgroupParent) { | ||||
|     args.push('--cgroup-parent', inputs.cgroupParent); | ||||
|   } | ||||
|   if (inputs.file) { | ||||
|     args.push('--file', inputs.file); | ||||
|   } | ||||
|   if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) { | ||||
|     args.push('--iidfile', await buildx.getImageIDFile()); | ||||
|   } | ||||
|   await asyncForEach(inputs.labels, async label => { | ||||
|     args.push('--label', label); | ||||
|   }); | ||||
|   await asyncForEach(inputs.noCacheFilters, async noCacheFilter => { | ||||
|     args.push('--no-cache-filter', noCacheFilter); | ||||
|   }); | ||||
|   await asyncForEach(inputs.outputs, async output => { | ||||
|     args.push('--output', output); | ||||
|   }); | ||||
|   if (inputs.platforms.length > 0) { | ||||
|     args.push('--platform', inputs.platforms.join(',')); | ||||
|   } | ||||
|   await asyncForEach(inputs.secrets, async secret => { | ||||
|     try { | ||||
|       args.push('--secret', await buildx.getSecretString(secret)); | ||||
| @@ -147,35 +164,47 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio | ||||
|       core.warning(err.message); | ||||
|     } | ||||
|   }); | ||||
|   if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && inputs.context == defaultContext) { | ||||
|   if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && context.startsWith(defaultContext)) { | ||||
|     args.push('--secret', await buildx.getSecretString(`GIT_AUTH_TOKEN=${inputs.githubToken}`)); | ||||
|   } | ||||
|   if (inputs.shmSize) { | ||||
|     args.push('--shm-size', inputs.shmSize); | ||||
|   } | ||||
|   await asyncForEach(inputs.ssh, async ssh => { | ||||
|     args.push('--ssh', ssh); | ||||
|   }); | ||||
|   if (inputs.file) { | ||||
|     args.push('--file', inputs.file); | ||||
|   await asyncForEach(inputs.tags, async tag => { | ||||
|     args.push('--tag', tag); | ||||
|   }); | ||||
|   if (inputs.target) { | ||||
|     args.push('--target', inputs.target); | ||||
|   } | ||||
|   await asyncForEach(inputs.ulimit, async ulimit => { | ||||
|     args.push('--ulimit', ulimit); | ||||
|   }); | ||||
|   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, buildxVersion: string): 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 (buildx.satisfies(buildxVersion, '>=0.6.0')) { | ||||
|     args.push('--metadata-file', await buildx.getMetadataFile()); | ||||
|   } | ||||
|   if (inputs.network) { | ||||
|     args.push('--network', inputs.network); | ||||
|   } | ||||
|   if (inputs.noCache) { | ||||
|     args.push('--no-cache'); | ||||
|   } | ||||
|   if (inputs.pull) { | ||||
|     args.push('--pull'); | ||||
|   } | ||||
|   if (inputs.push) { | ||||
|     args.push('--push'); | ||||
|   } | ||||
| @@ -183,27 +212,29 @@ async function getCommonArgs(inputs: Inputs): Promise<Array<string>> { | ||||
| } | ||||
|  | ||||
| export async function getInputList(name: string, ignoreComma?: boolean): Promise<string[]> { | ||||
|   let res: Array<string> = []; | ||||
|   const res: Array<string> = []; | ||||
|  | ||||
|   const items = core.getInput(name); | ||||
|   if (items == '') { | ||||
|     return res; | ||||
|   } | ||||
|  | ||||
|   for (let output of (await csvparse(items, { | ||||
|   const records = await parse(items, { | ||||
|     columns: false, | ||||
|     relax: true, | ||||
|     relaxQuotes: true, | ||||
|     relaxColumnCount: true, | ||||
|     skipLinesWithEmptyValues: true | ||||
|   })) as Array<string[]>) { | ||||
|     if (output.length == 1) { | ||||
|       res.push(output[0]); | ||||
|     skipEmptyLines: true | ||||
|   }); | ||||
|  | ||||
|   for (const record of records as Array<string[]>) { | ||||
|     if (record.length == 1) { | ||||
|       res.push(record[0]); | ||||
|       continue; | ||||
|     } else if (!ignoreComma) { | ||||
|       res.push(...output); | ||||
|       res.push(...record); | ||||
|       continue; | ||||
|     } | ||||
|     res.push(output.join(',')); | ||||
|     res.push(record.join(',')); | ||||
|   } | ||||
|  | ||||
|   return res.filter(item => item).map(pat => pat.trim()); | ||||
| @@ -214,8 +245,3 @@ export const asyncForEach = async (array, callback) => { | ||||
|     await callback(array[index], index, array); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // FIXME: Temp fix https://github.com/actions/toolkit/issues/777 | ||||
| export function setOutput(name: string, value: any): void { | ||||
|   issueCommand('set-output', {name}, value); | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,19 @@ | ||||
| import * as exec from './exec'; | ||||
| import * as exec from '@actions/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; | ||||
|   }); | ||||
| export async function isAvailable(): Promise<boolean> { | ||||
|   return await exec | ||||
|     .getExecOutput('docker', undefined, { | ||||
|       ignoreReturnCode: true, | ||||
|       silent: true | ||||
|     }) | ||||
|     .then(res => { | ||||
|       if (res.stderr.length > 0 && res.exitCode != 0) { | ||||
|         return false; | ||||
|       } | ||||
|       return res.exitCode == 0; | ||||
|     }) | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
|     .catch(error => { | ||||
|       return false; | ||||
|     }); | ||||
| } | ||||
|   | ||||
							
								
								
									
										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() | ||||
|   }; | ||||
| }; | ||||
							
								
								
									
										75
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -1,40 +1,79 @@ | ||||
| import * as fs from 'fs'; | ||||
| import * as buildx from './buildx'; | ||||
| import * as context from './context'; | ||||
| import * as exec from './exec'; | ||||
| import * as docker from './docker'; | ||||
| import * as stateHelper from './state-helper'; | ||||
| import * as core from '@actions/core'; | ||||
| import * as exec from '@actions/exec'; | ||||
|  | ||||
| async function run(): Promise<void> { | ||||
|   try { | ||||
|     const defContext = context.defaultContext(); | ||||
|     const inputs: context.Inputs = await context.getInputs(defContext); | ||||
|  | ||||
|     // standalone if docker cli not available | ||||
|     const standalone = !(await docker.isAvailable()); | ||||
|  | ||||
|     core.startGroup(`Docker info`); | ||||
|     await exec.exec('docker', ['version']); | ||||
|     await exec.exec('docker', ['info']); | ||||
|     if (standalone) { | ||||
|       core.info(`Docker info skipped in standalone mode`); | ||||
|     } else { | ||||
|       await exec.exec('docker', ['version'], { | ||||
|         failOnStdErr: false | ||||
|       }); | ||||
|       await exec.exec('docker', ['info'], { | ||||
|         failOnStdErr: false | ||||
|       }); | ||||
|     } | ||||
|     core.endGroup(); | ||||
|  | ||||
|     if (!(await buildx.isAvailable())) { | ||||
|     if (!(await buildx.isAvailable(standalone))) { | ||||
|       core.setFailed(`Docker buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`); | ||||
|       return; | ||||
|     } | ||||
|     stateHelper.setTmpDir(context.tmpDir()); | ||||
|  | ||||
|     const buildxVersion = await buildx.getVersion(); | ||||
|     const defContext = context.defaultContext(); | ||||
|     let inputs: context.Inputs = await context.getInputs(defContext); | ||||
|  | ||||
|     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 buildxVersion = await buildx.getVersion(standalone); | ||||
|     await core.group(`Buildx version`, async () => { | ||||
|       const versionCmd = buildx.getCommand(['version'], standalone); | ||||
|       await exec.exec(versionCmd.command, versionCmd.args, { | ||||
|         failOnStdErr: false | ||||
|       }); | ||||
|     }); | ||||
|  | ||||
|     const args: string[] = await context.getArgs(inputs, defContext, buildxVersion); | ||||
|     const buildCmd = buildx.getCommand(args, standalone); | ||||
|     await exec | ||||
|       .getExecOutput(buildCmd.command, buildCmd.args, { | ||||
|         ignoreReturnCode: true | ||||
|       }) | ||||
|       .then(res => { | ||||
|         if (res.stderr.length > 0 && res.exitCode != 0) { | ||||
|           throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`); | ||||
|         } | ||||
|       }); | ||||
|  | ||||
|     const imageID = await buildx.getImageID(); | ||||
|     const metadata = await buildx.getMetadata(); | ||||
|     const digest = await buildx.getDigest(metadata); | ||||
|  | ||||
|     if (imageID) { | ||||
|       core.startGroup(`Extracting digest`); | ||||
|       core.info(`${imageID}`); | ||||
|       context.setOutput('digest', imageID); | ||||
|       core.endGroup(); | ||||
|       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 () => { | ||||
|         core.info(metadata); | ||||
|         core.setOutput('metadata', metadata); | ||||
|       }); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     core.setFailed(error.message); | ||||
| @@ -44,7 +83,7 @@ async function run(): Promise<void> { | ||||
| async function cleanup(): Promise<void> { | ||||
|   if (stateHelper.tmpDir.length > 0) { | ||||
|     core.startGroup(`Removing temp folder ${stateHelper.tmpDir}`); | ||||
|     fs.rmdirSync(stateHelper.tmpDir, {recursive: true}); | ||||
|     fs.rmSync(stateHelper.tmpDir, {recursive: true}); | ||||
|     core.endGroup(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -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/buildcontext.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/buildcontext.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # syntax=docker/dockerfile:1 | ||||
| FROM alpine | ||||
| RUN cat /etc/*release | ||||
							
								
								
									
										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 | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										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 | ||||
							
								
								
									
										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 | ||||
| @@ -2,20 +2,18 @@ | ||||
|   "compilerOptions": { | ||||
|     "target": "es6", | ||||
|     "module": "commonjs", | ||||
|     "lib": [ | ||||
|       "es6", | ||||
|       "dom" | ||||
|     ], | ||||
|     "newLine": "lf", | ||||
|     "outDir": "./lib", | ||||
|     "rootDir": "./src", | ||||
|     "esModuleInterop": true, | ||||
|     "forceConsistentCasingInFileNames": true, | ||||
|     "strict": true, | ||||
|     "noImplicitAny": false, | ||||
|     "esModuleInterop": true, | ||||
|     "sourceMap": true | ||||
|     "useUnknownInCatchVariables": false, | ||||
|   }, | ||||
|   "exclude": [ | ||||
|     "node_modules", | ||||
|     "**/*.test.ts" | ||||
|     "**/*.test.ts", | ||||
|     "jest.config.ts" | ||||
|   ] | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user