Compare commits
	
		
			24 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 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 | 
							
								
								
									
										88
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										88
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -70,9 +70,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: | | ||||
| @@ -133,9 +130,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: | | ||||
| @@ -191,9 +185,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: | | ||||
| @@ -392,9 +383,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: | | ||||
| @@ -447,9 +435,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 +465,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: | | ||||
| @@ -503,7 +485,7 @@ jobs: | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   github-cache-first: | ||||
|   local-cache-first: | ||||
|     runs-on: ubuntu-latest | ||||
|     outputs: | ||||
|       digest: ${{ steps.docker_build.outputs.digest }} | ||||
| @@ -531,7 +513,7 @@ jobs: | ||||
|         uses: actions/cache@v2 | ||||
|         with: | ||||
|           path: /tmp/.buildx-cache | ||||
|           key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }} | ||||
|           key: ${{ runner.os }}-buildx-local-${{ github.sha }} | ||||
|           restore-keys: | | ||||
|             ${{ runner.os }}-buildx-ghcache- | ||||
|       - | ||||
| @@ -557,9 +539,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: | | ||||
| @@ -572,9 +551,9 @@ jobs: | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   github-cache-hit: | ||||
|   local-cache-hit: | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: github-cache-first | ||||
|     needs: local-cache-first | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
| @@ -600,7 +579,7 @@ jobs: | ||||
|         id: cache | ||||
|         with: | ||||
|           path: /tmp/.buildx-cache | ||||
|           key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }} | ||||
|           key: ${{ runner.os }}-buildx-local-${{ github.sha }} | ||||
|           restore-keys: | | ||||
|             ${{ runner.os }}-buildx-ghcache- | ||||
|       - | ||||
| @@ -622,9 +601,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: | | ||||
| @@ -635,8 +611,8 @@ jobs: | ||||
|       - | ||||
|         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 Compare "${{ needs.local-cache-first.outputs.digest }}" with "${{ steps.docker_build.outputs.digest }}" | ||||
|           if [ "${{ needs.local-cache-first.outputs.digest }}" != "${{ steps.docker_build.outputs.digest }}" ]; then | ||||
|             echo "::error::Digests should be identical" | ||||
|             exit 1 | ||||
|           fi | ||||
| @@ -647,3 +623,53 @@ jobs: | ||||
|         name: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|  | ||||
|   github-cache: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         buildx_version: | ||||
|           - "" | ||||
|           - latest | ||||
|     services: | ||||
|       registry: | ||||
|         image: registry:2 | ||||
|         ports: | ||||
|           - 5000:5000 | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v1 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|         with: | ||||
|           version: ${{ matrix.buildx_version }} | ||||
|           driver-opts: | | ||||
|             network=host | ||||
|           buildkitd-flags: --debug | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: ./ | ||||
|         with: | ||||
|           context: ./test | ||||
|           file: ./test/multi.Dockerfile | ||||
|           platforms: linux/amd64,linux/arm64 | ||||
|           push: true | ||||
|           tags: | | ||||
|             localhost:5000/name/app:latest | ||||
|             localhost:5000/name/app:1.0.0 | ||||
|           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: Dump context | ||||
|         if: always() | ||||
|         uses: crazy-max/ghaction-dump-context@v1 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -27,6 +27,6 @@ jobs: | ||||
|           targets: test | ||||
|       - | ||||
|         name: Upload coverage | ||||
|         uses: codecov/codecov-action@v1 | ||||
|         uses: codecov/codecov-action@v2 | ||||
|         with: | ||||
|           file: ./coverage/clover.xml | ||||
|   | ||||
							
								
								
									
										19
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.md
									
									
									
									
									
								
							| @@ -33,8 +33,6 @@ ___ | ||||
|   * [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) | ||||
| @@ -53,7 +51,7 @@ By default, this action uses the [Git context](#git-context) so you don't need t | ||||
| 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>`. | ||||
|  | ||||
| Be careful because **any file mutation in the steps that precede the build step will be ignored** since | ||||
| 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. | ||||
| @@ -100,9 +98,6 @@ jobs: | ||||
|         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) | ||||
| @@ -121,9 +116,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 | ||||
| @@ -170,8 +162,6 @@ 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) | ||||
| @@ -223,9 +213,10 @@ Following inputs can be used as `step.with` keys | ||||
|  | ||||
| Following outputs are available | ||||
|  | ||||
| | Name          | Type    | Description                           | | ||||
| |---------------|---------|---------------------------------------| | ||||
| | `digest`      | String  | Image content-addressable identifier also called a digest | | ||||
| | Name              | Type    | Description                           | | ||||
| |-------------------|---------|---------------------------------------| | ||||
| | `digest`          | String  | Image content-addressable identifier also called a digest | | ||||
| | `metadata`        | JSON    | Build result metadata | | ||||
|  | ||||
| ## Troubleshooting | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
| @@ -69,3 +73,47 @@ 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, or a dedicated step to sanitize the slug: | ||||
|  | ||||
| ```yaml | ||||
| - name: Sanitize repo slug | ||||
|   uses: actions/github-script@v4 | ||||
|   id: repo_slug | ||||
|   with: | ||||
|     result-encoding: string | ||||
|     script: return `ghcr.io/${github.repository.toLowerCase()}` | ||||
|  | ||||
| - name: Build and push | ||||
|   uses: docker/build-push-action@v2 | ||||
|   with: | ||||
|     context: . | ||||
|     push: true | ||||
|     tags: ${{ steps.repo_slug.outputs.result }}:latest | ||||
| ``` | ||||
|   | ||||
							
								
								
									
										40
									
								
								UPGRADE.md
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								UPGRADE.md
									
									
									
									
									
								
							| @@ -101,25 +101,17 @@ 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: Docker meta | ||||
|     id: meta | ||||
|     uses: docker/metadata-action@v3 | ||||
|     with: | ||||
|       images: | | ||||
|         myorg/myrepository | ||||
|       tags: | | ||||
|         type=ref,event=branch | ||||
|         type=ref,event=pr | ||||
|         type=semver,pattern={{version}} | ||||
|         type=sha | ||||
|   - | ||||
|     name: Set up Docker Buildx | ||||
|     uses: docker/setup-buildx-action@v1 | ||||
| @@ -136,12 +128,6 @@ steps: | ||||
|     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 }} | ||||
|       tags: ${{ steps.meta.outputs.tags }} | ||||
|       labels: ${{ steps.meta.outputs.labels }} | ||||
| ``` | ||||
|  | ||||
| > 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. | ||||
|   | ||||
| @@ -8,6 +8,10 @@ import * as context from '../src/context'; | ||||
|  | ||||
| const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep); | ||||
| const digest = '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); | ||||
| @@ -32,6 +36,17 @@ describe('getImageID', () => { | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('getMetadata', () => { | ||||
|   it('matches', async () => { | ||||
|     const metadataFile = await buildx.getMetadataFile(); | ||||
|     console.log(`metadataFile: ${metadataFile}`); | ||||
|     await fs.writeFileSync(metadataFile, metadata); | ||||
|     const expected = await buildx.getMetadata(); | ||||
|     console.log(`metadata: ${expected}`); | ||||
|     expect(expected).toEqual(metadata); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| describe('isLocalOrTarExporter', () => { | ||||
|   // prettier-ignore | ||||
|   test.each([ | ||||
|   | ||||
| @@ -425,7 +425,30 @@ ccc`], | ||||
|         '--output', 'type=local,dest=./release-out', | ||||
|         '.' | ||||
|       ] | ||||
|     ] | ||||
|     ], | ||||
|     [ | ||||
|       '0.6.0', | ||||
|       new Map<string, string>([ | ||||
|         ['context', '.'], | ||||
|         ['tag', 'localhost:5000/name/app:latest'], | ||||
|         ['file', './test/Dockerfile'], | ||||
|         ['network', 'host'], | ||||
|         ['load', 'false'], | ||||
|         ['no-cache', 'false'], | ||||
|         ['push', 'true'], | ||||
|         ['pull', 'false'] | ||||
|       ]), | ||||
|       [ | ||||
|         'buildx', | ||||
|         'build', | ||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||
|         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||
|         '--file', './test/Dockerfile', | ||||
|         '--network', 'host', | ||||
|         '--push', | ||||
|         '.' | ||||
|       ] | ||||
|     ], | ||||
|   ])( | ||||
|     'given %p with %p as inputs, returns %p', | ||||
|     async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => { | ||||
|   | ||||
| @@ -79,6 +79,8 @@ inputs: | ||||
| outputs: | ||||
|   digest: | ||||
|     description: 'Image content-addressable identifier also called a digest' | ||||
|   metadata: | ||||
|     description: 'Build result metadata' | ||||
|  | ||||
| runs: | ||||
|   using: 'node12' | ||||
|   | ||||
							
								
								
									
										84
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										84
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -38,7 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.satisfies = exports.parseVersion = exports.getVersion = exports.isAvailable = exports.hasGitAuthToken = exports.isLocalOrTarExporter = exports.getSecret = exports.getSecretFile = exports.getSecretString = exports.getImageID = exports.getImageIDFile = void 0; | ||||
| exports.satisfies = exports.parseVersion = exports.getVersion = exports.isAvailable = exports.hasGitAuthToken = exports.isLocalOrTarExporter = exports.getSecret = exports.getSecretFile = exports.getSecretString = exports.getMetadata = exports.getMetadataFile = exports.getImageID = exports.getImageIDFile = void 0; | ||||
| const sync_1 = __importDefault(__nccwpck_require__(8750)); | ||||
| const fs_1 = __importDefault(__nccwpck_require__(5747)); | ||||
| const path_1 = __importDefault(__nccwpck_require__(5622)); | ||||
| @@ -61,6 +61,22 @@ function getImageID() { | ||||
|     }); | ||||
| } | ||||
| exports.getImageID = getImageID; | ||||
| function getMetadataFile() { | ||||
|     return __awaiter(this, void 0, void 0, function* () { | ||||
|         return path_1.default.join(context.tmpDir(), 'metadata-file').split(path_1.default.sep).join(path_1.default.posix.sep); | ||||
|     }); | ||||
| } | ||||
| exports.getMetadataFile = getMetadataFile; | ||||
| function getMetadata() { | ||||
|     return __awaiter(this, void 0, void 0, function* () { | ||||
|         const metadataFile = yield getMetadataFile(); | ||||
|         if (!fs_1.default.existsSync(metadataFile)) { | ||||
|             return undefined; | ||||
|         } | ||||
|         return fs_1.default.readFileSync(metadataFile, { encoding: 'utf-8' }); | ||||
|     }); | ||||
| } | ||||
| exports.getMetadata = getMetadata; | ||||
| function getSecretString(kvp) { | ||||
|     return __awaiter(this, void 0, void 0, function* () { | ||||
|         return getSecret(kvp, false); | ||||
| @@ -311,6 +327,9 @@ function getBuildArgs(inputs, defaultContext, buildxVersion) { | ||||
|         if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) { | ||||
|             args.push('--iidfile', yield buildx.getImageIDFile()); | ||||
|         } | ||||
|         if (buildx.satisfies(buildxVersion, '>=0.6.0')) { | ||||
|             args.push('--metadata-file', yield buildx.getMetadataFile()); | ||||
|         } | ||||
|         yield exports.asyncForEach(inputs.cacheFrom, (cacheFrom) => __awaiter(this, void 0, void 0, function* () { | ||||
|             args.push('--cache-from', cacheFrom); | ||||
|         })); | ||||
| @@ -476,13 +495,18 @@ function run() { | ||||
|                     throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)[0].trim()}`); | ||||
|                 } | ||||
|             }); | ||||
|             const imageID = yield buildx.getImageID(); | ||||
|             if (imageID) { | ||||
|                 core.startGroup(`Extracting digest`); | ||||
|                 core.info(`${imageID}`); | ||||
|                 context.setOutput('digest', imageID); | ||||
|                 core.endGroup(); | ||||
|             } | ||||
|             yield core.group(`Setting outputs`, () => __awaiter(this, void 0, void 0, function* () { | ||||
|                 const imageID = yield buildx.getImageID(); | ||||
|                 const metadata = yield buildx.getMetadata(); | ||||
|                 if (imageID) { | ||||
|                     core.info(`digest=${imageID}`); | ||||
|                     context.setOutput('digest', imageID); | ||||
|                 } | ||||
|                 if (metadata) { | ||||
|                     core.info(`metadata=${metadata}`); | ||||
|                     context.setOutput('metadata', metadata); | ||||
|                 } | ||||
|             })); | ||||
|         } | ||||
|         catch (error) { | ||||
|             core.setFailed(error.message); | ||||
| @@ -681,7 +705,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge | ||||
|     }); | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; | ||||
| exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; | ||||
| const command_1 = __nccwpck_require__(5241); | ||||
| const file_command_1 = __nccwpck_require__(717); | ||||
| const utils_1 = __nccwpck_require__(5278); | ||||
| @@ -859,19 +883,30 @@ exports.debug = debug; | ||||
| /** | ||||
|  * Adds an error issue | ||||
|  * @param message error issue message. Errors will be converted to string via toString() | ||||
|  * @param properties optional properties to add to the annotation. | ||||
|  */ | ||||
| function error(message) { | ||||
|     command_1.issue('error', message instanceof Error ? message.toString() : message); | ||||
| function error(message, properties = {}) { | ||||
|     command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); | ||||
| } | ||||
| exports.error = error; | ||||
| /** | ||||
|  * Adds an warning issue | ||||
|  * Adds a warning issue | ||||
|  * @param message warning issue message. Errors will be converted to string via toString() | ||||
|  * @param properties optional properties to add to the annotation. | ||||
|  */ | ||||
| function warning(message) { | ||||
|     command_1.issue('warning', message instanceof Error ? message.toString() : message); | ||||
| function warning(message, properties = {}) { | ||||
|     command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); | ||||
| } | ||||
| exports.warning = warning; | ||||
| /** | ||||
|  * Adds a notice issue | ||||
|  * @param message notice issue message. Errors will be converted to string via toString() | ||||
|  * @param properties optional properties to add to the annotation. | ||||
|  */ | ||||
| function notice(message, properties = {}) { | ||||
|     command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); | ||||
| } | ||||
| exports.notice = notice; | ||||
| /** | ||||
|  * Writes info to log with console.log. | ||||
|  * @param message info message | ||||
| @@ -1005,7 +1040,7 @@ exports.issueCommand = issueCommand; | ||||
| // We use any as a valid input type | ||||
| /* eslint-disable @typescript-eslint/no-explicit-any */ | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.toCommandValue = void 0; | ||||
| exports.toCommandProperties = exports.toCommandValue = void 0; | ||||
| /** | ||||
|  * Sanitizes an input into a string so it can be passed into issueCommand safely | ||||
|  * @param input input to sanitize into a string | ||||
| @@ -1020,6 +1055,25 @@ function toCommandValue(input) { | ||||
|     return JSON.stringify(input); | ||||
| } | ||||
| exports.toCommandValue = toCommandValue; | ||||
| /** | ||||
|  * | ||||
|  * @param annotationProperties | ||||
|  * @returns The command properties to send with the actual annotation command | ||||
|  * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 | ||||
|  */ | ||||
| function toCommandProperties(annotationProperties) { | ||||
|     if (!Object.keys(annotationProperties).length) { | ||||
|         return {}; | ||||
|     } | ||||
|     return { | ||||
|         title: annotationProperties.title, | ||||
|         line: annotationProperties.startLine, | ||||
|         endLine: annotationProperties.endLine, | ||||
|         col: annotationProperties.startColumn, | ||||
|         endColumn: annotationProperties.endColumn | ||||
|     }; | ||||
| } | ||||
| exports.toCommandProperties = toCommandProperties; | ||||
| //# sourceMappingURL=utils.js.map | ||||
|  | ||||
| /***/ }), | ||||
|   | ||||
| @@ -1,13 +1,18 @@ | ||||
| # 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 | ||||
| > More info about cache on [BuildKit](https://github.com/moby/buildkit#export-cache) and [Buildx](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from) repositories. | ||||
|  | ||||
| ## Registry cache | ||||
| ## Inline cache | ||||
|  | ||||
| You can import/export cache from a cache manifest or (special) image configuration on the registry. | ||||
| In most case you want to use the [`type=inline` cache exporter](https://github.com/moby/buildkit#inline-push-image-and-cache-together). | ||||
| 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 | ||||
| @@ -44,16 +49,104 @@ jobs: | ||||
|           cache-to: type=inline | ||||
| ``` | ||||
|  | ||||
| ## Registry cache | ||||
|  | ||||
| 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/moby/buildkit/tree/master#registry-push-image-and-cache-separately). | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|           cache-from: type=registry,ref=user/app:buildcache | ||||
|           cache-to: type=registry,ref=user/app:buildcache,mode=max | ||||
| ``` | ||||
|  | ||||
| ## GitHub cache | ||||
|  | ||||
| ### Cache backend API | ||||
|  | ||||
| > :test_tube: 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. | ||||
|  | ||||
| Since [buildx 0.6.0](https://github.com/docker/buildx/releases/tag/v0.6.0) and [BuildKit 0.9.0](https://github.com/moby/buildkit/releases/tag/v0.9.0), | ||||
| you can use the [`type=gha` cache exporter](https://github.com/moby/buildkit/tree/master#github-actions-cache-experimental). | ||||
|  | ||||
| GitHub Actions cache exporter 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: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   docker: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v2 | ||||
|       - | ||||
|         name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v1 | ||||
|       - | ||||
|         name: Login to DockerHub | ||||
|         uses: docker/login-action@v1  | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|       - | ||||
|         name: Build and push | ||||
|         uses: docker/build-push-action@v2 | ||||
|         with: | ||||
|           context: . | ||||
|           push: true | ||||
|           tags: user/app:latest | ||||
|           cache-from: type=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 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 also 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) and [`type=local` cache exporter](https://github.com/moby/buildkit#local-directory-1) | ||||
| with this action: | ||||
|  | ||||
| ```yaml | ||||
| name: ci | ||||
| @@ -95,7 +188,7 @@ jobs: | ||||
|           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,5 +1,10 @@ | ||||
| # syntax=docker/dockerfile:1.2 | ||||
| ARG NODE_VERSION | ||||
| ARG DOCKER_VERSION=20.10.7 | ||||
| ARG BUILDX_VERSION=0.6.0 | ||||
|  | ||||
| FROM docker:${DOCKER_VERSION} as docker | ||||
| FROM docker/buildx-bin:${BUILDX_VERSION} as buildx | ||||
|  | ||||
| FROM node:${NODE_VERSION}-alpine AS base | ||||
| RUN apk add --no-cache git | ||||
| @@ -15,8 +20,8 @@ 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 \ | ||||
|   --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 | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
|   ], | ||||
|   "license": "Apache-2.0", | ||||
|   "dependencies": { | ||||
|     "@actions/core": "^1.4.0", | ||||
|     "@actions/core": "^1.5.0", | ||||
|     "@actions/exec": "^1.1.0", | ||||
|     "@actions/github": "^5.0.0", | ||||
|     "csv-parse": "^4.16.0", | ||||
|   | ||||
| @@ -18,6 +18,18 @@ export async function getImageID(): Promise<string | undefined> { | ||||
|   return fs.readFileSync(iidFile, {encoding: 'utf-8'}); | ||||
| } | ||||
|  | ||||
| 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; | ||||
|   } | ||||
|   return fs.readFileSync(metadataFile, {encoding: 'utf-8'}); | ||||
| } | ||||
|  | ||||
| export async function getSecretString(kvp: string): Promise<string> { | ||||
|   return getSecret(kvp, false); | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,6 @@ 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'; | ||||
| @@ -122,6 +121,9 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio | ||||
|   if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) { | ||||
|     args.push('--iidfile', await buildx.getImageIDFile()); | ||||
|   } | ||||
|   if (buildx.satisfies(buildxVersion, '>=0.6.0')) { | ||||
|     args.push('--metadata-file', await buildx.getMetadataFile()); | ||||
|   } | ||||
|   await asyncForEach(inputs.cacheFrom, async cacheFrom => { | ||||
|     args.push('--cache-from', cacheFrom); | ||||
|   }); | ||||
|   | ||||
							
								
								
									
										19
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -33,13 +33,18 @@ async function run(): Promise<void> { | ||||
|         } | ||||
|       }); | ||||
|  | ||||
|     const imageID = await buildx.getImageID(); | ||||
|     if (imageID) { | ||||
|       core.startGroup(`Extracting digest`); | ||||
|       core.info(`${imageID}`); | ||||
|       context.setOutput('digest', imageID); | ||||
|       core.endGroup(); | ||||
|     } | ||||
|     await core.group(`Setting outputs`, async () => { | ||||
|       const imageID = await buildx.getImageID(); | ||||
|       const metadata = await buildx.getMetadata(); | ||||
|       if (imageID) { | ||||
|         core.info(`digest=${imageID}`); | ||||
|         context.setOutput('digest', imageID); | ||||
|       } | ||||
|       if (metadata) { | ||||
|         core.info(`metadata=${metadata}`); | ||||
|         context.setOutput('metadata', metadata); | ||||
|       } | ||||
|     }); | ||||
|   } catch (error) { | ||||
|     core.setFailed(error.message); | ||||
|   } | ||||
|   | ||||
| @@ -2,10 +2,10 @@ | ||||
| # yarn lockfile v1 | ||||
|  | ||||
|  | ||||
| "@actions/core@^1.4.0": | ||||
|   version "1.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.4.0.tgz#cf2e6ee317e314b03886adfeb20e448d50d6e524" | ||||
|   integrity sha512-CGx2ilGq5i7zSLgiiGUtBCxhRRxibJYU6Fim0Q1Wg2aQL2LTnF27zbqZOrxfvFQ55eSBW0L8uVStgtKMpa0Qlg== | ||||
| "@actions/core@^1.5.0": | ||||
|   version "1.5.0" | ||||
|   resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.5.0.tgz#885b864700001a1b9a6fba247833a036e75ad9d3" | ||||
|   integrity sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ== | ||||
|  | ||||
| "@actions/exec@^1.1.0": | ||||
|   version "1.1.0" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user