mirror of
https://git.flexiblyrigid.au/actions/bake-action.git
synced 2025-12-06 15:58:07 +08:00
Compare commits
33 Commits
1a42865db7
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f0ddf5080 | ||
|
|
5be5f02ff8 | ||
|
|
4f25520e7a | ||
|
|
eeacb3deff | ||
|
|
cce027f633 | ||
|
|
53ce91f18b | ||
|
|
6b8437d2b5 | ||
|
|
d14785b0cb | ||
|
|
597dc07998 | ||
|
|
8ba51ac4ee | ||
|
|
23c049fba9 | ||
|
|
41c10f2beb | ||
|
|
5b9bf92d49 | ||
|
|
3acf805d94 | ||
|
|
f6376ff6a4 | ||
|
|
60b3af61bc | ||
|
|
f08ef55f78 | ||
|
|
c22b3482ed | ||
|
|
40bffc195e | ||
|
|
d7a0b5eb51 | ||
|
|
3965f4baf4 | ||
|
|
3d864c34f9 | ||
|
|
3589b0c183 | ||
|
|
2215fae6ab | ||
|
|
d0cb9774dc | ||
|
|
a6c0a91e79 | ||
|
|
74cb41d332 | ||
|
|
8f035c08cd | ||
|
|
a4c28defc8 | ||
|
|
d260a27f75 | ||
|
|
5efdf4de8d | ||
|
|
7a78e75fa4 | ||
|
|
24d8c3471c |
8
.github/workflows/ci-subaction.yml
vendored
8
.github/workflows/ci-subaction.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Matrix gen
|
||||
id: gen
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
-
|
||||
name: Check output
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
env:
|
||||
INPUT_TARGETS: ${{ steps.gen.outputs.targets }}
|
||||
INPUT_EXPECTED: ${{ matrix.expected }}
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Matrix gen
|
||||
id: gen
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
fields: ${{ matrix.fields }}
|
||||
-
|
||||
name: Check output
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
env:
|
||||
INPUT_MATRIX: ${{ steps.gen.outputs.matrix }}
|
||||
INPUT_EXPECTED: ${{ matrix.expected }}
|
||||
|
||||
162
.github/workflows/ci.yml
vendored
162
.github/workflows/ci.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
continue-on-error: true
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Stop docker
|
||||
run: |
|
||||
@@ -116,7 +116,6 @@ jobs:
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.bake) }}"
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
@@ -127,7 +126,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Uninstall docker cli
|
||||
run: |
|
||||
@@ -156,7 +155,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
@@ -178,7 +177,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -220,7 +219,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -275,7 +274,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
@@ -297,7 +296,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -322,7 +321,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set malformed docker config
|
||||
run: |
|
||||
@@ -351,7 +350,7 @@ jobs:
|
||||
curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy http://127.0.0.1:3128 -v --insecure --head https://www.google.com
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set proxy config
|
||||
run: |
|
||||
@@ -390,7 +389,7 @@ jobs:
|
||||
curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy http://127.0.0.1:3128 -v --insecure --head https://www.google.com
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -415,7 +414,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -432,7 +431,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -461,7 +460,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -505,7 +504,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -538,7 +537,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -561,7 +560,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -585,7 +584,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -606,7 +605,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -635,7 +634,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -664,7 +663,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -693,7 +692,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -715,7 +714,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -747,7 +746,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -769,7 +768,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
@@ -779,3 +778,112 @@ jobs:
|
||||
./test/config.hcl
|
||||
env:
|
||||
BUILDX_NO_DEFAULT_ATTESTATIONS: 1
|
||||
|
||||
call-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
workdir: ./test
|
||||
source: .
|
||||
files: |
|
||||
./lint.hcl
|
||||
call: check
|
||||
targets: lint
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
call-check-multi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
workdir: ./test
|
||||
source: .
|
||||
files: |
|
||||
./lint.hcl
|
||||
call: check
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
if [ "${{ steps.bake.outcome }}" != "failure" ] || [ "${{ steps.bake.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
call-check-nowarning:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build
|
||||
id: bake
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./test/config.hcl
|
||||
call: check
|
||||
|
||||
attest-override:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: ./
|
||||
with:
|
||||
workdir: ./test/attest
|
||||
source: .
|
||||
|
||||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Publish
|
||||
uses: actions/publish-immutable-action@v0.0.4
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v6
|
||||
|
||||
2
.github/workflows/validate.yml
vendored
2
.github/workflows/validate.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
-
|
||||
name: List targets
|
||||
id: generate
|
||||
|
||||
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
File diff suppressed because one or more lines are too long
12
.yarnrc.yml
12
.yarnrc.yml
@@ -1,3 +1,9 @@
|
||||
# https://yarnpkg.com/configuration/yarnrc
|
||||
|
||||
compressionLevel: mixed
|
||||
enableGlobalCache: false
|
||||
enableHardenedMode: true
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
@@ -5,9 +11,7 @@ logFilters:
|
||||
level: discard
|
||||
- code: YN0076
|
||||
level: discard
|
||||
- code: YN0086
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
||||
|
||||
@@ -200,11 +200,11 @@ The following inputs can be used as `step.with` keys
|
||||
| Name | Type | Description |
|
||||
|----------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||
| `workdir` | String | Working directory of execution |
|
||||
| `source` | String | Context to build from. Can be either local (`.`) or a [remote bake definition](https://docs.docker.com/build/bake/remote-definition/) |
|
||||
| `allow` | List/CSV | Allow build to access specified resources (e.g., `network.host`) |
|
||||
| `call` | String | Set method for evaluating build (e.g., check) |
|
||||
| `files` | List/CSV | List of [bake definition files](https://docs.docker.com/build/customize/bake/file-definition/) |
|
||||
| `workdir` | String | Working directory of execution |
|
||||
| `targets` | List/CSV | List of bake targets (`default` target used if empty) |
|
||||
| `no-cache` | Bool | Do not use cache when building the image (default `false`) |
|
||||
| `pull` | Bool | Always attempt to pull a newer version of the image (default `false`) |
|
||||
| `load` | Bool | Load is a shorthand for `--set=*.output=type=docker` (default `false`) |
|
||||
@@ -212,6 +212,7 @@ The following inputs can be used as `step.with` keys
|
||||
| `push` | Bool | Push is a shorthand for `--set=*.output=type=registry` (default `false`) |
|
||||
| `sbom` | Bool/String | [SBOM](https://docs.docker.com/build/attestations/sbom/) is a shorthand for `--set=*.attest=type=sbom` |
|
||||
| `set` | List | List of [targets values to override](https://docs.docker.com/engine/reference/commandline/buildx_bake/#set) (e.g., `targetpattern.key=value`) |
|
||||
| `targets` | List/CSV | List of bake targets (`default` target used if empty) |
|
||||
| `github-token` | String | API token used to authenticate to a Git repository for [remote definitions](https://docs.docker.com/build/bake/remote-definition/) (default `${{ github.token }}`) |
|
||||
|
||||
### outputs
|
||||
|
||||
@@ -218,7 +218,9 @@ describe('getArgs', () => {
|
||||
[
|
||||
'bake',
|
||||
'--metadata-file', metadataJson,
|
||||
"--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
],
|
||||
undefined
|
||||
],
|
||||
@@ -311,7 +313,9 @@ describe('getArgs', () => {
|
||||
'--set', '*.platform=linux/amd64,linux/ppc64le,linux/s390x',
|
||||
'--set', `*.output=type=image,"name=moby/buildkit:v0.11.0,moby/buildkit:latest",push=true`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--provenance', `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'image-all'
|
||||
],
|
||||
undefined
|
||||
@@ -332,7 +336,9 @@ describe('getArgs', () => {
|
||||
'bake',
|
||||
'--set', `*.labels.foo=bar=#baz`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--provenance', `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'image-all'
|
||||
],
|
||||
undefined
|
||||
@@ -352,7 +358,9 @@ describe('getArgs', () => {
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master',
|
||||
'--file', './foo.hcl',
|
||||
'--metadata-file', metadataJson,
|
||||
'--provenance', `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
@@ -371,7 +379,9 @@ describe('getArgs', () => {
|
||||
'bake',
|
||||
'--allow', 'network.host',
|
||||
'--metadata-file', metadataJson,
|
||||
"--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
@@ -391,7 +401,9 @@ describe('getArgs', () => {
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master:subdir',
|
||||
'--file', './foo.hcl',
|
||||
'--metadata-file', metadataJson,
|
||||
'--provenance', `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `lint.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-docs.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--set', `validate-vendor.attest=type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`
|
||||
],
|
||||
undefined
|
||||
],
|
||||
|
||||
17
action.yml
17
action.yml
@@ -10,22 +10,22 @@ inputs:
|
||||
builder:
|
||||
description: "Builder instance"
|
||||
required: false
|
||||
workdir:
|
||||
description: "Working directory of bake execution"
|
||||
required: false
|
||||
default: '.'
|
||||
source:
|
||||
description: "Context to build from. Can be either local or a remote bake definition"
|
||||
required: false
|
||||
allow:
|
||||
description: "Allow build to access specified resources (e.g., network.host)"
|
||||
required: false
|
||||
call:
|
||||
description: "Set method for evaluating build (e.g., check)"
|
||||
required: false
|
||||
files:
|
||||
description: "List of bake definition files"
|
||||
required: false
|
||||
workdir:
|
||||
description: "Working directory of bake execution"
|
||||
required: false
|
||||
default: '.'
|
||||
targets:
|
||||
description: "List of bake targets"
|
||||
required: false
|
||||
no-cache:
|
||||
description: "Do not use cache when building the image"
|
||||
required: false
|
||||
@@ -51,6 +51,9 @@ inputs:
|
||||
set:
|
||||
description: "List of targets values to override (eg. targetpattern.key=value)"
|
||||
required: false
|
||||
targets:
|
||||
description: "List of bake targets"
|
||||
required: false
|
||||
github-token:
|
||||
description: "API token used to authenticate to a Git repository for remote definitions"
|
||||
default: ${{ github.token }}
|
||||
|
||||
302
dist/606.index.js
generated
vendored
Normal file
302
dist/606.index.js
generated
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
"use strict";
|
||||
exports.id = 606;
|
||||
exports.ids = [606];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 606:
|
||||
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||
/* harmony export */ "default": () => (/* binding */ pMap)
|
||||
/* harmony export */ });
|
||||
/* unused harmony exports pMapIterable, pMapSkip */
|
||||
async function pMap(
|
||||
iterable,
|
||||
mapper,
|
||||
{
|
||||
concurrency = Number.POSITIVE_INFINITY,
|
||||
stopOnError = true,
|
||||
signal,
|
||||
} = {},
|
||||
) {
|
||||
return new Promise((resolve_, reject_) => {
|
||||
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
|
||||
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
|
||||
}
|
||||
|
||||
if (typeof mapper !== 'function') {
|
||||
throw new TypeError('Mapper function is required');
|
||||
}
|
||||
|
||||
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
|
||||
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
|
||||
}
|
||||
|
||||
const result = [];
|
||||
const errors = [];
|
||||
const skippedIndexesMap = new Map();
|
||||
let isRejected = false;
|
||||
let isResolved = false;
|
||||
let isIterableDone = false;
|
||||
let resolvingCount = 0;
|
||||
let currentIndex = 0;
|
||||
const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
|
||||
|
||||
const signalListener = () => {
|
||||
reject(signal.reason);
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
signal?.removeEventListener('abort', signalListener);
|
||||
};
|
||||
|
||||
const resolve = value => {
|
||||
resolve_(value);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
const reject = reason => {
|
||||
isRejected = true;
|
||||
isResolved = true;
|
||||
reject_(reason);
|
||||
cleanup();
|
||||
};
|
||||
|
||||
if (signal) {
|
||||
if (signal.aborted) {
|
||||
reject(signal.reason);
|
||||
}
|
||||
|
||||
signal.addEventListener('abort', signalListener, {once: true});
|
||||
}
|
||||
|
||||
const next = async () => {
|
||||
if (isResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextItem = await iterator.next();
|
||||
|
||||
const index = currentIndex;
|
||||
currentIndex++;
|
||||
|
||||
// Note: `iterator.next()` can be called many times in parallel.
|
||||
// This can cause multiple calls to this `next()` function to
|
||||
// receive a `nextItem` with `done === true`.
|
||||
// The shutdown logic that rejects/resolves must be protected
|
||||
// so it runs only one time as the `skippedIndex` logic is
|
||||
// non-idempotent.
|
||||
if (nextItem.done) {
|
||||
isIterableDone = true;
|
||||
|
||||
if (resolvingCount === 0 && !isResolved) {
|
||||
if (!stopOnError && errors.length > 0) {
|
||||
reject(new AggregateError(errors)); // eslint-disable-line unicorn/error-message
|
||||
return;
|
||||
}
|
||||
|
||||
isResolved = true;
|
||||
|
||||
if (skippedIndexesMap.size === 0) {
|
||||
resolve(result);
|
||||
return;
|
||||
}
|
||||
|
||||
const pureResult = [];
|
||||
|
||||
// Support multiple `pMapSkip`'s.
|
||||
for (const [index, value] of result.entries()) {
|
||||
if (skippedIndexesMap.get(index) === pMapSkip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pureResult.push(value);
|
||||
}
|
||||
|
||||
resolve(pureResult);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
resolvingCount++;
|
||||
|
||||
// Intentionally detached
|
||||
(async () => {
|
||||
try {
|
||||
const element = await nextItem.value;
|
||||
|
||||
if (isResolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = await mapper(element, index);
|
||||
|
||||
// Use Map to stage the index of the element.
|
||||
if (value === pMapSkip) {
|
||||
skippedIndexesMap.set(index, value);
|
||||
}
|
||||
|
||||
result[index] = value;
|
||||
|
||||
resolvingCount--;
|
||||
await next();
|
||||
} catch (error) {
|
||||
if (stopOnError) {
|
||||
reject(error);
|
||||
} else {
|
||||
errors.push(error);
|
||||
resolvingCount--;
|
||||
|
||||
// In that case we can't really continue regardless of `stopOnError` state
|
||||
// since an iterable is likely to continue throwing after it throws once.
|
||||
// If we continue calling `next()` indefinitely we will likely end up
|
||||
// in an infinite loop of failed iteration.
|
||||
try {
|
||||
await next();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
// Create the concurrent runners in a detached (non-awaited)
|
||||
// promise. We need this so we can await the `next()` calls
|
||||
// to stop creating runners before hitting the concurrency limit
|
||||
// if the iterable has already been marked as done.
|
||||
// NOTE: We *must* do this for async iterators otherwise we'll spin up
|
||||
// infinite `next()` calls by default and never start the event loop.
|
||||
(async () => {
|
||||
for (let index = 0; index < concurrency; index++) {
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await next();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (isIterableDone || isRejected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
function pMapIterable(
|
||||
iterable,
|
||||
mapper,
|
||||
{
|
||||
concurrency = Number.POSITIVE_INFINITY,
|
||||
backpressure = concurrency,
|
||||
} = {},
|
||||
) {
|
||||
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
|
||||
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
|
||||
}
|
||||
|
||||
if (typeof mapper !== 'function') {
|
||||
throw new TypeError('Mapper function is required');
|
||||
}
|
||||
|
||||
if (!((Number.isSafeInteger(concurrency) && concurrency >= 1) || concurrency === Number.POSITIVE_INFINITY)) {
|
||||
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
|
||||
}
|
||||
|
||||
if (!((Number.isSafeInteger(backpressure) && backpressure >= concurrency) || backpressure === Number.POSITIVE_INFINITY)) {
|
||||
throw new TypeError(`Expected \`backpressure\` to be an integer from \`concurrency\` (${concurrency}) and up or \`Infinity\`, got \`${backpressure}\` (${typeof backpressure})`);
|
||||
}
|
||||
|
||||
return {
|
||||
async * [Symbol.asyncIterator]() {
|
||||
const iterator = iterable[Symbol.asyncIterator] === undefined ? iterable[Symbol.iterator]() : iterable[Symbol.asyncIterator]();
|
||||
|
||||
const promises = [];
|
||||
let pendingPromisesCount = 0;
|
||||
let isDone = false;
|
||||
let index = 0;
|
||||
|
||||
function trySpawn() {
|
||||
if (isDone || !(pendingPromisesCount < concurrency && promises.length < backpressure)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pendingPromisesCount++;
|
||||
|
||||
const promise = (async () => {
|
||||
const {done, value} = await iterator.next();
|
||||
|
||||
if (done) {
|
||||
pendingPromisesCount--;
|
||||
return {done: true};
|
||||
}
|
||||
|
||||
// Spawn if still below concurrency and backpressure limit
|
||||
trySpawn();
|
||||
|
||||
try {
|
||||
const returnValue = await mapper(await value, index++);
|
||||
|
||||
pendingPromisesCount--;
|
||||
|
||||
if (returnValue === pMapSkip) {
|
||||
const index = promises.indexOf(promise);
|
||||
|
||||
if (index > 0) {
|
||||
promises.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn if still below backpressure limit and just dropped below concurrency limit
|
||||
trySpawn();
|
||||
|
||||
return {done: false, value: returnValue};
|
||||
} catch (error) {
|
||||
pendingPromisesCount--;
|
||||
isDone = true;
|
||||
return {error};
|
||||
}
|
||||
})();
|
||||
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
trySpawn();
|
||||
|
||||
while (promises.length > 0) {
|
||||
const {error, done, value} = await promises[0]; // eslint-disable-line no-await-in-loop
|
||||
|
||||
promises.shift();
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn if just dropped below backpressure limit and below the concurrency limit
|
||||
trySpawn();
|
||||
|
||||
if (value === pMapSkip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield value;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const pMapSkip = Symbol('skip');
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
//# sourceMappingURL=606.index.js.map
|
||||
1
dist/606.index.js.map
generated
vendored
Normal file
1
dist/606.index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
74
dist/index.js
generated
vendored
74
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
3915
dist/licenses.txt
generated
vendored
3915
dist/licenses.txt
generated
vendored
File diff suppressed because it is too large
Load Diff
2
dist/sourcemap-register.js
generated
vendored
2
dist/sourcemap-register.js
generated
vendored
File diff suppressed because one or more lines are too long
26
package.json
26
package.json
@@ -24,25 +24,25 @@
|
||||
],
|
||||
"author": "Docker Inc.",
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@3.6.3",
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@docker/actions-toolkit": "^0.62.1",
|
||||
"@docker/actions-toolkit": "^0.68.0",
|
||||
"handlebars": "^4.7.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.12",
|
||||
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
||||
"@typescript-eslint/parser": "^7.9.0",
|
||||
"@vercel/ncc": "^0.38.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-jest": "^28.5.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"@types/node": "^20.19.9",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^9.1.2",
|
||||
"eslint-plugin-jest": "^28.14.0",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"prettier": "^3.6.2",
|
||||
"ts-jest": "^29.4.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "^5.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,12 @@ import {Util} from '@docker/actions-toolkit/lib/util';
|
||||
import {BakeDefinition} from '@docker/actions-toolkit/lib/types/buildx/bake';
|
||||
|
||||
export interface Inputs {
|
||||
allow: string[];
|
||||
builder: string;
|
||||
files: string[];
|
||||
workdir: string;
|
||||
targets: string[];
|
||||
source: string;
|
||||
allow: string[];
|
||||
call: string;
|
||||
files: string[];
|
||||
'no-cache': boolean;
|
||||
pull: boolean;
|
||||
load: boolean;
|
||||
@@ -23,17 +24,18 @@ export interface Inputs {
|
||||
push: boolean;
|
||||
sbom: string;
|
||||
set: string[];
|
||||
source: string;
|
||||
targets: string[];
|
||||
'github-token': string;
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
return {
|
||||
allow: Util.getInputList('allow'),
|
||||
builder: core.getInput('builder'),
|
||||
files: Util.getInputList('files'),
|
||||
workdir: core.getInput('workdir') || '.',
|
||||
targets: Util.getInputList('targets'),
|
||||
source: getSourceInput('source'),
|
||||
allow: Util.getInputList('allow'),
|
||||
call: core.getInput('call'),
|
||||
files: Util.getInputList('files'),
|
||||
'no-cache': core.getBooleanInput('no-cache'),
|
||||
pull: core.getBooleanInput('pull'),
|
||||
load: core.getBooleanInput('load'),
|
||||
@@ -41,7 +43,7 @@ export async function getInputs(): Promise<Inputs> {
|
||||
push: core.getBooleanInput('push'),
|
||||
sbom: core.getInput('sbom'),
|
||||
set: Util.getInputList('set', {ignoreComma: true, quote: false}),
|
||||
source: getSourceInput('source'),
|
||||
targets: Util.getInputList('targets'),
|
||||
'github-token': core.getInput('github-token')
|
||||
};
|
||||
}
|
||||
@@ -69,6 +71,12 @@ async function getBakeArgs(inputs: Inputs, definition: BakeDefinition, toolkit:
|
||||
args.push('--allow', allow);
|
||||
});
|
||||
}
|
||||
if (inputs.call) {
|
||||
if (!(await toolkit.buildx.versionSatisfies('>=0.16.0'))) {
|
||||
throw new Error(`Buildx >= 0.16.0 is required to use the call flag.`);
|
||||
}
|
||||
args.push('--call', inputs.call);
|
||||
}
|
||||
await Util.asyncForEach(inputs.files, async file => {
|
||||
args.push('--file', file);
|
||||
});
|
||||
@@ -82,16 +90,22 @@ async function getBakeArgs(inputs: Inputs, definition: BakeDefinition, toolkit:
|
||||
if (inputs.provenance) {
|
||||
args.push('--provenance', inputs.provenance);
|
||||
} else if (!noDefaultAttestations() && (await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !Bake.hasDockerExporter(definition, inputs.load)) {
|
||||
// if provenance not specified and BuildKit version compatible for
|
||||
// check if provenance attestation is already specified in the bake
|
||||
// definition and if not specified and BuildKit version compatible for
|
||||
// attestation, set default provenance. Also needs to make sure user
|
||||
// doesn't want to explicitly load the image to docker.
|
||||
if (GitHub.context.payload.repository?.private ?? false) {
|
||||
// if this is a private repository, we set the default provenance
|
||||
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
|
||||
args.push('--provenance', Build.resolveProvenanceAttrs(`mode=min,inline-only=true`));
|
||||
} else {
|
||||
// for a public repository, we set max provenance mode.
|
||||
args.push('--provenance', Build.resolveProvenanceAttrs(`mode=max`));
|
||||
for (const targetName in definition.target) {
|
||||
const target = definition.target[targetName];
|
||||
if (!Array.isArray(target.attest) || !target.attest.some(attest => attest?.type === 'provenance')) {
|
||||
if (GitHub.context.payload.repository?.private ?? false) {
|
||||
// if this is a private repository, we set the default provenance
|
||||
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
|
||||
args.push('--set', `${targetName}.attest=type=provenance,${Build.resolveProvenanceAttrs(`mode=min,inline-only=true`)}`);
|
||||
} else {
|
||||
// for a public repository, we set max provenance mode.
|
||||
args.push('--set', `${targetName}.attest=type=provenance,${Build.resolveProvenanceAttrs(`mode=max`)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inputs.sbom) {
|
||||
|
||||
24
src/main.ts
24
src/main.ts
@@ -146,8 +146,26 @@ actionsToolkit.run(
|
||||
env: buildEnv,
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
err = Error(`buildx bake failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
if (res.exitCode != 0) {
|
||||
if (inputs.call && inputs.call === 'check' && res.stdout.length > 0) {
|
||||
// checks warnings are printed to stdout: https://github.com/docker/buildx/pull/2647
|
||||
// with bake we can have multiple targets being checked so we need to
|
||||
// count the total number of warnings
|
||||
const totalWarnings = [...res.stdout.matchAll(/^Check complete, (\d+) warnings? (?:has|have) been found!/gm)].reduce((sum, m) => sum + parseInt(m[1], 10), 0);
|
||||
if (totalWarnings > 0) {
|
||||
// https://github.com/docker/buildx/blob/1e50e8ddabe108f009b9925e13a321d7c8f99f26/commands/build.go#L797-L803
|
||||
if (totalWarnings === 1) {
|
||||
err = Error(`Check complete, ${totalWarnings} warning has been found!`);
|
||||
} else {
|
||||
err = Error(`Check complete, ${totalWarnings} warnings have been found!`);
|
||||
}
|
||||
} else {
|
||||
// if there are no warnings found, return the first line of stdout
|
||||
err = Error(res.stdout.split('\n')[0]?.trim());
|
||||
}
|
||||
} else if (res.stderr.length > 0) {
|
||||
err = Error(`buildx bake failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -191,6 +209,8 @@ actionsToolkit.run(
|
||||
await core.group(`Check build summary support`, async () => {
|
||||
if (!buildSummaryEnabled()) {
|
||||
core.info('Build summary disabled');
|
||||
} else if (inputs.call && inputs.call !== 'build') {
|
||||
core.info(`Build summary skipped for ${inputs.call} subrequest`);
|
||||
} else if (GitHub.isGHES) {
|
||||
core.info('Build summary is not yet supported on GHES');
|
||||
} else if (!(await toolkit.buildx.versionSatisfies('>=0.13.0'))) {
|
||||
|
||||
10
test/attest/Dockerfile
Normal file
10
test/attest/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM busybox AS t1
|
||||
RUN echo "Hello t1"
|
||||
|
||||
FROM busybox AS t2
|
||||
RUN echo "Hello t2"
|
||||
|
||||
FROM busybox AS t3
|
||||
RUN echo "Hello t3"
|
||||
17
test/attest/docker-bake.hcl
Normal file
17
test/attest/docker-bake.hcl
Normal file
@@ -0,0 +1,17 @@
|
||||
group "default" {
|
||||
targets = ["t1", "t2", "t3"]
|
||||
}
|
||||
|
||||
target "t1" {
|
||||
target = "t1"
|
||||
}
|
||||
|
||||
target "t2" {
|
||||
target = "t2"
|
||||
attest = ["type=provenance,mode=min"]
|
||||
}
|
||||
|
||||
target "t3" {
|
||||
target = "t3"
|
||||
attest = ["type=sbom"]
|
||||
}
|
||||
Reference in New Issue
Block a user