From 24d8c3471c7a1ac0a817d90b6083a096e7073880 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Wed, 30 Jul 2025 15:20:30 +0200 Subject: [PATCH] call input to set method for evaluating build Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/ci.yml | 90 +++++++++++++++++++++++++++++++++++++++- README.md | 5 ++- action.yml | 17 ++++---- src/context.ts | 24 +++++++---- src/main.ts | 24 ++++++++++- 5 files changed, 140 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 107f3a4..a967713 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 @@ -779,3 +778,92 @@ jobs: ./test/config.hcl env: BUILDX_NO_DEFAULT_ATTESTATIONS: 1 + + call-check: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v5 + - + 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@v5 + - + 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@v5 + - + 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 diff --git a/README.md b/README.md index 10fc84a..8d0530a 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/action.yml b/action.yml index 361f317..6d5ccb1 100644 --- a/action.yml +++ b/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 }} diff --git a/src/context.ts b/src/context.ts index 882c1c7..cff0f3b 100644 --- a/src/context.ts +++ b/src/context.ts @@ -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 { 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 { 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); }); diff --git a/src/main.ts b/src/main.ts index 0c2b9f9..0a1b689 100644 --- a/src/main.ts +++ b/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'))) {