Skip to content

Commit

Permalink
Add support for 'platform' parameter (#75)
Browse files Browse the repository at this point in the history
Signed-off-by: James Addison <jay@jp-hosting.net>
  • Loading branch information
jayaddison authored Oct 14, 2021
1 parent 979e6a6 commit 3bb95d0
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 21 deletions.
85 changes: 76 additions & 9 deletions .github/workflows/multiarch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ env:
IMAGE_TAG: latest

jobs:
build:
name: Build image using Buildah
build-multiarch:
name: Build multi-architecture image using Buildah
runs-on: ubuntu-20.04
strategy:
fail-fast: false
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
EOF
- name: Build Image
id: build_image
id: build_image_multiarch
uses: ./buildah-build/
with:
image: ${{ env.IMAGE_NAME }}
Expand All @@ -63,19 +63,86 @@ jobs:
- name: Echo Outputs
run: |
echo "Image: ${{ steps.build_image.outputs.image }}"
echo "Tags: ${{ steps.build_image.outputs.tags }}"
echo "Tagged Image: ${{ steps.build_image.outputs.image-with-tag }}"
echo "Image: ${{ steps.build_image_multiarch.outputs.image }}"
echo "Tags: ${{ steps.build_image_multiarch.outputs.tags }}"
echo "Tagged Image: ${{ steps.build_image_multiarch.outputs.image-with-tag }}"
- name: Check images created
run: buildah images | grep '${{ env.IMAGE_NAME }}'

- name: Check image metadata
run: |
set -x
buildah inspect ${{ steps.build_image.outputs.image }}:${{ env.IMAGE_TAG }} | jq ".OCIv1.architecture"
buildah inspect ${{ steps.build_image.outputs.image }}:${{ env.IMAGE_TAG }} | jq ".Docker.architecture"
buildah inspect ${{ steps.build_image_multiarch.outputs.image }}:${{ env.IMAGE_TAG }} | jq ".OCIv1.architecture"
buildah inspect ${{ steps.build_image_multiarch.outputs.image }}:${{ env.IMAGE_TAG }} | jq ".Docker.architecture"
- name: Run image
run: |
podman run --rm ${{ steps.build_image.outputs.image }}:${{ env.IMAGE_TAG }}
podman run --rm ${{ steps.build_image_multiarch.outputs.image }}:${{ env.IMAGE_TAG }}
build-multiplatform:
name: Build multi-platform image using Buildah
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
platform: [ "linux/amd64", "linux/arm64/v8" ]
install_latest: [ true, false ]

steps:

# Checkout buildah action github repository
- name: Checkout Buildah action
uses: actions/checkout@v2
with:
path: "buildah-build"

- name: Install latest buildah
if: matrix.install_latest
run: |
bash buildah-build/.github/install_latest_buildah.sh
- name: Install qemu dependency
run: |
sudo apt-get update
sudo apt-get install -y qemu-user-static
- name: Create Containerfile
run: |
cat > Containerfile<<EOF
FROM docker.io/alpine:3.14
RUN echo "hello world"
ENTRYPOINT [ "sh", "-c", "echo -n 'Machine: ' && uname -m && echo -n 'Bits: ' && getconf LONG_BIT && echo 'goodbye world'" ]
EOF
- name: Build Image
id: build_image_multiplatform
uses: ./buildah-build/
with:
image: ${{ env.IMAGE_NAME }}
tags: ${{ env.IMAGE_TAG }}
platform: ${{ matrix.platform }}
containerfiles: |
./Containerfile
- name: Echo Outputs
run: |
echo "Image: ${{ steps.build_image_multiplatform.outputs.image }}"
echo "Tags: ${{ steps.build_image_multiplatform.outputs.tags }}"
echo "Tagged Image: ${{ steps.build_image_multiplatform.outputs.image-with-tag }}"
- name: Check images created
run: buildah images | grep '${{ env.IMAGE_NAME }}'

- name: Check image metadata
run: |
set -x
buildah inspect ${{ steps.build_image_multiplatform.outputs.image }}:${{ env.IMAGE_TAG }} | jq ".OCIv1.architecture"
buildah inspect ${{ steps.build_image_multiplatform.outputs.image }}:${{ env.IMAGE_TAG }} | jq ".Docker.architecture"
- name: Run image
run: |
podman run --rm ${{ steps.build_image_multiplatform.outputs.image }}:${{ env.IMAGE_TAG }}
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ After building your image, use [push-to-registry](https://github.com/redhat-acti
| Input Name | Description | Default |
| ---------- | ----------- | ------- |
| arch | Label the image with this architecture, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) for more information. | None (host architecture)
| platform | Label the image with this platform, instead of defaulting to the host platform. Refer to [Multi arch builds](#multi-arch-builds) for more information. | None (host platform)
| build-args | Build arguments to pass to the Docker build using `--build-arg`, if using a Containerfile that requires ARGs. Use the form `arg_name=arg_value`, and separate arguments with newlines. | None
| context | Path to directory to use as the build context. | `.`
| containerfiles\* | The list of Containerfile paths to perform a build using docker instructions. This is a multiline input to allow multiple Containerfiles. | **Must be provided**
Expand All @@ -43,6 +44,7 @@ After building your image, use [push-to-registry](https://github.com/redhat-acti
| Input Name | Description | Default |
| ---------- | ----------- | ------- |
| arch | Label the image with this architecture, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) for more information. | None (host architecture)
| platform | Label the image with this platform, instead of defaulting to the host platform. Refer to [Multi arch builds](#multi-arch-builds) for more information. | None (host platform)
| base-image | The base image to use for the container. | **Must be provided**
| content | Paths to files or directories to copy inside the container to create the file image. This is a multiline input to allow you to copy multiple files/directories.| None
| entrypoint | The entry point to set for the container. This is a multiline input; split arguments across lines. | None
Expand Down Expand Up @@ -179,8 +181,8 @@ sudo podman run --rm --privileged docker.io/tonistiigi/binfmt --install all
```
This registration remains active until the host reboots.

### The `arch` input
The `arch` argument overrides the Architecture label in the output image. It does not actually affect the architectures the output image will run on. The image must still be built for the required architecture.
### The `arch` and `platform` inputs
The `arch` and `platform` arguments override the Architecture and Platform labels in the output image, respectively. They do not actually affect the architectures and platforms the output image will run on. The image must still be built for the required architecture or platform.

There is a simple example [in this issue](https://github.com/redhat-actions/buildah-build/issues/60#issuecomment-876552452).

Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ inputs:
archs:
description: 'Alias for "arch". "arch" takes precedence if both are set.'
required: false
platform:
description: 'Label the image with this PLATFORM, instead of defaulting to the host platform.'
required: false
extra-args:
description: |
Extra args to be passed to buildah bud.
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions src/buildah.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ export interface BuildahConfigSettings {
port?: string;
workingdir?: string;
arch?: string;
platform?: string;
}

interface Buildah {
buildUsingDocker(
image: string, context: string, containerFiles: string[], buildArgs: string[],
useOCI: boolean, arch: string, layers: string, extraArgs: string[]
useOCI: boolean, arch: string, platform: string, layers: string, extraArgs: string[]
): Promise<CommandResult>;
from(baseImage: string): Promise<CommandResult>;
config(container: string, setting: BuildahConfigSettings): Promise<CommandResult>;
Expand Down Expand Up @@ -63,13 +64,17 @@ export class BuildahCli implements Buildah {

async buildUsingDocker(
image: string, context: string, containerFiles: string[], buildArgs: string[],
useOCI: boolean, arch: string, layers: string, extraArgs: string[]
useOCI: boolean, arch: string, platform: string, layers: string, extraArgs: string[]
): Promise<CommandResult> {
const args: string[] = [ "bud" ];
if (arch) {
args.push("--arch");
args.push(arch);
}
if (platform) {
args.push("--platform");
args.push(platform);
}
containerFiles.forEach((file) => {
args.push("-f");
args.push(file);
Expand Down Expand Up @@ -135,6 +140,10 @@ export class BuildahCli implements Buildah {
args.push("--arch");
args.push(settings.arch);
}
if (settings.platform) {
args.push("--platform");
args.push(settings.platform);
}
if (settings.workingdir) {
args.push("--workingdir");
args.push(settings.workingdir);
Expand Down
6 changes: 6 additions & 0 deletions src/generated/inputs-outputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ export enum Inputs {
* Default: "false"
*/
OCI = "oci",
/**
* Label the image with this PLATFORM, instead of defaulting to the host platform.
* Required: false
* Default: None.
*/
PLATFORM = "platform",
/**
* The port to expose when running containers based on image
* Required: false
Expand Down
19 changes: 13 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as path from "path";
import { Inputs, Outputs } from "./generated/inputs-outputs";
import { BuildahCli, BuildahConfigSettings } from "./buildah";
import {
getArch, getContainerfiles, getInputList, splitByNewline,
getArch, getPlatform, getContainerfiles, getInputList, splitByNewline,
isFullImageName, getFullImageName,
} from "./utils";

Expand Down Expand Up @@ -54,12 +54,17 @@ export async function run(): Promise<void> {
const useOCI = core.getInput(Inputs.OCI) === "true";

const arch = getArch();
const platform = getPlatform();

if (arch && platform) {
throw new Error("The --platform option may not be used in combination with the --arch option.");
}

if (containerFiles.length !== 0) {
await doBuildUsingContainerFiles(cli, newImage, workspace, containerFiles, useOCI, arch);
await doBuildUsingContainerFiles(cli, newImage, workspace, containerFiles, useOCI, arch, platform);
}
else {
await doBuildFromScratch(cli, newImage, useOCI, arch);
await doBuildFromScratch(cli, newImage, useOCI, arch, platform);
}

if (tagsList.length > 1) {
Expand All @@ -71,7 +76,8 @@ export async function run(): Promise<void> {
}

async function doBuildUsingContainerFiles(
cli: BuildahCli, newImage: string, workspace: string, containerFiles: string[], useOCI: boolean, arch: string
cli: BuildahCli, newImage: string, workspace: string, containerFiles: string[], useOCI: boolean, arch: string,
platform: string
): Promise<void> {
if (containerFiles.length === 1) {
core.info(`Performing build from Containerfile`);
Expand All @@ -94,12 +100,12 @@ async function doBuildUsingContainerFiles(
buildahBudExtraArgs = lines.flatMap((line) => line.split(" ")).map((arg) => arg.trim());
}
await cli.buildUsingDocker(
newImage, context, containerFileAbsPaths, buildArgs, useOCI, arch, layers, buildahBudExtraArgs
newImage, context, containerFileAbsPaths, buildArgs, useOCI, arch, platform, layers, buildahBudExtraArgs
);
}

async function doBuildFromScratch(
cli: BuildahCli, newImage: string, useOCI: boolean, arch: string
cli: BuildahCli, newImage: string, useOCI: boolean, arch: string, platform: string
): Promise<void> {
core.info(`Performing build from scratch`);

Expand All @@ -119,6 +125,7 @@ async function doBuildFromScratch(
workingdir: workingDir,
envs,
arch,
platform,
};
await cli.config(containerId, newImageConfig);
await cli.copy(containerId, content);
Expand Down
4 changes: 4 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export function getArch(): string {
return arch || archs;
}

export function getPlatform(): string {
return core.getInput(Inputs.PLATFORM);
}

export function getContainerfiles(): string[] {
// 'containerfile' should be used over 'dockerfile',
// see https://github.com/redhat-actions/buildah-build/issues/57
Expand Down

0 comments on commit 3bb95d0

Please sign in to comment.