mirror of
https://github.com/redhat-actions/buildah-build.git
synced 2025-04-13 22:51:23 +00:00
Rename 'archs' input and improve multiarch (#62)
- Expand readme - Add example Signed-off-by: Tim Etchells <tetchel@gmail.com>
This commit is contained in:
parent
098556ccc2
commit
48fe07762a
13 changed files with 674 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
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# buildah-build Changelog
|
||||
|
||||
## v2.6
|
||||
- Rename "archs" input to "arch"
|
||||
- Improve documentation for multi-architecture builds
|
||||
|
||||
## v2.5.2
|
||||
- Update README for multi-architecture builds
|
||||
|
||||
|
|
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 architecture, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) for more information. | 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 architecture, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) for more information. | 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 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.
|
||||
|
||||
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);
|
||||
const arch = core.getInput(Inputs.ARCH);
|
||||
|
||||
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