Skip to content

Commit 798e59b

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 17bd7d6 commit 798e59b

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"
@@ -185,6 +190,7 @@ jobs:
185190
metaImages: ${{ steps.set.outputs.metaImages }}
186191
sign: ${{ steps.set.outputs.sign }}
187192
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
193+
registryLogin: ${{ steps.set.outputs.registryLogin }}
188194
steps:
189195
-
190196
name: Install dependencies
@@ -283,6 +289,7 @@ jobs:
283289
INPUT_FILES: ${{ inputs.files }}
284290
INPUT_OUTPUT: ${{ inputs.output }}
285291
INPUT_PUSH: ${{ inputs.push }}
292+
INPUT_REGISTRY-LOGIN: ${{ inputs.registry-login }}
286293
INPUT_SBOM: ${{ inputs.sbom }}
287294
INPUT_SET: ${{ inputs.set }}
288295
INPUT_SIGN: ${{ inputs.sign }}
@@ -310,6 +317,7 @@ jobs:
310317
const inpFiles = Util.getInputList('files');
311318
const inpOutput = core.getInput('output');
312319
const inpPush = core.getBooleanInput('push');
320+
const inpRegistryLogin = core.getInput('registry-login');
313321
const inpSbom = core.getBooleanInput('sbom');
314322
const inpSet = Util.getInputList('set', {ignoreComma: true, quote: false});
315323
const inpSign = core.getInput('sign');
@@ -439,7 +447,13 @@ jobs:
439447
await core.group(`Set bake source`, async () => {
440448
core.info(bakeSource);
441449
});
442-
450+
451+
if (!['auto', 'true', 'false'].includes(inpRegistryLogin)) {
452+
core.setFailed(`Invalid registry-login input: ${inpRegistryLogin}`);
453+
return;
454+
}
455+
const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true';
456+
443457
const envs = Object.assign({},
444458
inpVars ? inpVars.reduce((acc, curr) => {
445459
const idx = curr.indexOf('=');
@@ -525,7 +539,7 @@ jobs:
525539
core.setFailed(error);
526540
return;
527541
}
528-
542+
529543
const platforms = def.target[target].platforms || [];
530544
if (inpDistribute && platforms.length > inpMatrixSizeLimit) {
531545
core.setFailed(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`);
@@ -566,6 +580,10 @@ jobs:
566580
core.info(`ghaCacheSign: ${ghaCacheSign}`);
567581
core.setOutput('ghaCacheSign', ghaCacheSign);
568582
});
583+
await core.group(`Set registryLogin output`, async () => {
584+
core.info(`registryLogin: ${registryLogin}`);
585+
core.setOutput('registryLogin', registryLogin);
586+
});
569587
570588
build:
571589
runs-on: ${{ matrix.runner }}
@@ -954,7 +972,7 @@ jobs:
954972
});
955973
-
956974
name: Login to registry
957-
if: ${{ inputs.push && inputs.output == 'image' }}
975+
if: ${{ needs.prepare.outputs.registryLogin == 'true' }}
958976
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
959977
with:
960978
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"
@@ -189,6 +194,7 @@ jobs:
189194
sign: ${{ steps.set.outputs.sign }}
190195
privateRepo: ${{ steps.set.outputs.privateRepo }}
191196
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
197+
registryLogin: ${{ steps.set.outputs.registryLogin }}
192198
steps:
193199
-
194200
name: Install dependencies
@@ -277,6 +283,7 @@ jobs:
277283
INPUT_OUTPUT: ${{ inputs.output }}
278284
INPUT_PLATFORMS: ${{ inputs.platforms }}
279285
INPUT_PUSH: ${{ inputs.push }}
286+
INPUT_REGISTRY-LOGIN: ${{ inputs.registry-login }}
280287
INPUT_SIGN: ${{ inputs.sign }}
281288
with:
282289
script: |
@@ -293,6 +300,7 @@ jobs:
293300
const inpPlatforms = Util.getInputList('platforms');
294301
const inpOutput = core.getInput('output');
295302
const inpPush = core.getBooleanInput('push');
303+
const inpRegistryLogin = core.getInput('registry-login');
296304
const inpSign = core.getInput('sign');
297305
298306
const parseRunnerConfig = value => {
@@ -412,7 +420,13 @@ jobs:
412420
core.setFailed(`signing attestation manifests requires push to be enabled`);
413421
return;
414422
}
415-
423+
424+
if (!['auto', 'true', 'false'].includes(inpRegistryLogin)) {
425+
core.setFailed(`Invalid registry-login input: ${inpRegistryLogin}`);
426+
return;
427+
}
428+
const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true';
429+
416430
if (inpDistribute && inpPlatforms.length > inpMatrixSizeLimit) {
417431
core.setFailed(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`);
418432
return;
@@ -458,6 +472,10 @@ jobs:
458472
core.info(`ghaCacheSign: ${ghaCacheSign}`);
459473
core.setOutput('ghaCacheSign', ghaCacheSign);
460474
});
475+
await core.group(`Set registryLogin output`, async () => {
476+
core.info(`registryLogin: ${registryLogin}`);
477+
core.setOutput('registryLogin', registryLogin);
478+
});
461479
462480
build:
463481
runs-on: ${{ matrix.runner }}
@@ -812,7 +830,7 @@ jobs:
812830
}
813831
-
814832
name: Login to registry
815-
if: ${{ inputs.push && inputs.output == 'image' }}
833+
if: ${{ needs.prepare.outputs.registryLogin == 'true' }}
816834
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
817835
with:
818836
registry-auth: ${{ secrets.registry-auths }}

‎README.md‎

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ___
1919
* [Notes](#notes)
2020
* [Signed GitHub Actions cache](#signed-github-actions-cache)
2121
* [Runner mapping](#runner-mapping)
22+
* [Registry login](#registry-login)
2223
* [Metadata templates](#metadata-templates)
2324

2425
## Overview
@@ -233,6 +234,7 @@ jobs:
233234
| `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 |
234235
| `platforms` | List/CSV | | List of [target platforms](https://docs.docker.com/engine/reference/commandline/buildx_build/#platform) to build |
235236
| `push` | Bool | `false` | [Push](https://docs.docker.com/engine/reference/commandline/buildx_build/#push) image to the registry (for `image` output) |
237+
| `registry-login` | String | `auto` | [Login to registry](#registry-login) before build (one of `auto`, `true` or `false`) |
236238
| `sbom` | Bool | `false` | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build |
237239
| `shm-size` | String | | Size of [`/dev/shm`](https://docs.docker.com/engine/reference/commandline/buildx_build/#shm-size) (e.g., `2g`) |
238240
| `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 |
@@ -246,10 +248,10 @@ jobs:
246248

247249
### Secrets
248250

249-
| Name | Default | Description |
250-
|------------------|-----------------------|--------------------------------------------------------------------------------|
251-
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (for `image` output) |
252-
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
251+
| Name | Default | Description |
252+
|------------------|-----------------------|--------------------------------------------------------------------------|
253+
| `registry-auths` | | Raw authentication to registries, defined as YAML objects |
254+
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
253255

254256
### Outputs
255257

@@ -338,8 +340,9 @@ jobs:
338340
| `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 |
339341
| `context` | String | `.` | Context to build from in the Git working tree |
340342
| `files` | List | `{context}/docker-bake.hcl` | List of bake definition files |
341-
| `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/)). |
343+
| `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/)) |
342344
| `push` | Bool | `false` | Push image to the registry (for `image` output) |
345+
| `registry-login` | String | `auto` | [Login to registry](#registry-login) before build (one of `auto`, `true` or `false`) |
343346
| `sbom` | Bool | `false` | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build |
344347
| `set` | List | | List of [target values to override](https://docs.docker.com/engine/reference/commandline/buildx_bake/#set) (e.g., `targetpattern.key=value`) |
345348
| `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 |
@@ -355,10 +358,10 @@ jobs:
355358

356359
### Secrets
357360

358-
| Name | Default | Description |
359-
|------------------|-----------------------|--------------------------------------------------------------------------------|
360-
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (for `image` output) |
361-
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
361+
| Name | Default | Description |
362+
|------------------|-----------------------|--------------------------------------------------------------------------|
363+
| `registry-auths` | | Raw authentication to registries, defined as YAML objects |
364+
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
362365

363366
### Outputs
364367

@@ -422,6 +425,21 @@ runner: |
422425
For example, `linux` matches all Linux platforms, `linux/arm` matches variants
423426
such as `linux/arm/v7`, and `linux/arm64` is separate from `linux/arm`.
424427

428+
### Registry login
429+
430+
The `registry-login` input controls whether the workflows run a registry login
431+
before the build step. `auto` preserves the existing behavior and enables login
432+
only when `output=image` and `push=true`.
433+
434+
When `registry-login=true`, the workflow always attempts pre-build login. If
435+
credentials resolve to empty values, for example on forked pull requests where
436+
secrets are not exposed, login fails. Gate the input at the caller side for
437+
fork-safe workflows:
438+
439+
```yaml
440+
registry-login: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
441+
```
442+
425443
### Metadata templates
426444

427445
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)