Skip to content

Commit da6b4e6

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 7d2a024 commit da6b4e6

File tree

7 files changed

+131
-16
lines changed

7 files changed

+131
-16
lines changed

.github/workflows/.test-bake.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,3 +645,25 @@ jobs:
645645
- registry: ghcr.io
646646
username: ${{ github.actor }}
647647
password: ${{ secrets.GITHUB_TOKEN }}
648+
649+
bake-local-login:
650+
uses: ./.github/workflows/bake.yml
651+
if: ${{ github.event_name != 'pull_request' }}
652+
permissions:
653+
contents: read
654+
id-token: write
655+
with:
656+
artifact-name: bake-login-output
657+
artifact-upload: true
658+
context: test
659+
output: local
660+
registry-login: true
661+
sbom: true
662+
sign: true
663+
target: dhi
664+
secrets:
665+
registry-auths: |
666+
- registry: dhi.io
667+
username: ${{ vars.DOCKERPUBLICBOT_USERNAME }}
668+
password: ${{ secrets.DOCKERPUBLICBOT_READ_PAT }}
669+
scope: 'dhi.io@pull'

.github/workflows/.test-build.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,3 +664,24 @@ jobs:
664664
- registry: ghcr.io
665665
username: ${{ github.actor }}
666666
password: ${{ secrets.GITHUB_TOKEN }}
667+
668+
build-local-login:
669+
uses: ./.github/workflows/build.yml
670+
if: ${{ github.event_name != 'pull_request' }}
671+
permissions:
672+
contents: read
673+
id-token: write
674+
with:
675+
artifact-name: build-login-output
676+
artifact-upload: true
677+
file: test/dhi.Dockerfile
678+
output: local
679+
registry-login: true
680+
sbom: true
681+
sign: true
682+
secrets:
683+
registry-auths: |
684+
- registry: dhi.io
685+
username: ${{ vars.DOCKERPUBLICBOT_USERNAME }}
686+
password: ${{ secrets.DOCKERPUBLICBOT_READ_PAT }}
687+
scope: 'dhi.io@pull'

.github/workflows/bake.yml

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ on:
6565
description: "Push image to the registry (for image output)"
6666
required: false
6767
default: false
68+
registry-login:
69+
type: string
70+
description: "Login to registry before build (one of auto, true or false). Auto enables login only when output is image and push is true"
71+
required: false
72+
default: auto
6873
sbom:
6974
type: boolean
7075
description: "Generate SBOM attestation for the build"
@@ -125,7 +130,7 @@ on:
125130
required: false
126131
secrets:
127132
registry-auths:
128-
description: "Raw authentication to registries, defined as YAML objects (for image output)"
133+
description: "Raw authentication to registries, defined as YAML objects"
129134
required: false
130135
github-token:
131136
description: "GitHub Token used to authenticate against the repository for Git context"
@@ -173,6 +178,7 @@ jobs:
173178
metaImages: ${{ steps.set.outputs.metaImages }}
174179
sign: ${{ steps.set.outputs.sign }}
175180
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
181+
registryLogin: ${{ steps.set.outputs.registryLogin }}
176182
steps:
177183
-
178184
name: Install dependencies
@@ -260,6 +266,7 @@ jobs:
260266
INPUT_FILES: ${{ inputs.files }}
261267
INPUT_OUTPUT: ${{ inputs.output }}
262268
INPUT_PUSH: ${{ inputs.push }}
269+
INPUT_REGISTRY-LOGIN: ${{ inputs.registry-login }}
263270
INPUT_SBOM: ${{ inputs.sbom }}
264271
INPUT_SET: ${{ inputs.set }}
265272
INPUT_SIGN: ${{ inputs.sign }}
@@ -287,6 +294,7 @@ jobs:
287294
const inpFiles = Util.getInputList('files');
288295
const inpOutput = core.getInput('output');
289296
const inpPush = core.getBooleanInput('push');
297+
const inpRegistryLogin = core.getInput('registry-login');
290298
const inpSbom = core.getBooleanInput('sbom');
291299
const inpSet = Util.getInputList('set', {ignoreComma: true, quote: false});
292300
const inpSign = core.getInput('sign');
@@ -317,12 +325,18 @@ jobs:
317325
core.setFailed(`signing attestation manifests requires push to be enabled`);
318326
return;
319327
}
320-
328+
321329
const bakeSource = await new Build().gitContext({subdir: inpContext});
322330
await core.group(`Set bake source`, async () => {
323331
core.info(bakeSource);
324332
});
325333
334+
if (!['auto', 'true', 'false'].includes(inpRegistryLogin)) {
335+
core.setFailed(`Invalid registry-login input: ${inpRegistryLogin}`);
336+
return;
337+
}
338+
const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true';
339+
326340
const envs = Object.assign({},
327341
inpVars ? inpVars.reduce((acc, curr) => {
328342
const idx = curr.indexOf('=');
@@ -339,13 +353,13 @@ jobs:
339353
await core.group(`Set envs`, async () => {
340354
core.info(JSON.stringify(envs, null, 2));
341355
});
342-
356+
343357
const metaImages = inpMetaImages.map(image => image.toLowerCase());
344358
await core.group(`Set metaImages output`, async () => {
345359
core.info(JSON.stringify(metaImages, null, 2));
346360
core.setOutput('metaImages', metaImages.join('\n'));
347361
});
348-
362+
349363
let def;
350364
let target;
351365
try {
@@ -414,7 +428,7 @@ jobs:
414428
core.setFailed(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`);
415429
return;
416430
}
417-
431+
418432
const privateRepo = GitHub.context.payload.repository?.private ?? false;
419433
await core.group(`Set privateRepo output`, async () => {
420434
core.info(`privateRepo: ${privateRepo}`);
@@ -449,6 +463,10 @@ jobs:
449463
core.info(`ghaCacheSign: ${ghaCacheSign}`);
450464
core.setOutput('ghaCacheSign', ghaCacheSign);
451465
});
466+
await core.group(`Set registryLogin output`, async () => {
467+
core.info(`registryLogin: ${registryLogin}`);
468+
core.setOutput('registryLogin', registryLogin);
469+
});
452470
453471
build:
454472
runs-on: ${{ matrix.runner }}
@@ -791,7 +809,7 @@ jobs:
791809
});
792810
-
793811
name: Login to registry
794-
if: ${{ inputs.push && inputs.output == 'image' }}
812+
if: ${{ needs.prepare.outputs.registryLogin == 'true' }}
795813
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
796814
with:
797815
registry-auth: ${{ secrets.registry-auths }}

.github/workflows/build.yml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ on:
8181
description: "Push image to the registry (for image output)"
8282
required: false
8383
default: false
84+
registry-login:
85+
type: string
86+
description: "Login to registry before build (one of auto, true or false). Auto enables login only when output is image and push is true"
87+
required: false
88+
default: auto
8489
sbom:
8590
type: boolean
8691
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"
@@ -177,6 +182,7 @@ jobs:
177182
sign: ${{ steps.set.outputs.sign }}
178183
privateRepo: ${{ steps.set.outputs.privateRepo }}
179184
ghaCacheSign: ${{ steps.set.outputs.ghaCacheSign }}
185+
registryLogin: ${{ steps.set.outputs.registryLogin }}
180186
steps:
181187
-
182188
name: Install dependencies
@@ -254,6 +260,7 @@ jobs:
254260
INPUT_OUTPUT: ${{ inputs.output }}
255261
INPUT_PLATFORMS: ${{ inputs.platforms }}
256262
INPUT_PUSH: ${{ inputs.push }}
263+
INPUT_REGISTRY-LOGIN: ${{ inputs.registry-login }}
257264
INPUT_SIGN: ${{ inputs.sign }}
258265
with:
259266
script: |
@@ -270,6 +277,7 @@ jobs:
270277
const inpPlatforms = Util.getInputList('platforms');
271278
const inpOutput = core.getInput('output');
272279
const inpPush = core.getBooleanInput('push');
280+
const inpRegistryLogin = core.getInput('registry-login');
273281
const inpSign = core.getInput('sign');
274282
275283
let runner = inpRunner;
@@ -297,6 +305,12 @@ jobs:
297305
return;
298306
}
299307
308+
if (!['auto', 'true', 'false'].includes(inpRegistryLogin)) {
309+
core.setFailed(`Invalid registry-login input: ${inpRegistryLogin}`);
310+
return;
311+
}
312+
const registryLogin = inpRegistryLogin === 'auto' ? inpOutput === 'image' && inpPush : inpRegistryLogin === 'true';
313+
300314
if (inpDistribute && inpPlatforms.length > inpMatrixSizeLimit) {
301315
core.setFailed(`Platforms to build exceed matrix size limit of ${inpMatrixSizeLimit}`);
302316
return;
@@ -342,6 +356,10 @@ jobs:
342356
core.info(`ghaCacheSign: ${ghaCacheSign}`);
343357
core.setOutput('ghaCacheSign', ghaCacheSign);
344358
});
359+
await core.group(`Set registryLogin output`, async () => {
360+
core.info(`registryLogin: ${registryLogin}`);
361+
core.setOutput('registryLogin', registryLogin);
362+
});
345363
346364
build:
347365
runs-on: ${{ matrix.runner }}
@@ -649,7 +667,7 @@ jobs:
649667
}
650668
-
651669
name: Login to registry
652-
if: ${{ inputs.push && inputs.output == 'image' }}
670+
if: ${{ needs.prepare.outputs.registryLogin == 'true' }}
653671
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
654672
with:
655673
registry-auth: ${{ secrets.registry-auths }}

README.md

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ jobs:
239239
| `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 |
240240
| `platforms` | List/CSV | | List of [target platforms](https://docs.docker.com/engine/reference/commandline/buildx_build/#platform) to build |
241241
| `push` | Bool | `false` | [Push](https://docs.docker.com/engine/reference/commandline/buildx_build/#push) image to the registry (for `image` output) |
242+
| `registry-login` | String | `auto` | Login to registry before build (one of `auto`, `true` or `false`). `auto` enables login only when output is `image` and push is `true` |
242243
| `sbom` | Bool | `false` | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build |
243244
| `shm-size` | String | | Size of [`/dev/shm`](https://docs.docker.com/engine/reference/commandline/buildx_build/#shm-size) (e.g., `2g`) |
244245
| `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 |
@@ -250,6 +251,16 @@ jobs:
250251
| `meta-tags` | List | | [List of tags](https://github.com/docker/metadata-action?tab=readme-ov-file#tags-input) as key-value pair attributes |
251252
| `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` |
252253

254+
> [!NOTE]
255+
> `registry-login: true` forces a pre-build login attempt and will fail if the
256+
> resolved credentials are empty, for example, on forked pull requests where
257+
> secrets are not exposed. Gate this input at the caller side if you need
258+
> fork-safe behavior:
259+
>
260+
> ```yaml
261+
> registry-login: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
262+
> ```
263+
253264
> [!TIP]
254265
> When `output=image`, following inputs support Handlebars templates rendered
255266
> from selected `docker/metadata-action` outputs:
@@ -275,10 +286,10 @@ jobs:
275286

276287
#### Secrets
277288

278-
| Name | Default | Description |
279-
|------------------|-----------------------|--------------------------------------------------------------------------------|
280-
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (for `image` output) |
281-
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
289+
| Name | Default | Description |
290+
|------------------|-----------------------|----------------------------------------------------------------------------------------------------------------|
291+
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (used for push/signing and optional pre-build login) |
292+
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
282293

283294
#### Outputs
284295

@@ -384,6 +395,7 @@ jobs:
384395
| `files` | List | `{context}/docker-bake.hcl` | List of bake definition files |
385396
| `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/)). |
386397
| `push` | Bool | `false` | Push image to the registry (for `image` output) |
398+
| `registry-login` | String | `auto` | Login to registry before build (one of `auto`, `true` or `false`). `auto` enables login only when output is `image` and push is `true` |
387399
| `sbom` | Bool | `false` | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build |
388400
| `set` | List | | List of [target values to override](https://docs.docker.com/engine/reference/commandline/buildx_bake/#set) (e.g., `targetpattern.key=value`) |
389401
| `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 |
@@ -397,6 +409,16 @@ jobs:
397409
| `meta-annotations` | List | | [List of custom annotations](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) |
398410
| `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` |
399411

412+
> [!NOTE]
413+
> `registry-login: true` forces a pre-build login attempt and will fail if the
414+
> resolved credentials are empty, for example, on forked pull requests where
415+
> secrets are not exposed. Gate this input at the caller side if you need
416+
> fork-safe behavior:
417+
>
418+
> ```yaml
419+
> registry-login: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
420+
> ```
421+
400422
> [!TIP]
401423
> When `output=image`, the `set` input supports Handlebars templates rendered
402424
> from selected `docker/metadata-action` outputs.
@@ -419,10 +441,10 @@ jobs:
419441

420442
#### Secrets
421443

422-
| Name | Default | Description |
423-
|------------------|-----------------------|--------------------------------------------------------------------------------|
424-
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (for `image` output) |
425-
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
444+
| Name | Default | Description |
445+
|------------------|-----------------------|----------------------------------------------------------------------------------------------------------------|
446+
| `registry-auths` | | Raw authentication to registries, defined as YAML objects (used for push/signing and optional pre-build login) |
447+
| `github-token` | `${{ github.token }}` | GitHub Token used to authenticate against the repository for Git context |
426448

427449
#### Outputs
428450

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 /

0 commit comments

Comments
 (0)