mirror of
https://github.com/redhat-actions/buildah-build.git
synced 2025-04-18 00:21:22 +00:00
Rename 'archs' input and improve multiarch
Expand readme Add example Signed-off-by: Tim Etchells <tetchel@gmail.com>
This commit is contained in:
parent
098556ccc2
commit
5cf7e9c453
12 changed files with 670 additions and 424 deletions
71
.github/workflows/multiarch.yml
vendored
Normal file
71
.github/workflows/multiarch.yml
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
name: Multiarch build
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # every day at midnight
|
||||
|
||||
env:
|
||||
IMAGE_NAME: hello-world-multiarch
|
||||
IMAGE_TAG: latest
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build image using Buildah
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [ amd64, i386, arm64v8 ]
|
||||
steps:
|
||||
|
||||
# Checkout buildah action github repository
|
||||
- name: Checkout Buildah action
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: "buildah-build"
|
||||
|
||||
- name: Install qemu dependency
|
||||
run: sudo apt-get install -y qemu-user-static
|
||||
|
||||
- name: Create Dockerfile
|
||||
run: |
|
||||
cat > Dockerfile<<EOF
|
||||
|
||||
ARG ARCH
|
||||
FROM docker.io/\${ARCH}/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
|
||||
uses: ./buildah-build/
|
||||
with:
|
||||
image: ${{ env.IMAGE_NAME }}
|
||||
tags: ${{ env.IMAGE_TAG }}
|
||||
arch: ${{ matrix.arch }}
|
||||
build-args: ARCH=${{ matrix.arch }}
|
||||
dockerfiles: |
|
||||
./Dockerfile
|
||||
|
||||
- name: Echo Outputs
|
||||
run: |
|
||||
echo "Image: ${{ steps.build_image.outputs.image }}"
|
||||
echo "Tags: ${{ steps.build_image.outputs.tags }}"
|
||||
|
||||
- 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"
|
||||
|
||||
- name: Run image
|
||||
run: |
|
||||
podman run --rm ${{ steps.build_image.outputs.image }}:${{ env.IMAGE_TAG }}
|
2
.github/workflows/scratch_build.yml
vendored
2
.github/workflows/scratch_build.yml
vendored
|
@ -84,7 +84,7 @@ jobs:
|
|||
-jar
|
||||
spring-petclinic-*.jar
|
||||
port: 8080
|
||||
archs: amd64,arm64
|
||||
arch: amd64
|
||||
workdir: "."
|
||||
|
||||
- name: Echo Outputs
|
||||
|
|
30
README.md
30
README.md
|
@ -25,7 +25,7 @@ After building your image, use [push-to-registry](https://github.com/redhat-acti
|
|||
|
||||
| Input Name | Description | Default |
|
||||
| ---------- | ----------- | ------- |
|
||||
| archs | Architecture(s) to build the image(s) for. For multiple architectures, separate by a comma. Refer to [Multi arch builds](#multi-arch-builds) to setup the `qemu-user-static` dependency. | None (host architecture)
|
||||
| arch | Label the image with this ARCH, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) to setup the `qemu-user-static` dependency. | None (host architecture)
|
||||
| build-args | Build arguments to pass to the Docker build using `--build-arg`, if using a Dockerfile 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. | `.`
|
||||
| dockerfiles | The list of Dockerfile paths to perform a build using docker instructions. This is a multiline input to allow multiple Dockerfiles. | **Must be provided**
|
||||
|
@ -41,7 +41,7 @@ After building your image, use [push-to-registry](https://github.com/redhat-acti
|
|||
|
||||
| Input Name | Description | Default |
|
||||
| ---------- | ----------- | ------- |
|
||||
| archs | Architecture(s) to build the image(s) for. For multiple architectures, separate by a comma. | None (host architecture)
|
||||
| arch | Label the image with this ARCH, instead of defaulting to the host architecture. | None (host architecture)
|
||||
| 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
|
||||
|
@ -146,11 +146,31 @@ jobs:
|
|||
|
||||
## Multi arch builds
|
||||
|
||||
Cross-architecture builds from dockerfiles containing `RUN` instructions require `qemu-user-static` emulation registered in the Linux kernel. Run `sudo apt install -y qemu-user-static` on Debian-based container hosts. Or run the following registration command for other distributions:
|
||||
```
|
||||
Refer to the [multi-arch example](./.github/workflows/multiarch.yml).
|
||||
|
||||
### Emulating RUN instructions
|
||||
|
||||
Cross-architecture builds from dockerfiles containing `RUN` instructions require `qemu-user-static` emulation registered in the Linux kernel.
|
||||
|
||||
For example, run `sudo apt install qemu-user-static` on Debian hosts, or `sudo dnf install qemu-user-static` on Fedora.
|
||||
|
||||
You can run a [containerized version of the registration](https://hub.docker.com/r/tonistiigi/binfmt) if the package does not exist for your distribution:
|
||||
```sh
|
||||
sudo podman run --rm --privileged docker.io/tonistiigi/binfmt --install all
|
||||
```
|
||||
The registration remains active until the container host reboots.
|
||||
This registration remains active until the host reboots.
|
||||
|
||||
### The `arch` input
|
||||
The `arch` argument overrides the `ARCH` 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.
|
||||
|
||||
There is a simple example [in this issue](https://github.com/redhat-actions/buildah-build/issues/60#issuecomment-876552452).
|
||||
|
||||
### Creating a Multi-Arch Image List
|
||||
Use the [buildah manifest](https://github.com/containers/buildah/blob/main/docs/buildah-manifest.md) command to bundle images into an image list, so multiple image can be referenced by the same repository tag.
|
||||
|
||||
There are examples and explanations of the `manifest` command [in this issue](https://github.com/containers/buildah/issues/1590).
|
||||
|
||||
This action does not support the `manifest` command at this time, but there is [an issue open](https://github.com/redhat-actions/buildah-build/issues/61).
|
||||
|
||||
## Using private images
|
||||
|
||||
|
|
|
@ -47,11 +47,11 @@ inputs:
|
|||
description: 'Set to true to build using the OCI image format instead of the Docker image format'
|
||||
default: 'false'
|
||||
required: false
|
||||
arch:
|
||||
description: 'Label the image with this ARCH, instead of defaulting to the host architecture.'
|
||||
required: false
|
||||
archs:
|
||||
description: |
|
||||
Architecture(s) to build the image(s) for. For multiple architectures,
|
||||
separate by a comma.
|
||||
default: 'amd64'
|
||||
description: 'Alias for "arch". "arch" takes precedence if both are set.'
|
||||
required: false
|
||||
extra-args:
|
||||
description: |
|
||||
|
|
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
0
git-hooks/pre-commit
Normal file → Executable file
0
git-hooks/pre-commit
Normal file → Executable file
907
package-lock.json
generated
907
package-lock.json
generated
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
@ -23,19 +23,18 @@
|
|||
"@actions/core": "^1.2.6",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/io": "^1.0.2",
|
||||
"ini": "^2.0.0",
|
||||
"language-recognizer": "0.0.1"
|
||||
"ini": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redhat-actions/action-io-generator": "^1.5.0",
|
||||
"@redhat-actions/eslint-config": "^1.2.11",
|
||||
"@redhat-actions/eslint-config": "^1.3.2",
|
||||
"@redhat-actions/tsconfig": "^1.1.1",
|
||||
"@types/ini": "^1.3.30",
|
||||
"@types/node": "^12",
|
||||
"@typescript-eslint/eslint-plugin": "^4.14.1",
|
||||
"@typescript-eslint/parser": "^4.14.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
||||
"@typescript-eslint/parser": "^4.28.2",
|
||||
"@vercel/ncc": "^0.25.1",
|
||||
"eslint": "^7.18.0",
|
||||
"typescript": "^4.0.5"
|
||||
"eslint": "^7.30.0",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,13 @@ export interface BuildahConfigSettings {
|
|||
envs?: string[];
|
||||
port?: string;
|
||||
workingdir?: string;
|
||||
archs?: string;
|
||||
arch?: string;
|
||||
}
|
||||
|
||||
interface Buildah {
|
||||
buildUsingDocker(
|
||||
image: string, context: string, dockerFiles: string[], buildArgs: string[],
|
||||
useOCI: boolean, archs: string, layers: string, extraArgs: string[]
|
||||
useOCI: boolean, arch: string, layers: string, extraArgs: string[]
|
||||
): Promise<CommandResult>;
|
||||
from(baseImage: string): Promise<CommandResult>;
|
||||
copy(container: string, contentToCopy: string[]): Promise<CommandResult | undefined>;
|
||||
|
@ -63,12 +63,12 @@ export class BuildahCli implements Buildah {
|
|||
|
||||
async buildUsingDocker(
|
||||
image: string, context: string, dockerFiles: string[], buildArgs: string[],
|
||||
useOCI: boolean, archs: string, layers: string, extraArgs: string[]
|
||||
useOCI: boolean, arch: string, layers: string, extraArgs: string[]
|
||||
): Promise<CommandResult> {
|
||||
const args: string[] = [ "bud" ];
|
||||
if (archs) {
|
||||
if (arch) {
|
||||
args.push("--arch");
|
||||
args.push(archs);
|
||||
args.push(arch);
|
||||
}
|
||||
dockerFiles.forEach((file) => {
|
||||
args.push("-f");
|
||||
|
@ -131,9 +131,9 @@ export class BuildahCli implements Buildah {
|
|||
args.push(env);
|
||||
});
|
||||
}
|
||||
if (settings.archs) {
|
||||
if (settings.arch) {
|
||||
args.push("--arch");
|
||||
args.push(settings.archs);
|
||||
args.push(settings.arch);
|
||||
}
|
||||
if (settings.workingdir) {
|
||||
args.push("--workingdir");
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
// This file was auto-generated by action-io-generator. Do not edit by hand!
|
||||
export enum Inputs {
|
||||
/**
|
||||
* Architecture(s) to build the image(s) for. For multiple architectures,
|
||||
* separate by a comma.
|
||||
* Label the image with this ARCH, instead of defaulting to the host architecture.
|
||||
* Required: false
|
||||
* Default: "amd64"
|
||||
* Default: None.
|
||||
*/
|
||||
ARCH = "arch",
|
||||
/**
|
||||
* Alias for "arch". "arch" takes precedence if both are set.
|
||||
* Required: false
|
||||
* Default: None.
|
||||
*/
|
||||
ARCHS = "archs",
|
||||
/**
|
||||
|
|
34
src/index.ts
34
src/index.ts
|
@ -33,21 +33,20 @@ export async function run(): Promise<void> {
|
|||
const tagsList: string[] = tags.split(" ");
|
||||
|
||||
// info message if user doesn't provides any tag
|
||||
if (!tagsList.length) {
|
||||
if (tagsList.length === 0) {
|
||||
core.info(`Input "${Inputs.TAGS}" is not provided, using default tag "${DEFAULT_TAG}"`);
|
||||
tagsList.push(DEFAULT_TAG);
|
||||
}
|
||||
const newImage = `${image}:${tagsList[0]}`;
|
||||
const useOCI = core.getInput(Inputs.OCI) === "true";
|
||||
let archs: string | undefined = core.getInput(Inputs.ARCHS);
|
||||
// remove white spaces (if any) in archs input
|
||||
archs = archs.replace(/\s+/g, "");
|
||||
|
||||
const arch = getArch();
|
||||
|
||||
if (dockerFiles.length !== 0) {
|
||||
await doBuildUsingDockerFiles(cli, newImage, workspace, dockerFiles, useOCI, archs);
|
||||
await doBuildUsingDockerFiles(cli, newImage, workspace, dockerFiles, useOCI, arch);
|
||||
}
|
||||
else {
|
||||
await doBuildFromScratch(cli, newImage, useOCI, archs);
|
||||
await doBuildFromScratch(cli, newImage, useOCI, arch);
|
||||
}
|
||||
|
||||
if (tagsList.length > 1) {
|
||||
|
@ -58,7 +57,7 @@ export async function run(): Promise<void> {
|
|||
}
|
||||
|
||||
async function doBuildUsingDockerFiles(
|
||||
cli: BuildahCli, newImage: string, workspace: string, dockerFiles: string[], useOCI: boolean, archs: string
|
||||
cli: BuildahCli, newImage: string, workspace: string, dockerFiles: string[], useOCI: boolean, arch: string
|
||||
): Promise<void> {
|
||||
if (dockerFiles.length === 1) {
|
||||
core.info(`Performing build from Dockerfile`);
|
||||
|
@ -81,12 +80,12 @@ async function doBuildUsingDockerFiles(
|
|||
buildahBudExtraArgs = lines.flatMap((line) => line.split(" ")).map((arg) => arg.trim());
|
||||
}
|
||||
await cli.buildUsingDocker(
|
||||
newImage, context, dockerFileAbsPaths, buildArgs, useOCI, archs, layers, buildahBudExtraArgs
|
||||
newImage, context, dockerFileAbsPaths, buildArgs, useOCI, arch, layers, buildahBudExtraArgs
|
||||
);
|
||||
}
|
||||
|
||||
async function doBuildFromScratch(
|
||||
cli: BuildahCli, newImage: string, useOCI: boolean, archs: string
|
||||
cli: BuildahCli, newImage: string, useOCI: boolean, arch: string
|
||||
): Promise<void> {
|
||||
core.info(`Performing build from scratch`);
|
||||
|
||||
|
@ -107,7 +106,7 @@ async function doBuildFromScratch(
|
|||
port,
|
||||
workingdir: workingDir,
|
||||
envs,
|
||||
archs,
|
||||
arch,
|
||||
};
|
||||
await cli.config(containerId, newImageConfig);
|
||||
await cli.commit(containerId, newImage, useOCI);
|
||||
|
@ -127,4 +126,19 @@ function getInputList(name: string): string[] {
|
|||
);
|
||||
}
|
||||
|
||||
function getArch(): string {
|
||||
// 'arch' should be used over 'archs', see https://github.com/redhat-actions/buildah-build/issues/60
|
||||
const archs = core.getInput(Inputs.ARCHS).replace(/\s+/g, "");
|
||||
const arch = core.getInput(Inputs.ARCH).replace(/\s+/g, "");
|
||||
|
||||
if (arch && archs) {
|
||||
core.warning(
|
||||
`Please use only one input of "${Inputs.ARCH}" and "${Inputs.ARCHS}". "${Inputs.ARCH}" takes precedence, `
|
||||
+ `so --arch argument will be "${arch}".`
|
||||
);
|
||||
}
|
||||
|
||||
return arch || archs;
|
||||
}
|
||||
|
||||
run().catch(core.setFailed);
|
||||
|
|
Loading…
Reference in a new issue