diff --git a/.github/workflows/docker-build-images.md b/.github/workflows/docker-build-images.md
index 7b2b1101..d0925c04 100644
--- a/.github/workflows/docker-build-images.md
+++ b/.github/workflows/docker-build-images.md
@@ -64,7 +64,7 @@ jobs:
# Default: "${{ github.repository_owner }}"
oci-registry-username: ""
- # Images to build parameters.
+ # Images to build parameters. Json array of objects.
# Example: [{
# "name": "application",
# "dockerfile": "./docker/application/Dockerfile",
@@ -117,6 +117,20 @@ jobs:
| **target
** | Sets the target stage to build. See [Docker build-image action](../../actions/docker/build-image/README.md) | | **true** |
| **platforms
** | List of platforms to build for. It is used as `platform` in [Docker build-image action](../../actions/docker/build-image/README.md). Can be a string (Example: `linux/amd64`) or an object (Example: `{"name": "darwin/amd64","runs-on": "macos-latest"}`) | | **true** |
+#### Platforms entry parameters
+
+| **Parameter** | **Description** | **Default** | **Required** |
+| ------------------------ | ----------------------------------------------------------------------------------------------------------------- | ----------- | ------------ |
+| **name
** | Platform name. Example: `linux/amd64` | | **true** |
+| **runs-on
** | Json array of runner(s) to use. See | | **false** |
+
+##### Default `runs-on` strategy
+
+If a platform entry omits the runs-on
field, the following default strategy applies:
+
+- When the main docker-build-images
job uses a standard hosted runner, that runner is automatically matched to each platform.
+- If the main docker-build-images
job uses a custom or self-hosted runner, all platforms use the same runner.
+
## Outputs
diff --git a/.github/workflows/docker-build-images.yml b/.github/workflows/docker-build-images.yml
index 4a9b7cb1..4d844d65 100644
--- a/.github/workflows/docker-build-images.yml
+++ b/.github/workflows/docker-build-images.yml
@@ -54,7 +54,7 @@ on: # yamllint disable-line rule:truthy
required: false
images:
description: |
- Images to build parameters.
+ Images to build parameters. Json array of objects.
Example: [
{
"name": "application",
@@ -99,8 +99,8 @@ permissions:
jobs:
prepare-variables:
outputs:
- images: ${{ steps.validate-inputs.outputs.images }}
artifact-name: ${{ steps.define-artifact-name.outputs.artifact-name }}
+ images: ${{ steps.define-images-by-platform.outputs.images }}
runs-on: ${{ fromJson(inputs.runs-on) }}
steps:
- id: validate-inputs
@@ -138,7 +138,6 @@ jobs:
// jscpd:ignore-end
// Check each item
- const imagesByPlatform = [];
for (const key in images) {
const image = images[key];
if (typeof image !== 'object') {
@@ -172,12 +171,56 @@ jobs:
if (!image['repository']) {
image['repository'] = `${{ github.repository }}`;
}
+ }
+
+ core.setOutput('images', JSON.stringify(images));
+
+ - id: define-images-by-platform
+ uses: actions/github-script@v7.0.1
+ with:
+ script: |
+ const images = JSON.parse(`${{ steps.validate-inputs.outputs.images }}`);
+
+ const runsOnInput = `${{ inputs.runs-on }}`;
+ const isDefaultRunsOn = runsOnInput === '["ubuntu-latest"]';
+ runsOn = JSON.parse(runsOnInput);
+
+ // See https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners
+ const standardHostedRunnerByPlatform = [
+ { runner: "ubuntu-24.04-arm", platformPattern: /^linux\/arm/ }, // FIXME: should use latest when available
+ { runner: "macos-latest", platformPattern: /^darwin\// },
+ { runner: "windows-latest", platformPattern: /^windows\// }
+ ];
+
+ function getPlatformRunsOn(platform) {
+ if (platform.hasOwnProperty('runs-on')) {
+ return platform['runs-on'];
+ }
+
+ if (!isDefaultRunsOn) {
+ return runsOn;
+ }
+
+ for (const { runner, platformPattern } of standardHostedRunnerByPlatform) {
+ if (platformPattern.test(platform.name)) {
+ return [runner];
+ }
+ }
+
+ return runsOn;
+ }
+
+ // Check each item
+ const imagesByPlatform = [];
+ for (const key in images) {
+ const image = images[key];
// Add image for each platform
const platforms = image['platforms'];
+
for (const platform of platforms) {
- let platformName = platform;
- let platformRunsOn = runsOn;
+ let platformName;
+ let platformRunsOn;
// Platform can be a string or an object
if (typeof platform === 'object') {
@@ -185,11 +228,11 @@ jobs:
throw new Error(`"images[${key}].platforms[${platform}].name" input is missing`);
}
platformName = platform['name'];
-
- if (platform.hasOwnProperty('runs-on')) {
- platformRunsOn = platform['runs-on'];
- }
- } else if (typeof platform !== 'string') {
+ platformRunsOn = getPlatformRunsOn(platform);
+ } else if (typeof platform === 'string') {
+ platformName = platform;
+ platformRunsOn = getPlatformRunsOn({ name: platform });
+ } else {
throw new Error(`"images[${key}].platforms[${platform}]" input is not a string or an object`);
}
diff --git a/actions/docker/build-image/action.yml b/actions/docker/build-image/action.yml
index a8a4f4bc..e2c5c4e3 100644
--- a/actions/docker/build-image/action.yml
+++ b/actions/docker/build-image/action.yml
@@ -126,7 +126,7 @@ runs:
with:
value: ${{ inputs.platform }}
- - id: get-platform-config
+ - id: get-docker-config
shell: bash
run: |
TAG_SUFFIX="-${{ steps.slugify-platform.outputs.result }}"
@@ -136,11 +136,55 @@ runs:
echo "cache-flavor=$CACHE_FLAVOR" >> "$GITHUB_OUTPUT"
+ # Check if docker exists
+ if command -v docker &> /dev/null; then
+ echo "docker-exists=true" >> "$GITHUB_OUTPUT"
+ fi
+
+ PLATFORM="${{ inputs.platform }}"
+ if [ -z "$PLATFORM" ]; then
+ echo "platform-exists=true" >> "$GITHUB_OUTPUT"
+ else
+ PLATFORM_OS=$(echo "$PLATFORM" | cut -d'/' -f1)
+ RUNNER_OS=$(uname -s | tr '[:upper:]' '[:lower:]')
+
+ echo "::debug::PLATFORM_OS=$PLATFORM_OS"
+ echo "::debug::RUNNER_OS=$RUNNER_OS"
+
+ if [ "$PLATFORM_OS" = "$RUNNER_OS" ]; then
+ PLATFORM_ARCH=$(echo "$PLATFORM" | cut -d'/' -f2-)
+ RUNNER_ARCH=$(uname -m)
+
+ echo "::debug::PLATFORM_ARCH=$PLATFORM_ARCH"
+ echo "::debug::RUNNER_ARCH=$RUNNER_ARCH"
+
+ # Convert runner arch to docker arch
+ case $RUNNER_ARCH in
+ x86_64)
+ RUNNER_ARCH="amd64"
+ ;;
+ aarch64)
+ RUNNER_ARCH="arm64"
+ ;;
+ armv7l)
+ RUNNER_ARCH="arm/v7"
+ ;;
+ *)
+ echo "::warning::Unsupported architecture: $RUNNER_ARCH"
+ ;;
+ esac
+
+ if [ "$PLATFORM_ARCH" = "$RUNNER_ARCH" ]; then
+ echo "platform-exists=true" >> "$GITHUB_OUTPUT"
+ fi
+ fi
+ fi
+
- id: cache
uses: int128/docker-build-cache-config-action@v1.37.0
with:
image: ${{ steps.metadata.outputs.image }}/cache
- flavor: ${{ steps.get-platform-config.outputs.cache-flavor }}
+ flavor: ${{ steps.get-docker-config.outputs.cache-flavor }}
pull-request-cache: true
cache-type: gha
@@ -151,17 +195,21 @@ runs:
- shell: bash
run: git lfs pull
- - uses: docker/setup-qemu-action@v3
+ - if: steps.get-docker-config.outputs.docker-exists != 'true'
+ uses: docker/setup-docker-action@v4
+
+ - if: steps.get-docker-config.outputs.platform-exists != 'true'
+ uses: docker/setup-qemu-action@v3
with:
platforms: ${{ inputs.platform }}
- uses: docker/setup-buildx-action@v3
with:
# FIXME: upgrade version when available (https://github.com/docker/buildx/releases)
- version: v0.19.2
+ version: v0.20.1
# FIXME: upgrade version when available (https://hub.docker.com/r/moby/buildkit)
driver-opts: |
- image=moby/buildkit:v0.18.1
+ image=moby/buildkit:v0.19.0
- uses: docker/login-action@v3
with:
diff --git a/tests/charts/umbrella-application/ci/ingress-nopath-values.yaml b/tests/charts/umbrella-application/ci/ingress-nopath-values.yaml
index 9e37faa1..33240ce4 100644
--- a/tests/charts/umbrella-application/ci/ingress-nopath-values.yaml
+++ b/tests/charts/umbrella-application/ci/ingress-nopath-values.yaml
@@ -5,6 +5,6 @@ ingress:
hosts:
- host: chart-example.local
paths:
- - path: ''
+ - path: ""
pathType: ImplementationSpecific
tls: []