Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(workflows/docker-build-images): add strategy to defined runner regarding platform type #353

Merged
merged 1 commit into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
58 changes: 53 additions & 5 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,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:
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: []
Loading