diff --git a/.github/workflows/.test-bake.yml b/.github/workflows/.test-bake.yml index ad224dd9..0fd64847 100644 --- a/.github/workflows/.test-bake.yml +++ b/.github/workflows/.test-bake.yml @@ -598,11 +598,10 @@ jobs: contents: read id-token: write with: - setup-qemu: true artifact-upload: false context: test output: local - target: go + target: vars vars: | XX_VERSION=1.9.0 diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 59988a9c..8e2ef74a 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -342,6 +342,7 @@ jobs: const { GitHub } = require('@docker/github-builder-runtime/lib/github/github'); const { RunnerMapping } = require('@docker/github-builder-runtime/lib/github-builder/runner-mapping'); const { BakeTargets } = require('@docker/github-builder-runtime/lib/github-builder/bake-targets'); + const { BakeVars } = require('@docker/github-builder-runtime/lib/github-builder/bake-vars'); const { Util } = require('@docker/github-builder-runtime/lib/util'); const inpSbomImage = core.getInput('sbom-image'); @@ -354,7 +355,7 @@ jobs: const inpArtifactUpload = core.getBooleanInput('artifact-upload'); const inpJobNamePrefix = core.getInput('job-name-prefix'); const inpContext = core.getInput('context'); - const inpVars = Util.getInputList('vars'); + const inpVars = Util.getInputList('vars', {ignoreComma: true, quote: false}); const inpFiles = Util.getInputList('files'); const inpOutput = core.getInput('output'); const inpPush = core.getBooleanInput('push'); @@ -404,21 +405,12 @@ jobs: } const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true'; - const envs = Object.assign({}, - inpVars ? inpVars.reduce((acc, curr) => { - const idx = curr.indexOf('='); - if (idx !== -1) { - acc[curr.substring(0, idx)] = curr.substring(idx + 1); - } - return acc; - }, {}) : {}, - { - BUILDKIT_MULTI_PLATFORM: '1', - BUILDX_BAKE_GIT_AUTH_TOKEN: inpGitHubToken - } - ); - await core.group(`Set envs`, async () => { - core.info(JSON.stringify(Object.keys(envs).sort(), null, 2)); + const bakeVars = BakeVars.resolve(inpVars); + await core.group(`Set bake vars`, async () => { + core.info(JSON.stringify(bakeVars.map(value => { + const idx = value.indexOf('='); + return idx === -1 ? '' : value.substring(0, idx); + }).sort(), null, 2)); }); const metaImages = inpMetaImages.map(image => image.toLowerCase()); @@ -443,9 +435,14 @@ jobs: overrides: [...validationOverrides, '*.secrets='], sbom: inpSbom ? `generator=${inpSbomImage}` : 'false', source: bakeSource, - targets: [inpTarget] + targets: [inpTarget], + vars: bakeVars, + githubToken: inpGitHubToken }, { - env: Object.keys(envs).length > 0 ? envs : undefined + env: { + BUILDKIT_MULTI_PLATFORM: '1', + BUILDX_BAKE_DISABLE_VARS_ENV_LOOKUP: '1' + } }); if (!def) { throw new Error('Bake definition not set'); @@ -851,6 +848,7 @@ jobs: const os = require('os'); const { Build } = require('@docker/github-builder-runtime/lib/buildx/build'); const { BuildSecrets } = require('@docker/github-builder-runtime/lib/github-builder/build-secrets'); + const { BakeVars } = require('@docker/github-builder-runtime/lib/github-builder/bake-vars'); const { GitHub } = require('@docker/github-builder-runtime/lib/github/github'); const { Util } = require('@docker/github-builder-runtime/lib/util'); @@ -873,7 +871,7 @@ jobs: const inpSbom = core.getBooleanInput('sbom'); const inpSet = Util.getInputList('set', {ignoreComma: true, quote: false}); const inpTarget = core.getInput('target'); - const inpVars = Util.getInputList('vars'); + const inpVars = Util.getInputList('vars', {ignoreComma: true, quote: false}); const inpBuildkitProxyNetwork = core.getBooleanInput('buildkit-proxy-network'); const inpMetaImages = core.getMultilineInput('meta-images'); @@ -918,27 +916,15 @@ jobs: } core.setOutput('secret-dir', buildSecrets.directory); - const envs = Object.assign({}, - inpVars ? inpVars.reduce((acc, curr) => { - const idx = curr.indexOf('='); - if (idx !== -1) { - acc[curr.substring(0, idx)] = curr.substring(idx + 1); - } - return acc; - }, {}) : {}, - { - BUILDKIT_MULTI_PLATFORM: '1' - } - ); - - // Git authentication is supplied directly to the Bake action. - delete envs.BUILDX_BAKE_GIT_AUTH_TOKEN; - - await core.group(`Set envs`, async () => { - core.info(JSON.stringify(Object.keys(envs).sort(), null, 2)); - core.setOutput('envs', JSON.stringify(envs)); + const bakeVars = BakeVars.resolve(inpVars); + await core.group(`Set bake vars`, async () => { + core.info(JSON.stringify(bakeVars.map(value => { + const idx = value.indexOf('='); + return idx === -1 ? '' : value.substring(0, idx); + }).sort(), null, 2)); + core.setOutput('vars', bakeVars.join(os.EOL)); }); - + let bakeFiles = inpFiles; await core.group(`Set bake files`, async () => { if (bakeFiles.length === 0) { @@ -1013,8 +999,11 @@ jobs: targets: ${{ steps.prepare.outputs.target }} sbom: ${{ steps.prepare.outputs.sbom }} set: ${{ steps.prepare.outputs.overrides }} + vars: ${{ steps.prepare.outputs.vars }} github-token: ${{ secrets.github-token || github.token }} - env: ${{ fromJson(steps.prepare.outputs.envs || '{}') }} + env: + BUILDKIT_MULTI_PLATFORM: '1' + BUILDX_BAKE_DISABLE_VARS_ENV_LOOKUP: '1' - name: Remove build secrets if: ${{ always() && steps.prepare.outputs.secret-dir != '' }} diff --git a/README.md b/README.md index 2d59c559..3efea5fb 100644 --- a/README.md +++ b/README.md @@ -375,6 +375,13 @@ jobs: | `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` | | `buildkit-proxy-network` | Bool | `false` | Enable BuildKit proxy network mode for default Dockerfile `RUN` networking. See [BuildKit proxy network](#buildkit-proxy-network). | +> [!NOTE] +> The `vars` input is passed to Buildx as explicit Bake variables. Ambient +> environment lookup for Bake variables is disabled. The `CI` environment variable +> and variables with `GITHUB_` or `RUNNER_` prefixes are forwarded as explicit vars +> for workflows that declare them in their Bake definition. Caller-provided vars +> take precedence over these forwarded values. + ### Secrets | Name | Default | Description | diff --git a/test/docker-bake.hcl b/test/docker-bake.hcl index adbbd19c..bb9d5ace 100644 --- a/test/docker-bake.hcl +++ b/test/docker-bake.hcl @@ -15,6 +15,22 @@ variable "XX_VERSION" { default = null } +variable "BUILDX_VERSION" { + default = "not-leaked" +} + +variable "CI" { + default = "" +} + +variable "GITHUB_SHA" { + default = "" +} + +variable "RUNNER_OS" { + default = "" +} + target "go" { inherits = ["docker-metadata-action"] args = { @@ -23,6 +39,17 @@ target "go" { dockerfile = "go.Dockerfile" } +target "vars" { + args = { + BUILDX_VERSION = BUILDX_VERSION + CI = CI + GITHUB_SHA = GITHUB_SHA + RUNNER_OS = RUNNER_OS + XX_VERSION = XX_VERSION + } + dockerfile = "vars.Dockerfile" +} + target "go-cross" { inherits = ["go"] platforms = ["linux/amd64", "linux/arm64"] diff --git a/test/vars.Dockerfile b/test/vars.Dockerfile new file mode 100644 index 00000000..83b172c4 --- /dev/null +++ b/test/vars.Dockerfile @@ -0,0 +1,17 @@ +# syntax=docker/dockerfile:1 + +FROM alpine +ARG BUILDX_VERSION +ARG CI +ARG GITHUB_SHA +ARG RUNNER_OS +ARG XX_VERSION +RUN test "$BUILDX_VERSION" = "not-leaked" +RUN test "$CI" = "true" +RUN test -n "$GITHUB_SHA" +RUN test -n "$RUNNER_OS" +RUN test "$XX_VERSION" = "1.9.0" +RUN mkdir -p /out && printf 'ok\n' > /out/vars.txt + +FROM scratch +COPY --from=0 /out /