From 75ffdcce887d6fc1a2125373054adab1d5e169a2 Mon Sep 17 00:00:00 2001
From: CrazyMax <1951866+crazy-max@users.noreply.github.com>
Date: Mon, 25 Nov 2024 17:14:29 +0100
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 | 32 ++++++++++++++++++++++++++++++--
 README.md                |  1 +
 action.yml               |  3 +++
 src/context.ts           |  8 ++++++++
 src/main.ts              | 12 ++++++++++--
 5 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 71bca85..387dff8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -288,7 +288,6 @@ jobs:
       -
         name: Check
         run: |
-          echo "${{ toJson(steps.docker_build) }}"
           if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
             echo "::error::Should have failed"
             exit 1
@@ -324,7 +323,6 @@ jobs:
       -
         name: Check
         run: |
-          echo "${{ toJson(steps.docker_build) }}"
           if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
             echo "::error::Should have failed"
             exit 1
@@ -1511,3 +1509,33 @@ jobs:
           file: ./test/lint.Dockerfile
         env:
           DOCKER_BUILD_CHECKS_ANNOTATIONS: false
+
+  call-check:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v4
+      -
+        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: docker_build
+        continue-on-error: true
+        uses: ./
+        with:
+          context: ./test
+          file: ./test/lint.Dockerfile
+          call: check
+      -
+        name: Check
+        run: |
+          if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
+            echo "::error::Should have failed"
+            exit 1
+          fi
diff --git a/README.md b/README.md
index 81ce7f1..981e7d4 100644
--- a/README.md
+++ b/README.md
@@ -220,6 +220,7 @@ The following inputs can be used as `step.with` keys:
 | `build-contexts`   | List        | List of additional [build contexts](https://docs.docker.com/engine/reference/commandline/buildx_build/#build-context) (e.g., `name=path`)                                         |
 | `cache-from`       | List        | List of [external cache sources](https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from) (e.g., `type=local,src=path/to/dir`)                              |
 | `cache-to`         | List        | List of [cache export destinations](https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to) (e.g., `type=local,dest=path/to/dir`)                            |
+| `call`             | String      | Set [method for evaluating build](https://docs.docker.com/reference/cli/docker/buildx/build/#call) (e.g., `check`)                                                                |
 | `cgroup-parent`    | String      | Optional [parent cgroup](https://docs.docker.com/engine/reference/commandline/build/#use-a-custom-parent-cgroup---cgroup-parent) for the container used in the build              |
 | `context`          | String      | Build's context is the set of files located in the specified [`PATH` or `URL`](https://docs.docker.com/engine/reference/commandline/build/) (default [Git context](#git-context)) |
 | `file`             | String      | Path to the Dockerfile. (default `{context}/Dockerfile`)                                                                                                                          |
diff --git a/action.yml b/action.yml
index 2fa9806..d8ce5d9 100644
--- a/action.yml
+++ b/action.yml
@@ -34,6 +34,9 @@ inputs:
   cache-to:
     description: "List of cache export destinations for buildx (e.g., user/app:cache, type=local,dest=path/to/dir)"
     required: false
+  call:
+    description: "Set method for evaluating build (e.g., check)"
+    required: false
   cgroup-parent:
     description: "Optional parent cgroup for the container used in the build"
     required: false
diff --git a/src/context.ts b/src/context.ts
index 7dd57c5..37b953e 100644
--- a/src/context.ts
+++ b/src/context.ts
@@ -17,6 +17,7 @@ export interface Inputs {
   builder: string;
   'cache-from': string[];
   'cache-to': string[];
+  call: string;
   'cgroup-parent': string;
   context: string;
   file: string;
@@ -53,6 +54,7 @@ export async function getInputs(): Promise<Inputs> {
     builder: core.getInput('builder'),
     'cache-from': Util.getInputList('cache-from', {ignoreComma: true}),
     'cache-to': Util.getInputList('cache-to', {ignoreComma: true}),
+    call: core.getInput('call'),
     'cgroup-parent': core.getInput('cgroup-parent'),
     context: core.getInput('context') || Context.gitContext(),
     file: core.getInput('file'),
@@ -141,6 +143,12 @@ async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit):
   await Util.asyncForEach(inputs['cache-to'], async cacheTo => {
     args.push('--cache-to', cacheTo);
   });
+  if (inputs.call) {
+    if (!(await toolkit.buildx.versionSatisfies('>=0.15.0'))) {
+      throw new Error(`Buildx >= 0.15.0 is required to use the call flag.`);
+    }
+    args.push('--call', inputs.call);
+  }
   if (inputs['cgroup-parent']) {
     args.push('--cgroup-parent', inputs['cgroup-parent']);
   }
diff --git a/src/main.ts b/src/main.ts
index 2824fa8..3525cfd 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -104,8 +104,14 @@ actionsToolkit.run(
         [key: string]: string;
       }
     }).then(res => {
-      if (res.stderr.length > 0 && res.exitCode != 0) {
-        err = Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
+      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
+          // take the first line with the message summaryzing the warnings
+          err = Error(res.stdout.split('\n')[0]?.trim());
+        } else if (res.stderr.length > 0) {
+          err = Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
+        }
       }
     });
 
@@ -161,6 +167,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'))) {