Skip to content

Commit

Permalink
feat(workflows/docker-build-images): add strategy to defined runner r…
Browse files Browse the repository at this point in the history
…egarding platform type

Signed-off-by: Emilien Escalle <[email protected]>
  • Loading branch information
neilime committed Jan 24, 2025
1 parent 68a2e5b commit a4f2dab
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 15 deletions.
16 changes: 15 additions & 1 deletion .github/workflows/docker-build-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -117,6 +117,20 @@ jobs:
| **<code>target</code>** | Sets the target stage to build. See [Docker build-image action](../../actions/docker/build-image/README.md) | | **true** |
| **<code>platforms</code>** | 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** |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------- | ----------- | ------------ |
| **<code>name</code>** | Platform name. Example: `linux/amd64` | | **true** |
| **<code>runs-on</code>** | Json array of runner(s) to use. See <https://docs.github.com/en/actions/using-jobs/choosing-the-runner-for-a-job> | | **false** |

##### Default `runs-on` strategy

If a platform entry omits the <code>runs-on</code> field, the following default strategy applies:

- When the main <code>docker-build-images</code> job uses a standard hosted runner, that runner is automatically matched to each platform.
- If the main <code>docker-build-images</code> job uses a custom or self-hosted runner, all platforms use the same runner.

<!-- start outputs -->

## Outputs
Expand Down
63 changes: 53 additions & 10 deletions .github/workflows/docker-build-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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') {
Expand Down Expand Up @@ -172,24 +171,68 @@ jobs:
if (!image['repository']) {
image['repository'] = `${{ github.repository }}`;
}
}
core.setOutput('images', JSON.stringify(images));
- id: define-images-by-platform
uses: actions/[email protected]
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') {
if (!platform.hasOwnProperty('name')) {
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`);
}
Expand Down
54 changes: 51 additions & 3 deletions actions/docker/build-image/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}"
Expand All @@ -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/[email protected]
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

Expand All @@ -151,7 +195,11 @@ 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 }}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ ingress:
hosts:
- host: chart-example.local
paths:
- path: ''
- path: ""
pathType: ImplementationSpecific
tls: []

0 comments on commit a4f2dab

Please sign in to comment.