Skip to content

Commit 86740f4

Browse files
Copilotneilime
andcommitted
fix: harden docker build-image config script
Co-authored-by: neilime <314088+neilime@users.noreply.github.com> Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
1 parent a129c63 commit 86740f4

File tree

6 files changed

+168
-48
lines changed

6 files changed

+168
-48
lines changed

.github/workflows/docker-build-images.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ on: # yamllint disable-line rule:truthy
3232
description: |
3333
Username configuration used to log against OCI registries.
3434
Accepts either a single username string (default format) or a JSON object using the same keys as `oci-registry`.
35-
JSON example: `{"pull:private":"my-user","push":"my-user"}`
35+
JSON example: `{"pull:private":"$\{{ github.repository_owner }}","push":"$\{{ github.repository_owner }}"}`
3636
See https://github.com/docker/login-action#usage.
3737
type: string
3838
default: ${{ github.repository_owner }}
@@ -116,7 +116,7 @@ on: # yamllint disable-line rule:truthy
116116
description: |
117117
Password or GitHub token (`packages:read` and `packages:write` scopes) configuration used to log against OCI registries.
118118
Accepts either a single password/token string (default format) or a JSON object using the same keys as `oci-registry`.
119-
JSON example: `{"pull:private":"my-token","push":"my-token"}`
119+
JSON example: `{"pull:private":"$\{{ github.token }}","push":"$\{{ github.token }}"}`
120120
See https://github.com/docker/login-action#usage.
121121
required: true
122122
build-secrets:

actions/docker/build-image/action.yml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ inputs:
2828
description: |
2929
Username configuration used to log against OCI registries.
3030
Accepts either a single username string (default format) or a JSON object using the same keys as `oci-registry`.
31-
JSON example: `{"pull:private":"${{ github.repository_owner }}","push":"${{ github.repository_owner }}"}`
31+
JSON example:
32+
`{"pull:private":"$\{{ github.repository_owner }}","push":"$\{{ github.repository_owner }}"}`
3233
See https://github.com/docker/login-action#usage.
3334
default: ${{ github.repository_owner }}
3435
required: true
3536
oci-registry-password:
3637
description: |
3738
Password or personal access token configuration used to log against OCI registries.
3839
Accepts either a single password/token string (default format) or a JSON object using the same keys as `oci-registry`.
39-
JSON example: `{"pull:private":"${{ github.token }}","push":"${{ github.token }}"}`
40+
JSON example: `{"pull:private":"$\{{ github.token }}","push":"$\{{ github.token }}"}`
4041
Can be passed in using `secrets.GITHUB_TOKEN`.
4142
See https://github.com/docker/login-action#usage.
4243
default: ${{ github.token }}
@@ -168,15 +169,24 @@ runs:
168169
169170
- id: get-docker-config
170171
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
172+
env:
173+
CACHE_REGISTRY: ${{ steps.docker-setup.outputs.cache-registry }}
174+
CACHE_TYPE_INPUT: ${{ inputs.cache-type }}
175+
CONTEXT_INPUT: ${{ inputs.context }}
176+
DOCKERFILE_INPUT: ${{ inputs.dockerfile }}
177+
METADATA_IMAGE: ${{ steps.metadata.outputs.image }}
178+
MULTI_PLATFORM_INPUT: ${{ inputs.multi-platform }}
179+
PLATFORM_INPUT: ${{ inputs.platform }}
180+
SLUGIFIED_PLATFORM: ${{ steps.slugify-platform.outputs.result }}
171181
with:
172182
script: |
173183
const fs = require('fs');
174184
const path = require('path');
175185
176186
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
177-
const rawContext = `${{ inputs.context }}`.trim();
187+
const rawContext = (process.env.CONTEXT_INPUT || '').trim();
178188
const contextPath = rawContext.length > 0 ? rawContext : '.';
179-
const rawDockerfile = `${{ inputs.dockerfile }}`.trim();
189+
const rawDockerfile = (process.env.DOCKERFILE_INPUT || '').trim();
180190
const dockerfileName = rawDockerfile.length > 0 ? rawDockerfile : 'Dockerfile';
181191
182192
const dockerfilePath = path.resolve(workspace, contextPath, dockerfileName);
@@ -188,13 +198,16 @@ runs:
188198
const resolvedDockerfilePath = fs.realpathSync(dockerfilePath);
189199
core.setOutput('dockerfile-path', resolvedDockerfilePath);
190200
191-
const slugifiedPlatform = `${{ steps.slugify-platform.outputs.result }}`;
201+
const slugifiedPlatform = process.env.SLUGIFIED_PLATFORM || '';
192202
const tagSuffix = `-${slugifiedPlatform}`;
193203
core.setOutput('cache-flavor', `suffix=${tagSuffix}`);
194204
195-
const cacheType = `${{ inputs.cache-type }}`.trim();
196-
const metadataImage = `${{ steps.metadata.outputs.image }}`;
197-
const cacheRegistry = `${{ steps.docker-setup.outputs.cache-registry }}`.trim();
205+
const cacheType = (process.env.CACHE_TYPE_INPUT || '').trim();
206+
const metadataImage = process.env.METADATA_IMAGE || '';
207+
const cacheRegistry = (process.env.CACHE_REGISTRY || '').trim();
208+
if (cacheType === 'registry' && !cacheRegistry.length) {
209+
return core.setFailed('Cache registry is required when cache-type is set to "registry".');
210+
}
198211
const metadataImageWithoutRegistry = metadataImage.replace(/^[^\/]+\//, '');
199212
const cacheBaseImage = cacheRegistry.length ? `${cacheRegistry}/${metadataImageWithoutRegistry}` : metadataImage;
200213
const cacheImage = cacheType === 'registry' ? `${cacheBaseImage}/cache` : metadataImage;
@@ -207,14 +220,14 @@ runs:
207220
// docker not available on runner
208221
}
209222
210-
const multiplatformInput = `${{ inputs.multi-platform }}`.trim().toLowerCase();
223+
const multiplatformInput = (process.env.MULTI_PLATFORM_INPUT || '').trim().toLowerCase();
211224
const isMultiplatform = !(multiplatformInput.length === 0 || multiplatformInput === 'false');
212225
if (isMultiplatform) {
213226
core.debug('Multi-platform build is enabled.');
214227
core.setOutput('multi-platform', true);
215228
}
216229
217-
const platform = `${{ inputs.platform }}`.trim();
230+
const platform = (process.env.PLATFORM_INPUT || '').trim();
218231
if (platform.length === 0) {
219232
return core.setFailed('Input "platform" is required.');
220233
}

actions/docker/create-images-manifests/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ inputs:
2727
description: |
2828
Username configuration used to log against OCI registries.
2929
Accepts either a single username string (default format) or a JSON object using the same keys as `oci-registry`.
30-
JSON example: `{"pull:private":"${{ github.repository_owner }}","push":"${{ github.repository_owner }}"}`
30+
JSON example: `{"pull:private":"$\{{ github.repository_owner }}","push":"$\{{ github.repository_owner }}"}`
3131
See https://github.com/docker/login-action#usage.
3232
default: ${{ github.repository_owner }}
3333
required: true
3434
oci-registry-password:
3535
description: |
3636
Password or personal access token configuration used to log against OCI registries.
3737
Accepts either a single password/token string (default format) or a JSON object using the same keys as `oci-registry`.
38-
JSON example: `{"pull:private":"${{ github.token }}","push":"${{ github.token }}"}`
38+
JSON example: `{"pull:private":"$\{{ github.token }}","push":"$\{{ github.token }}"}`
3939
Can be passed in using `secrets.GITHUB_TOKEN`.
4040
See https://github.com/docker/login-action#usage.
4141
default: ${{ github.token }}

actions/docker/setup/README.md

Lines changed: 109 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,124 @@
1-
# Docker setup
1+
<!-- header:start -->
22

3-
Shared action used by the repository Docker actions to:
3+
# ![Icon](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItcGFja2FnZSIgY29sb3I9ImJsdWUiPjxsaW5lIHgxPSIxNi41IiB5MT0iOS40IiB4Mj0iNy41IiB5Mj0iNC4yMSI+PC9saW5lPjxwYXRoIGQ9Ik0yMSAxNlY4YTIgMiAwIDAgMC0xLTEuNzNsLTctNGEyIDIgMCAwIDAtMiAwbC03IDRBMiAyIDAgMCAwIDMgOHY4YTIgMiAwIDAgMCAxIDEuNzNsNyA0YTIgMiAwIDAgMCAyIDBsNy00QTIgMiAwIDAgMCAyMSAxNnoiPjwvcGF0aD48cG9seWxpbmUgcG9pbnRzPSIzLjI3IDYuOTYgMTIgMTIuMDEgMjAuNzMgNi45NiI+PC9wb2x5bGluZT48bGluZSB4MT0iMTIiIHkxPSIyMi4wOCIgeDI9IjEyIiB5Mj0iMTIiPjwvbGluZT48L3N2Zz4=) GitHub Action: Docker - Setup
44

5-
- resolve OCI registry inputs
6-
- ensure Docker is available on the runner
7-
- configure Docker Buildx
8-
- authenticate to one or more OCI registries with `docker/login-action`
5+
<div align="center">
6+
<img src="../../../.github/logo.svg" width="60px" align="center" alt="Docker - Setup" />
7+
</div>
8+
9+
---
10+
11+
<!-- header:end -->
12+
<!-- badges:start -->
13+
14+
[![Marketplace](https://img.shields.io/badge/Marketplace-docker------setup-blue?logo=github-actions)](https://github.com/marketplace/actions/docker---setup)
15+
[![Release](https://img.shields.io/github/v/release/hoverkraft-tech/ci-github-container)](https://github.com/hoverkraft-tech/ci-github-container/releases)
16+
[![License](https://img.shields.io/github/license/hoverkraft-tech/ci-github-container)](http://choosealicense.com/licenses/mit/)
17+
[![Stars](https://img.shields.io/github/stars/hoverkraft-tech/ci-github-container?style=social)](https://img.shields.io/github/stars/hoverkraft-tech/ci-github-container?style=social)
18+
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/hoverkraft-tech/ci-github-container/blob/main/CONTRIBUTING.md)
19+
20+
<!-- badges:end -->
21+
<!-- overview:start -->
22+
23+
## Overview
24+
25+
Shared action to configure Docker tooling and OCI registry authentication.
26+
27+
<!-- overview:end -->
28+
<!-- usage:start -->
929

1030
## Usage
1131

1232
```yaml
13-
- uses: hoverkraft-tech/ci-github-container/actions/docker/setup@main
33+
- uses: hoverkraft-tech/ci-github-container/actions/docker/setup@b6cc2773aa9e7d7362b9e16b9032fefd399e7df6 # copilot/add-multiple-registry-support
1434
with:
35+
# OCI registry configuration used to pull, push and cache images.
36+
# Accepts either a registry hostname string (default format) or a JSON object.
37+
# JSON example: `{"pull":"docker.io","pull:private":"ghcr.io","push":"ghcr.io"}`
38+
#
39+
# This input is required.
40+
# Default: `ghcr.io`
1541
oci-registry: ghcr.io
16-
oci-registry-username: ${{ github.repository_owner }}
17-
oci-registry-password: ${{ github.token }}
42+
43+
# Username configuration used to log against OCI registries.
44+
# Accepts either a single username string (default format) or a JSON object using the same keys as `oci-registry`.
45+
oci-registry-username: ""
46+
47+
# Password or personal access token configuration used to log against OCI registries.
48+
# Accepts either a single password/token string (default format) or a JSON object using the same keys as `oci-registry`.
49+
oci-registry-password: ""
50+
51+
# Optional built images payload used to resolve manifest publication registries.
52+
# When provided, registry authentication targets are inferred from the built image data.
53+
built-images: ""
54+
55+
# Whether to install and configure Docker Buildx.
56+
#
57+
# Default: `true`
58+
setup-buildx: true
1859
```
1960
61+
<!-- usage:end -->
62+
<!-- inputs:start -->
63+
2064
## Inputs
2165
22-
- `oci-registry`: OCI registry configuration used to pull, push and cache images.
23-
- `oci-registry-username`: Username configuration used to log against OCI registries.
24-
- `oci-registry-password`: Password or personal access token configuration used to log against OCI registries.
25-
- `built-images`: Optional built images payload used to resolve manifest publication registries.
26-
- `setup-buildx`: Whether to install and configure Docker Buildx.
66+
| **Input** | **Description** | **Required** | **Default** |
67+
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------ | ----------- |
68+
| **`oci-registry`** | OCI registry configuration used to pull, push and cache images. | **true** | `ghcr.io` |
69+
| | Accepts either a registry hostname string (default format) or a JSON object. | | |
70+
| | JSON example: `{"pull":"docker.io","pull:private":"ghcr.io","push":"ghcr.io"}` | | |
71+
| **`oci-registry-username`** | Username configuration used to log against OCI registries. | **false** | - |
72+
| | Accepts either a single username string (default format) or a JSON object using the same keys as `oci-registry`. | | |
73+
| **`oci-registry-password`** | Password or personal access token configuration used to log against OCI registries. | **false** | - |
74+
| | Accepts either a single password/token string (default format) or a JSON object using the same keys as `oci-registry`. | | |
75+
| **`built-images`** | Optional built images payload used to resolve manifest publication registries. | **false** | - |
76+
| | When provided, registry authentication targets are inferred from the built image data. | | |
77+
| **`setup-buildx`** | Whether to install and configure Docker Buildx. | **false** | `true` |
78+
79+
<!-- inputs:end -->
80+
<!-- secrets:start -->
81+
<!-- secrets:end -->
82+
<!-- outputs:start -->
2783

2884
## Outputs
2985

30-
- `push-registry`: Registry used for published images/manifests.
31-
- `cache-registry`: Registry used for registry-backed build cache.
32-
- `pull-registries`: JSON array of registries used to pull base images.
33-
- `registry-auth`: JSON object suitable for Docker login registry auth.
34-
- `buildx-name`: Docker Buildx builder name.
86+
| **Output** | **Description** |
87+
| --------------------- | -------------------------------------------------- |
88+
| **`push-registry`** | Registry used for published images/manifests. |
89+
| **`cache-registry`** | Registry used for registry-backed build cache. |
90+
| **`pull-registries`** | JSON array of registries used to pull base images. |
91+
| **`buildx-name`** | Docker Buildx builder name. |
92+
93+
<!-- outputs:end -->
94+
<!-- examples:start -->
95+
<!-- examples:end -->
96+
<!-- contributing:start -->
97+
98+
## Contributing
99+
100+
Contributions are welcome! Please see the [contributing guidelines](https://github.com/hoverkraft-tech/ci-github-container/blob/main/CONTRIBUTING.md) for more details.
101+
102+
<!-- contributing:end -->
103+
<!-- security:start -->
104+
<!-- security:end -->
105+
<!-- license:start -->
106+
107+
## License
108+
109+
This project is licensed under the MIT License.
110+
111+
SPDX-License-Identifier: MIT
112+
113+
Copyright © 2026 hoverkraft
114+
115+
For more details, see the [license](http://choosealicense.com/licenses/mit/).
116+
117+
<!-- license:end -->
118+
<!-- generated:start -->
119+
120+
---
121+
122+
This documentation was automatically generated by [CI Dokumentor](https://github.com/hoverkraft-tech/ci-dokumentor).
123+
124+
<!-- generated:end -->

actions/docker/setup/action.yml

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@ outputs:
4646
pull-registries:
4747
description: "JSON array of registries used to pull base images."
4848
value: ${{ steps.resolve-oci-registries.outputs.pull-registries }}
49-
registry-auth:
50-
description: "JSON object suitable for docker/login-action registry-auth."
51-
value: ${{ steps.resolve-oci-registries.outputs.registry-auth }}
5249
buildx-name:
5350
description: "Docker Buildx builder name."
5451
value: ${{ steps.setup-buildx.outputs.name }}
@@ -180,8 +177,8 @@ runs:
180177
return '';
181178
}
182179
183-
function createRegistryAuthMap(registryLogins) {
184-
return registryLogins.reduce((registryAuth, registryLogin) => {
180+
function createRegistryAuthList(registryLogins) {
181+
return registryLogins.reduce((registryAuthList, registryLogin) => {
185182
const { registry, username, password, required } = registryLogin;
186183
187184
if ((username && !password) || (!username && password)) {
@@ -194,24 +191,39 @@ runs:
194191
}
195192
196193
core.info(`Skipping Docker login for optional registry "${registry}" because no credentials were provided.`);
197-
return registryAuth;
194+
return registryAuthList;
198195
}
199196
200-
registryAuth[registry] = {
197+
registryAuthList.push({
198+
registry,
201199
username,
202200
password,
203-
};
201+
});
204202
205-
return registryAuth;
206-
}, {});
203+
return registryAuthList;
204+
}, []);
205+
}
206+
207+
function toRegistryAuthYaml(registryAuthList) {
208+
return registryAuthList
209+
.map(registryAuth => {
210+
const lines = [
211+
`- registry: ${JSON.stringify(registryAuth.registry)}`,
212+
` username: ${JSON.stringify(registryAuth.username)}`,
213+
` password: ${JSON.stringify(registryAuth.password)}`,
214+
];
215+
216+
return lines.join('\n');
217+
})
218+
.join('\n');
207219
}
208220
209-
function setOutputs({ pushRegistry = '', cacheRegistry = '', pullRegistries = [], registryAuth = {} }) {
221+
function setOutputs({ pushRegistry = '', cacheRegistry = '', pullRegistries = [], registryAuth = [] }) {
210222
core.setOutput('push-registry', pushRegistry);
211223
core.setOutput('cache-registry', cacheRegistry);
212224
core.setOutput('pull-registries', JSON.stringify(pullRegistries));
213-
core.setOutput('registry-auth', JSON.stringify(registryAuth));
214-
core.setOutput('has-registry-auth', Object.keys(registryAuth).length ? 'true' : 'false');
225+
core.setOutput('registry-auth', toRegistryAuthYaml(registryAuth));
226+
core.setOutput('has-registry-auth', registryAuth.length ? 'true' : 'false');
215227
}
216228
217229
const registryInputName = ['oci', 'registry'].join('-');
@@ -255,7 +267,7 @@ runs:
255267
const username = resolvePushCredential(usernameByRole);
256268
const password = resolvePushCredential(passwordByRole);
257269
258-
const registryAuth = createRegistryAuthMap(
270+
const registryAuth = createRegistryAuthList(
259271
registries.map(registry => ({
260272
registry,
261273
username,
@@ -348,7 +360,7 @@ runs:
348360
});
349361
}
350362
351-
const registryAuth = createRegistryAuthMap([...registryLoginsByRegistry.values()]);
363+
const registryAuth = createRegistryAuthList([...registryLoginsByRegistry.values()]);
352364
setOutputs({
353365
pushRegistry,
354366
cacheRegistry,

0 commit comments

Comments
 (0)