Skip to content

Commit c2bfaf8

Browse files
committed
add registry-login input for optional registry auth before build
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent c2782c5 commit c2bfaf8

7 files changed

Lines changed: 127 additions & 16 deletions

File tree

.github/workflows/.test-bake.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,25 @@ jobs:
667667
- registry: ghcr.io
668668
username: ${{ github.actor }}
669669
password: ${{ secrets.GITHUB_TOKEN }}
670+
671+
bake-local-login:
672+
uses: ./.github/workflows/bake.yml
673+
if: ${{ github.event_name != 'pull_request' }}
674+
permissions:
675+
contents: read
676+
id-token: write
677+
with:
678+
artifact-name: bake-login-output
679+
artifact-upload: true
680+
context: test
681+
output: local
682+
registry-login: true
683+
sbom: true
684+
sign: true
685+
target: dhi
686+
secrets:
687+
registry-auths: |
688+
- registry: dhi.io
689+
username: ${{ vars.DOCKERPUBLICBOT_USERNAME }}
690+
password: ${{ secrets.DOCKERPUBLICBOT_READ_PAT }}
691+
scope: 'dhi.io@pull'

.github/workflows/.test-build.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,3 +685,24 @@ jobs:
685685
- registry: ghcr.io
686686
username: ${{ github.actor }}
687687
password: ${{ secrets.GITHUB_TOKEN }}
688+
689+
build-local-login:
690+
uses: ./.github/workflows/build.yml
691+
if: ${{ github.event_name != 'pull_request' }}
692+
permissions:
693+
contents: read
694+
id-token: write
695+
with:
696+
artifact-name: build-login-output
697+
artifact-upload: true
698+
file: test/dhi.Dockerfile
699+
output: local
700+
registry-login: true
701+
sbom: true
702+
sign: true
703+
secrets:
704+
registry-auths: |
705+
- registry: dhi.io
706+
username: ${{ vars.DOCKERPUBLICBOT_USERNAME }}
707+
password: ${{ secrets.DOCKERPUBLICBOT_READ_PAT }}
708+
scope: 'dhi.io@pull'

.github/workflows/bake.yml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ on:
6868
description: "Push image to the registry (for image output)"
6969
required: false
7070
default: false
71+
registry-login:
72+
type: string
73+
description: "Login to registry before build (one of auto, true or false). Auto enables login only when output is image and push is true"
74+
required: false
75+
default: auto
7176
sbom:
7277
type: boolean
7378
description: "Generate SBOM attestation for the build"
@@ -128,7 +133,7 @@ on:
128133
required: false
129134
secrets:
130135
registry-auths:
131-
description: "Raw authentication to registries, defined as YAML objects (for image output)"
136+
description: "Raw authentication to registries, defined as YAML objects"
132137
required: false
133138
github-token:
134139
description: "GitHub Token used to authenticate against the repository for Git context"
@@ -176,6 +181,7 @@ jobs:
176181
metaImages: ${{ steps.set.outputs.metaImages }}
177182
sign: ${{ steps.set.outputs.sign }}
178183
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
184+
registryLogin: ${{ steps.set.outputs.registryLogin }}
179185
steps:
180186
-
181187
name: Install dependencies
@@ -263,6 +269,7 @@ jobs:
263269
INPUT_FILES: ${{ inputs.files }}
264270
INPUT_OUTPUT: ${{ inputs.output }}
265271
INPUT_PUSH: ${{ inputs.push }}
272+
INPUT_REGISTRY-LOGIN: ${{ inputs.registry-login }}
266273
INPUT_SBOM: ${{ inputs.sbom }}
267274
INPUT_SET: ${{ inputs.set }}
268275
INPUT_SIGN: ${{ inputs.sign }}
@@ -290,6 +297,7 @@ jobs:
290297
const inpFiles = Util.getInputList('files');
291298
const inpOutput = core.getInput('output');
292299
const inpPush = core.getBooleanInput('push');
300+
const inpRegistryLogin = core.getInput('registry-login');
293301
const inpSbom = core.getBooleanInput('sbom');
294302
const inpSet = Util.getInputList('set', {ignoreComma: true, quote: false});
295303
const inpSign = core.getInput('sign');
@@ -418,7 +426,13 @@ jobs:
418426
await core.group(`Set bake source`, async () => {
419427
core.info(bakeSource);
420428
});
421-
429+
430+
if (!['auto', 'true', 'false'].includes(inpRegistryLogin)) {
431+
core.setFailed(`Invalid registry-login input: ${inpRegistryLogin}`);
432+
return;
433+
}
434+
const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true';
435+
422436
const envs = Object.assign({},
423437
inpVars ? inpVars.reduce((acc, curr) => {
424438
const idx = curr.indexOf('=');
@@ -504,7 +518,7 @@ jobs:
504518
core.setFailed(error);
505519
return;
506520
}
507-
521+
508522
const platforms = def.target[target].platforms || [];
509523
if (inpDistribute && platforms.length > inpMatrixSizeLimit) {
510524
core.setFailed(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`);
@@ -545,6 +559,10 @@ jobs:
545559
core.info(`ghaCacheSign: ${ghaCacheSign}`);
546560
core.setOutput('ghaCacheSign', ghaCacheSign);
547561
});
562+
await core.group(`Set registryLogin output`, async () => {
563+
core.info(`registryLogin: ${registryLogin}`);
564+
core.setOutput('registryLogin', registryLogin);
565+
});
548566
549567
build:
550568
runs-on: ${{ matrix.runner }}
@@ -909,7 +927,7 @@ jobs:
909927
});
910928
-
911929
name: Login to registry
912-
if: ${{ inputs.push && inputs.output == 'image' }}
930+
if: ${{ needs.prepare.outputs.registryLogin == 'true' }}
913931
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
914932
with:
915933
registry-auth: ${{ secrets.registry-auths }}

.github/workflows/build.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ on:
8484
description: "Push image to the registry (for image output)"
8585
required: false
8686
default: false
87+
registry-login:
88+
type: string
89+
description: "Login to registry before build (one of auto, true or false). Auto enables login only when output is image and push is true"
90+
required: false
91+
default: auto
8792
sbom:
8893
type: boolean
8994
description: "Generate SBOM attestation for the build"
@@ -131,7 +136,7 @@ on:
131136
required: false
132137
secrets:
133138
registry-auths:
134-
description: "Raw authentication to registries, defined as YAML objects (for image output)"
139+
description: "Raw authentication to registries, defined as YAML objects"
135140
required: false
136141
github-token:
137142
description: "GitHub Token used to authenticate against the repository for Git context"
@@ -180,6 +185,7 @@ jobs:
180185
sign: ${{ steps.set.outputs.sign }}
181186
privateRepo: ${{ steps.set.outputs.privateRepo }}
182187
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
188+
registryLogin: ${{ steps.set.outputs.registryLogin }}
183189
steps:
184190
-
185191
name: Install dependencies
@@ -257,6 +263,7 @@ jobs:
257263
INPUT_OUTPUT: ${{ inputs.output }}
258264
INPUT_PLATFORMS: ${{ inputs.platforms }}
259265
INPUT_PUSH: ${{ inputs.push }}
266+
INPUT_REGISTRY-LOGIN: ${{ inputs.registry-login }}
260267
INPUT_SIGN: ${{ inputs.sign }}
261268
with:
262269
script: |
@@ -273,6 +280,7 @@ jobs:
273280
const inpPlatforms = Util.getInputList('platforms');
274281
const inpOutput = core.getInput('output');
275282
const inpPush = core.getBooleanInput('push');
283+
const inpRegistryLogin = core.getInput('registry-login');
276284
const inpSign = core.getInput('sign');
277285
278286
const parseRunnerConfig = value => {
@@ -392,7 +400,13 @@ jobs:
392400
core.setFailed(`signing attestation manifests requires push to be enabled`);
393401
return;
394402
}
395-
403+
404+
if (!['auto', 'true', 'false'].includes(inpRegistryLogin)) {
405+
core.setFailed(`Invalid registry-login input: ${inpRegistryLogin}`);
406+
return;
407+
}
408+
const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true';
409+
396410
if (inpDistribute && inpPlatforms.length > inpMatrixSizeLimit) {
397411
core.setFailed(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`);
398412
return;
@@ -438,6 +452,10 @@ jobs:
438452
core.info(`ghaCacheSign: ${ghaCacheSign}`);
439453
core.setOutput('ghaCacheSign', ghaCacheSign);
440454
});
455+
await core.group(`Set registryLogin output`, async () => {
456+
core.info(`registryLogin: ${registryLogin}`);
457+
core.setOutput('registryLogin', registryLogin);
458+
});
441459
442460
build:
443461
runs-on: ${{ matrix.runner }}
@@ -768,7 +786,7 @@ jobs:
768786
}
769787
-
770788
name: Login to registry
771-
if: ${{ inputs.push && inputs.output == 'image' }}
789+
if: ${{ needs.prepare.outputs.registryLogin == 'true' }}
772790
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
773791
with:
774792
registry-auth: ${{ secrets.registry-auths }}

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ ___
1818
* [Outputs](#outputs-1)
1919
* [Notes](#notes)
2020
* [Runner mapping](#runner-mapping)
21+
* [Registry login](#registry-login)
2122
* [Metadata templates](#metadata-templates)
2223

2324
## Overview
@@ -223,6 +224,7 @@ jobs:
223224
| `output` | String | | Build output destination (one of [`image`](https://docs.docker.com/build/exporters/image-registry/) or [`local`](https://docs.docker.com/build/exporters/local-tar/)). Unlike the `build-push-action`, it only accepts `image` or `local`. The reusable workflow takes care of setting the `outputs` attribute |
224225
| `platforms` | List/CSV | | List of [target platforms](https://docs.docker.com/engine/reference/commandline/buildx_build/#platform) to build |
225226
| `push` | Bool | `false` | [Push](https://docs.docker.com/engine/reference/commandline/buildx_build/#push) image to the registry (for `image` output) |
227+
| `registry-login` | String | `auto` | [Login to registry](#registry-login) before build (one of `auto`, `true` or `false`) |
226228
| `sbom` | Bool | `false` | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build |
227229
| `shm-size` | String | | Size of [`/dev/shm`](https://docs.docker.com/engine/reference/commandline/buildx_build/#shm-size) (e.g., `2g`) |
228230
| `sign` | String | `auto` | Sign attestation manifest for `image` output or artifacts for `local` output, can be one of `auto`, `true` or `false`. The `auto` mode will enable signing if `push` is enabled for pushing the `image` or if `artifact-upload` is enabled for uploading the `local` build output as GitHub Artifact |
@@ -236,10 +238,10 @@ jobs:
236238

237239
### Secrets
238240

239-
| Name | Default | Description |
240-
|------------------|-----------------------|--------------------------------------------------------------------------------|
241-
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (for `image` output) |
242-
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
241+
| Name | Default | Description |
242+
|------------------|-----------------------|----------------------------------------------------------------------------------------------------------------|
243+
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (used for push/signing and optional pre-build login) |
244+
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
243245

244246
### Outputs
245247

@@ -328,8 +330,9 @@ jobs:
328330
| `cache-mode` | String | `min` | [Cache layers to export](https://docs.docker.com/build/cache/backends/#cache-mode) if cache enabled (`min` or `max`). In `min` cache mode, only layers that are exported into the resulting image are cached, while in `max` cache mode, all layers are cached, even those of intermediate steps |
329331
| `context` | String | `.` | Context to build from in the Git working tree |
330332
| `files` | List | `{context}/docker-bake.hcl` | List of bake definition files |
331-
| `output` | String | | Build output destination (one of [`image`](https://docs.docker.com/build/exporters/image-registry/) or [`local`](https://docs.docker.com/build/exporters/local-tar/)). |
333+
| `output` | String | | Build output destination (one of [`image`](https://docs.docker.com/build/exporters/image-registry/) or [`local`](https://docs.docker.com/build/exporters/local-tar/)) |
332334
| `push` | Bool | `false` | Push image to the registry (for `image` output) |
335+
| `registry-login` | String | `auto` | [Login to registry](#registry-login) before build (one of `auto`, `true` or `false`) |
333336
| `sbom` | Bool | `false` | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build |
334337
| `set` | List | | List of [target values to override](https://docs.docker.com/engine/reference/commandline/buildx_bake/#set) (e.g., `targetpattern.key=value`) |
335338
| `sign` | String | `auto` | Sign attestation manifest for `image` output or artifacts for `local` output, can be one of `auto`, `true` or `false`. The `auto` mode will enable signing if `push` is enabled for pushing the `image` or if `artifact-upload` is enabled for uploading the `local` build output as GitHub Artifact |
@@ -345,10 +348,10 @@ jobs:
345348

346349
### Secrets
347350

348-
| Name | Default | Description |
349-
|------------------|-----------------------|--------------------------------------------------------------------------------|
350-
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (for `image` output) |
351-
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
351+
| Name | Default | Description |
352+
|------------------|-----------------------|----------------------------------------------------------------------------------------------------------------|
353+
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (used for push/signing and optional pre-build login) |
354+
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
352355

353356
### Outputs
354357

@@ -399,6 +402,21 @@ runner: |
399402
For example, `linux` matches all Linux platforms, `linux/arm` matches variants
400403
such as `linux/arm/v7`, and `linux/arm64` is separate from `linux/arm`.
401404

405+
### Registry login
406+
407+
The `registry-login` input controls whether the workflows run a registry login
408+
before the build step. `auto` preserves the existing behavior and enables login
409+
only when `output=image` and `push=true`.
410+
411+
When `registry-login=true`, the workflow always attempts pre-build login. If
412+
credentials resolve to empty values, for example on forked pull requests where
413+
secrets are not exposed, login fails. Gate the input at the caller side for
414+
fork-safe workflows:
415+
416+
```yaml
417+
registry-login: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
418+
```
419+
402420
### Metadata templates
403421

404422
When `output=image`, some inputs support Handlebars templates rendered from

test/dhi.Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# syntax=docker/dockerfile:1
2+
3+
FROM dhi.io/alpine-base:3.23 AS base
4+
ARG TARGETPLATFORM
5+
RUN echo "Hello, World! This is ${TARGETPLATFORM}" > /tmp/hello.txt
6+
ARG BUILDKIT_SBOM_SCAN_STAGE=true
7+
8+
FROM scratch
9+
COPY --from=base /tmp/hello.txt /

test/docker-bake.hcl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,8 @@ target "generated-hello2" {
6767
dockerfile = "hello.Dockerfile"
6868
output = ["type=cacheonly"]
6969
}
70+
71+
target "dhi" {
72+
inherits = ["docker-metadata-action"]
73+
dockerfile = "dhi.Dockerfile"
74+
}

0 commit comments

Comments
 (0)