mirror of
https://github.com/redhat-actions/buildah-build.git
synced 2025-04-21 09:31:22 +00:00
Compare commits
70 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7a95fa7ee0 | ||
|
1ec5690277 | ||
|
c79846fb30 | ||
|
b4dc19b4ba | ||
|
5f55f580e1 | ||
|
6c6c802bcc | ||
|
3e3409a032 | ||
|
5177407148 | ||
|
4b8d36793b | ||
|
807a385655 | ||
|
ea6be4fe0d | ||
|
ab528f78d0 | ||
|
2cb54cfbef | ||
|
d097e2e3d2 | ||
|
796a66693a | ||
|
c0b899fbc8 | ||
|
df970b4ee2 | ||
|
b053111d08 | ||
|
5b84b38144 | ||
|
b13805753a | ||
|
5ca1dab81f | ||
|
72b90216e8 | ||
|
3ffbc5da4f | ||
|
c7ca484deb | ||
|
c06a2c4759 | ||
|
88ef72ac21 | ||
|
bb88487cd2 | ||
|
733d8e9a38 | ||
|
3bb95d0042 | ||
|
979e6a6c6e | ||
|
f123b1f960 | ||
|
8eb0f5b196 | ||
|
f9dfea0413 | ||
|
ab006ef445 | ||
|
fe5edd5859 | ||
|
b82756135c | ||
|
2ee55183af | ||
|
a9a026b165 | ||
|
53657f6490 | ||
|
b803a73317 | ||
|
48fe07762a | ||
|
098556ccc2 | ||
|
208b26d3fb | ||
|
5437d64402 | ||
|
e2bcacef27 | ||
|
b8dfc09b78 | ||
|
2f7f68ec84 | ||
|
b78bde0b60 | ||
|
0c92abf306 | ||
|
14046ffbeb | ||
|
6dbeb7e1f6 | ||
|
65f18d484c | ||
|
8fe53efc79 | ||
|
3196e5acb5 | ||
|
54ff9945b9 | ||
|
71b37c4385 | ||
|
ef84eec383 | ||
|
1f7c249930 | ||
|
aec3a155d1 | ||
|
76570bc65b | ||
|
d871ed8ae9 | ||
|
3c5ca2c147 | ||
|
803a1413e7 | ||
|
21e07c3197 | ||
|
e56c3269a5 | ||
|
9deeef6ee2 | ||
|
20a8e62ce0 | ||
|
88e0085544 | ||
|
75dab40354 | ||
|
a1b98d2603 |
31 changed files with 6378 additions and 10940 deletions
15
.editorconfig
Normal file
15
.editorconfig
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
tab_width = 4
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
max_line_length = 120
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
tab_width = 2
|
||||||
|
indent_size = 2
|
5
.eslintrc.js
Normal file
5
.eslintrc.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
"@redhat-actions/eslint-config",
|
||||||
|
],
|
||||||
|
};
|
3
.github/install_latest_buildah.sh
vendored
Normal file
3
.github/install_latest_buildah.sh
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
sudo apt-key add - < Release.key
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get -qq -y install buildah
|
66
.github/workflows/check-lowercase.yaml
vendored
Normal file
66
.github/workflows/check-lowercase.yaml
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Check Case Normalization
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: ImageCaseTest
|
||||||
|
IMAGE_TAGS: v1 TagCaseTest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build image using Buildah
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: "buildah-build"
|
||||||
|
|
||||||
|
- name: Install latest buildah
|
||||||
|
if: matrix.install_latest
|
||||||
|
run: |
|
||||||
|
bash buildah-build/.github/install_latest_buildah.sh
|
||||||
|
|
||||||
|
- name: Create Dockerfile
|
||||||
|
run: |
|
||||||
|
cat > Containerfile<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build image using Buildah action
|
||||||
|
- name: Build Image
|
||||||
|
id: build_image
|
||||||
|
uses: ./buildah-build/
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
layers: false
|
||||||
|
tags: ${{ env.IMAGE_TAGS }}
|
||||||
|
containerfiles: |
|
||||||
|
./Containerfile
|
||||||
|
extra-args: |
|
||||||
|
--pull
|
||||||
|
|
||||||
|
- 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 }}"
|
||||||
|
|
||||||
|
# Check if image is build
|
||||||
|
- name: Check images created
|
||||||
|
run: buildah images
|
48
.github/workflows/ci.yml
vendored
Normal file
48
.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
name: CI checks
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Run ESLint
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run lint
|
||||||
|
|
||||||
|
check-dist:
|
||||||
|
name: Check Distribution
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
BUNDLE_FILE: "dist/index.js"
|
||||||
|
BUNDLE_COMMAND: "npm run bundle"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Verify Latest Bundle
|
||||||
|
uses: redhat-actions/common/bundle-verifier@v1
|
||||||
|
with:
|
||||||
|
bundle_file: ${{ env.BUNDLE_FILE }}
|
||||||
|
bundle_command: ${{ env.BUNDLE_COMMAND }}
|
||||||
|
|
||||||
|
check-inputs-outputs:
|
||||||
|
name: Check Input and Output enums
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
IO_FILE: ./src/generated/inputs-outputs.ts
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Verify Input and Output enums
|
||||||
|
uses: redhat-actions/common/action-io-generator@v1
|
||||||
|
with:
|
||||||
|
io_file: ${{ env.IO_FILE }}
|
65
.github/workflows/containerfile_build.yml
vendored
Normal file
65
.github/workflows/containerfile_build.yml
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Build from containerfile
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: "hello-world"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build image using Buildah
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: "buildah-build"
|
||||||
|
|
||||||
|
- name: Install latest buildah
|
||||||
|
if: matrix.install_latest
|
||||||
|
run: |
|
||||||
|
bash buildah-build/.github/install_latest_buildah.sh
|
||||||
|
|
||||||
|
- name: Create Dockerfile
|
||||||
|
run: |
|
||||||
|
cat > Containerfile<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build image using Buildah action
|
||||||
|
- name: Build Image
|
||||||
|
id: build_image
|
||||||
|
uses: ./buildah-build/
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
layers: false
|
||||||
|
tags: 'latest ${{ github.sha }}'
|
||||||
|
containerfiles: |
|
||||||
|
./Containerfile
|
||||||
|
extra-args: |
|
||||||
|
--pull
|
||||||
|
|
||||||
|
- 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 }}"
|
||||||
|
|
||||||
|
# Check if image is build
|
||||||
|
- name: Check images created
|
||||||
|
run: buildah images | grep '${{ env.IMAGE_NAME }}'
|
185
.github/workflows/docker_metadata_action.yml
vendored
Normal file
185
.github/workflows/docker_metadata_action.yml
vendored
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Build with docker/metadata-action
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-containerfile:
|
||||||
|
name: Build image with Containerfile
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: "hello-world"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Docker Metadata
|
||||||
|
id: docker-metadata
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=edge
|
||||||
|
type=sha
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=schedule
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
|
||||||
|
|
||||||
|
- name: Install latest buildah
|
||||||
|
if: matrix.install_latest
|
||||||
|
run: |
|
||||||
|
bash .github/install_latest_buildah.sh
|
||||||
|
|
||||||
|
- name: Create Dockerfile
|
||||||
|
run: |
|
||||||
|
cat > Containerfile<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build image using Buildah action
|
||||||
|
- name: Build Image
|
||||||
|
id: build_image
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
layers: false
|
||||||
|
tags: ${{ steps.docker-metadata.outputs.tags }}
|
||||||
|
labels: ${{ steps.docker-metadata.outputs.labels }}
|
||||||
|
containerfiles: |
|
||||||
|
./Containerfile
|
||||||
|
extra-args: |
|
||||||
|
--pull
|
||||||
|
|
||||||
|
- 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 }}"
|
||||||
|
|
||||||
|
# Check if image is build
|
||||||
|
- 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-with-tag }} | jq '.OCIv1.config.Labels."org.opencontainers.image.title"'
|
||||||
|
buildah inspect ${{ steps.build_image.outputs.image-with-tag }} | jq '.OCIv1.config.Labels."org.opencontainers.image.description"'
|
||||||
|
buildah inspect ${{ steps.build_image.outputs.image-with-tag }} | jq '.Docker.config.Labels."org.opencontainers.image.title"'
|
||||||
|
buildah inspect ${{ steps.build_image.outputs.image-with-tag }} | jq '.Docker.config.Labels."org.opencontainers.image.description"'
|
||||||
|
|
||||||
|
build-scratch:
|
||||||
|
name: Build image without Containerfile
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
PROJECT_DIR: spring-petclinic
|
||||||
|
IMAGE_NAME: spring-petclinic
|
||||||
|
MVN_REPO_DIR: ~/.m2/repository
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Docker Metadata
|
||||||
|
id: docker-metadata
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=edge
|
||||||
|
type=sha
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=schedule
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
|
||||||
|
|
||||||
|
- name: Install latest buildah
|
||||||
|
if: matrix.install_latest
|
||||||
|
run: |
|
||||||
|
bash .github/install_latest_buildah.sh
|
||||||
|
|
||||||
|
# Checkout spring-petclinic github repository
|
||||||
|
- name: Checkout spring-petclinic project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: "spring-projects/spring-petclinic"
|
||||||
|
path: ${{ env.PROJECT_DIR }}
|
||||||
|
|
||||||
|
# Setup java.
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '17'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
# Run maven to build the project
|
||||||
|
- name: Maven
|
||||||
|
working-directory: ${{ env.PROJECT_DIR }}
|
||||||
|
run: |
|
||||||
|
mvn package -ntp -B
|
||||||
|
|
||||||
|
# Build image using Buildah action
|
||||||
|
- name: Build Image
|
||||||
|
id: build_image
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
tags: ${{ steps.docker-metadata.outputs.tags }}
|
||||||
|
labels: ${{ steps.docker-metadata.outputs.labels }}
|
||||||
|
base-image: 'registry.access.redhat.com/openjdk/openjdk-11-rhel7'
|
||||||
|
# To avoid hardcoding a particular version of the binary.
|
||||||
|
content: |
|
||||||
|
./spring-petclinic/target/spring-petclinic-*.jar
|
||||||
|
entrypoint: |
|
||||||
|
java
|
||||||
|
-jar
|
||||||
|
spring-petclinic-*.jar
|
||||||
|
port: 8080
|
||||||
|
arch: amd64
|
||||||
|
workdir: "."
|
||||||
|
|
||||||
|
- 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 }}"
|
||||||
|
|
||||||
|
# Check if image is build
|
||||||
|
- 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-with-tag }} | jq '.OCIv1.config.Labels."org.opencontainers.image.title"'
|
||||||
|
buildah inspect ${{ steps.build_image.outputs.image-with-tag }} | jq '.OCIv1.config.Labels."org.opencontainers.image.description"'
|
||||||
|
buildah inspect ${{ steps.build_image.outputs.image-with-tag }} | jq '.Docker.config.Labels."org.opencontainers.image.title"'
|
||||||
|
buildah inspect ${{ steps.build_image.outputs.image-with-tag }} | jq '.Docker.config.Labels."org.opencontainers.image.description"'
|
20
.github/workflows/link_check.yml
vendored
Normal file
20
.github/workflows/link_check.yml
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
name: Link checker
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- '**.md'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '**.md'
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
markdown-link-check:
|
||||||
|
name: Check links in markdown
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: gaurav-nelson/github-action-markdown-link-check@v1
|
||||||
|
with:
|
||||||
|
use-verbose-mode: true
|
229
.github/workflows/multiarch.yml
vendored
Normal file
229
.github/workflows/multiarch.yml
vendored
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
name: Multiarch build
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
|
env:
|
||||||
|
PROJECT_DIR: spring-petclinic
|
||||||
|
MVN_REPO_DIR: ~/.m2/repository
|
||||||
|
IMAGE_TAG: latest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-multiarch-containerfile:
|
||||||
|
name: Build multi-architecture image using Containerfile
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: hello-world-multiarch
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
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_multiarch
|
||||||
|
uses: ./buildah-build/
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tags: latest v1
|
||||||
|
archs: amd64 # Single arch testcase
|
||||||
|
containerfiles: |
|
||||||
|
./Containerfile
|
||||||
|
|
||||||
|
- name: Echo Outputs
|
||||||
|
run: |
|
||||||
|
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_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_multiarch.outputs.image }}:${{ env.IMAGE_TAG }}
|
||||||
|
|
||||||
|
build-multiplatform-containerfile:
|
||||||
|
name: Build multi-platform image using Containerfile
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: hello-world-multiplatform
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
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.16
|
||||||
|
|
||||||
|
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 }}
|
||||||
|
platforms: linux/amd64, linux/ppc64le
|
||||||
|
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 manifest
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
buildah manifest inspect ${{ steps.build_image_multiplatform.outputs.image }}:${{ env.IMAGE_TAG }}
|
||||||
|
|
||||||
|
- name: Run image
|
||||||
|
run: |
|
||||||
|
podman run --rm ${{ steps.build_image_multiplatform.outputs.image }}:${{ env.IMAGE_TAG }}
|
||||||
|
|
||||||
|
build-multiarch-scratch:
|
||||||
|
name: Build multi-architecture image from scratch
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: spring-petclinic-multiarch
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# Checkout buildah action github repository
|
||||||
|
- name: Checkout Buildah action
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
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
|
||||||
|
|
||||||
|
# Checkout spring-petclinic github repository
|
||||||
|
- name: Checkout spring-petclinic project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: "spring-projects/spring-petclinic"
|
||||||
|
path: ${{ env.PROJECT_DIR }}
|
||||||
|
|
||||||
|
# Setup java.
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '17'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
# Run maven to build the project
|
||||||
|
- name: Maven
|
||||||
|
working-directory: ${{ env.PROJECT_DIR }}
|
||||||
|
run: |
|
||||||
|
mvn package -ntp -B
|
||||||
|
|
||||||
|
- name: Build Image
|
||||||
|
id: build_image_multiarch
|
||||||
|
uses: ./buildah-build/
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tags: ${{ env.IMAGE_TAG }}
|
||||||
|
base-image: 'registry.access.redhat.com/openjdk/openjdk-11-rhel7'
|
||||||
|
archs: amd64, i386, ppc64le
|
||||||
|
# To avoid hardcoding a particular version of the binary.
|
||||||
|
content: |
|
||||||
|
./spring-petclinic/target/spring-petclinic-*.jar
|
||||||
|
entrypoint: |
|
||||||
|
java
|
||||||
|
-jar
|
||||||
|
spring-petclinic-*.jar
|
||||||
|
port: 8080
|
||||||
|
workdir: "."
|
||||||
|
|
||||||
|
- name: Echo Outputs
|
||||||
|
run: |
|
||||||
|
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 manifest
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
buildah manifest inspect ${{ steps.build_image_multiarch.outputs.image }}:${{ env.IMAGE_TAG }}
|
|
@ -1,76 +1,86 @@
|
||||||
# This workflow will perform a test whenever there
|
# This workflow will perform a test whenever there
|
||||||
# is some change in code done to ensure that the changes
|
# is some change in code done to ensure that the changes
|
||||||
# are not buggy and we are getting the desired output.
|
# are not buggy and we are getting the desired output.
|
||||||
name: Test Build
|
name: Build
|
||||||
on: [push, pull_request, workflow_dispatch]
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
env:
|
env:
|
||||||
TEST_REPO: spring-petclinic
|
PROJECT_DIR: spring-petclinic
|
||||||
IMAGE_NAME: spring-petclinic
|
IMAGE_NAME: spring-petclinic
|
||||||
|
MVN_REPO_DIR: ~/.m2/repository
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build image using Buildah
|
name: Build image using Buildah
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
install_latest: [ true, false ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# Fetch name of the Forked Repository with Branch
|
|
||||||
# if workflow is triggered from pull request
|
|
||||||
- name: Fetch PR head repo and branch name
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
run: |
|
|
||||||
HEAD_REPO_NAME=$(jq -r '.pull_request.head.repo.full_name' "$GITHUB_EVENT_PATH")
|
|
||||||
echo "PR head repo: $HEAD_REPO_NAME"
|
|
||||||
echo "repo=$HEAD_REPO_NAME" >> $GITHUB_ENV
|
|
||||||
echo "branch=$GITHUB_HEAD_REF" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# Extract repository name with branch
|
|
||||||
- name: Fetch Repository name with branch
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "repo=$GITHUB_REPOSITORY" >> $GITHUB_ENV
|
|
||||||
echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# Checkout buildah action github repository
|
# Checkout buildah action github repository
|
||||||
- name: Checkout Buildah action
|
- name: Checkout Buildah action
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: ${{ env.repo }}
|
|
||||||
ref: ${{ env.branch }}
|
|
||||||
path: "buildah-build"
|
path: "buildah-build"
|
||||||
|
|
||||||
|
- name: Install latest buildah
|
||||||
|
if: matrix.install_latest
|
||||||
|
run: |
|
||||||
|
bash buildah-build/.github/install_latest_buildah.sh
|
||||||
|
|
||||||
# Checkout spring-petclinic github repository
|
# Checkout spring-petclinic github repository
|
||||||
- name: Checkout spring-petclinic project
|
- name: Checkout spring-petclinic project
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: "spring-projects/spring-petclinic"
|
repository: "spring-projects/spring-petclinic"
|
||||||
path: ${{ env.TEST_REPO }}
|
path: ${{ env.PROJECT_DIR }}
|
||||||
|
|
||||||
# Setup java.
|
# Setup java.
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
distribution: 'temurin'
|
||||||
|
java-version: '17'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
# Run maven to build the project
|
# Run maven to build the project
|
||||||
- name: Maven
|
- name: Maven
|
||||||
working-directory: ${{ env.TEST_REPO }}
|
working-directory: ${{ env.PROJECT_DIR }}
|
||||||
run: |
|
run: |
|
||||||
mvn package -ntp -B
|
mvn package -ntp -B
|
||||||
|
|
||||||
# Build image using Buildah action
|
# Build image using Buildah action
|
||||||
- name: Build Image
|
- name: Build Image
|
||||||
|
id: build_image
|
||||||
uses: ./buildah-build/
|
uses: ./buildah-build/
|
||||||
with:
|
with:
|
||||||
image: ${{ env.IMAGE_NAME }}
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tags: 'latest ${{ github.sha }}'
|
||||||
|
base-image: 'registry.access.redhat.com/openjdk/openjdk-11-rhel7'
|
||||||
# To avoid hardcoding a particular version of the binary.
|
# To avoid hardcoding a particular version of the binary.
|
||||||
content: |
|
content: |
|
||||||
./spring-petclinic/target/spring-petclinic-*.jar
|
./spring-petclinic/target/spring-petclinic-*.jar
|
||||||
entrypoint: |
|
entrypoint: |
|
||||||
java
|
java
|
||||||
-jar
|
-jar
|
||||||
spring-petclinic-*.BUILD-SNAPSHOT.jar
|
spring-petclinic-*.jar
|
||||||
port: 8080
|
port: 8080
|
||||||
|
arch: amd64
|
||||||
|
workdir: "."
|
||||||
|
|
||||||
|
- 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 }}"
|
||||||
|
|
||||||
# Check if image is build
|
# Check if image is build
|
||||||
- name: Check images created
|
- name: Check images created
|
36
.github/workflows/security_scan.yml
vendored
Normal file
36
.github/workflows/security_scan.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
name: Vulnerability Scan with CRDA
|
||||||
|
on:
|
||||||
|
# push:
|
||||||
|
workflow_dispatch:
|
||||||
|
# pull_request_target:
|
||||||
|
# types: [ assigned, opened, synchronize, reopened, labeled, edited ]
|
||||||
|
# schedule:
|
||||||
|
# - cron: '0 0 * * *' # every day at midnight
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
crda-scan:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
name: Scan project vulnerability with CRDA
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install CRDA
|
||||||
|
uses: redhat-actions/openshift-tools-installer@v1
|
||||||
|
with:
|
||||||
|
source: github
|
||||||
|
github_pat: ${{ github.token }}
|
||||||
|
crda: "latest"
|
||||||
|
|
||||||
|
- name: CRDA Scan
|
||||||
|
id: scan
|
||||||
|
uses: redhat-actions/crda@v1
|
||||||
|
with:
|
||||||
|
crda_key: ${{ secrets.CRDA_KEY }}
|
||||||
|
fail_on: never
|
18
.github/workflows/verify-bundle.yml
vendored
18
.github/workflows/verify-bundle.yml
vendored
|
@ -1,18 +0,0 @@
|
||||||
name: Verify Bundle
|
|
||||||
on: [ push, pull_request ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
verify-bundle:
|
|
||||||
name: Verify Distribution Bundle
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Check Distribution
|
|
||||||
uses: tetchel/bundle-verifier-action@v0.0.2
|
|
||||||
with:
|
|
||||||
bundle_file: dist/index.js
|
|
||||||
bundle_command: "npm run bundle"
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
out/
|
out/
|
||||||
|
.idea/
|
||||||
|
|
79
CHANGELOG.md
Normal file
79
CHANGELOG.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# buildah-build Changelog
|
||||||
|
|
||||||
|
## v2.13
|
||||||
|
- Update action to run on Node20. https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/
|
||||||
|
|
||||||
|
## v2.12
|
||||||
|
- Forcibly remove existing manifest before creating a new one. [#103](https://github.com/redhat-actions/buildah-build/pull/103)
|
||||||
|
|
||||||
|
## v2.11
|
||||||
|
- Update action to run on Node16. https://github.blog/changelog/2022-05-20-actions-can-now-run-in-a-node-js-16-runtime/
|
||||||
|
|
||||||
|
## v2.10
|
||||||
|
- Make image and tag in lowercase, if found in uppercase. https://github.com/redhat-actions/buildah-build/issues/89
|
||||||
|
- Add `--tls-verify` and `extra-args` input for `buildah from` command. https://github.com/redhat-actions/buildah-build/issues/92
|
||||||
|
- Remove kubic packages from test workflows. https://github.com/redhat-actions/buildah-build/issues/93
|
||||||
|
|
||||||
|
## v2.9
|
||||||
|
- Add support for multiple archs and platforms.
|
||||||
|
- Allow building image manifest if multi arch or platform is provided.
|
||||||
|
|
||||||
|
## v2.8
|
||||||
|
- Allow fully qualified image names in `tags` input, for compatibility with [docker/metadata-action`](https://github.com/docker/metadata-action). [#74](https://github.com/redhat-actions/buildah-build/issues/74)
|
||||||
|
- Support for `--platform` argument [#65](https://github.com/redhat-actions/buildah-build/issues/65)
|
||||||
|
|
||||||
|
## v2.7
|
||||||
|
- Add output `image-with-tag` which provides image name and its corresponding first tag present.
|
||||||
|
- Replace input `dockerfiles` with `containerfiles`. Input `dockerfiles` will be present as alias of `containerfiles`.
|
||||||
|
- Add matrix to install latest buildah. (Internal)
|
||||||
|
|
||||||
|
## v2.6.2
|
||||||
|
- Run `buildah config` command before `buildah copy` command to use `workingDir` for copying
|
||||||
|
|
||||||
|
## v2.6.1
|
||||||
|
- Fix buildah-bud docs link in README
|
||||||
|
|
||||||
|
## v2.6
|
||||||
|
- Rename "archs" input to "arch"
|
||||||
|
- Improve documentation for multi-architecture builds
|
||||||
|
|
||||||
|
## v2.5.2
|
||||||
|
- Update README for multi-architecture builds
|
||||||
|
|
||||||
|
## v2.5.1
|
||||||
|
- Fix README typo
|
||||||
|
|
||||||
|
## v2.5
|
||||||
|
- Add input `extra-args` to pass extra args to buildah bud for build image using dockerfile [2f7f68e](https://github.com/redhat-actions/buildah-build/commit/2f7f68ec840393890fca056f55d0140cf909c46d)
|
||||||
|
|
||||||
|
## v2.4.1
|
||||||
|
- Update README to point to podman-login action [0c92abf](https://github.com/redhat-actions/buildah-build/commit/0c92abf30679c2b1b5329bacce9abbc3d3d94496)
|
||||||
|
|
||||||
|
## v2.4
|
||||||
|
- Fix buildah issue of using `overlay` as storage driver [6dbeb7e](https://github.com/redhat-actions/buildah-build/commit/6dbeb7e1f64c961b642625d54e551d296dafdd30)
|
||||||
|
|
||||||
|
## v2.3.1
|
||||||
|
- Fix issue of workDir not being used in the code [65f18d4](https://github.com/redhat-actions/buildah-build/commit/65f18d484c4278f73a530e03bfe9661649dc7615)
|
||||||
|
|
||||||
|
## v2.3
|
||||||
|
- Add Layers input for build using dockerfile [3196e5a](https://github.com/redhat-actions/buildah-build/commit/3196e5acb5dc5db144b00aeddd723de3d8604506)
|
||||||
|
|
||||||
|
## v2.2.1
|
||||||
|
- Add note about multi architecture(s) image built support [1f7c249](https://github.com/redhat-actions/buildah-build/commit/1f7c2499306a8def9affb31cc7d43934bb87907d)
|
||||||
|
|
||||||
|
## v2.2
|
||||||
|
- Add output message if tags is not provided [76570bc](https://github.com/redhat-actions/buildah-build/commit/76570bc65b73d4072c85224b6f6e2fef3cf2b24b)
|
||||||
|
|
||||||
|
## v2.1
|
||||||
|
- Add `archs` input to allow building images for custom architectures [803a141](https://github.com/redhat-actions/buildah-build/commit/803a1413e7c2a594cbfb6680bca358bfdbe36745)
|
||||||
|
|
||||||
|
## v2
|
||||||
|
- Rename `tag` input to `tags`, to allow you to build multiple tags of the same image
|
||||||
|
- Add outputs `image` and `tags`, which output the image name and all tags of the image that was created [88e0085](https://github.com/redhat-actions/buildah-build/commit/88e00855444b8d915b900c8251f48c291ccedce5)
|
||||||
|
- (Internal) Add CI checks to the action that includes ESlint, bundle verifier and IO checker [20a8e62](https://github.com/redhat-actions/buildah-build/commit/20a8e62ce082870ed0ff1ee141bb98ae95432501)
|
||||||
|
|
||||||
|
## v1
|
||||||
|
- Initial marketplace release
|
||||||
|
|
||||||
|
## v0.1
|
||||||
|
- Initial pre-release
|
270
README.md
270
README.md
|
@ -1,135 +1,123 @@
|
||||||
# buildah-build
|
# buildah-build
|
||||||
[](https://github.com/redhat-actions/buildah-build/actions?query=workflow%3A%22Test+Build%22)
|
[](https://github.com/redhat-actions/buildah-build/actions?query=workflow%3A%22CI+checks%22)
|
||||||
[](https://github.com/redhat-actions/buildah-build/actions?query=workflow%3A%22Verify+Bundle%22)
|
[](https://github.com/redhat-actions/buildah-build/actions?query=workflow%3ABuild)
|
||||||
|
[](https://github.com/redhat-actions/buildah-build/actions?query=workflow%3A%22Build+from+containerfile%22)
|
||||||
|
[](https://github.com/redhat-actions/buildah-build/actions?query=workflow%3A%22Link+checker%22)
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
[](https://github.com/redhat-actions/buildah-build/tags)
|
[](https://github.com/redhat-actions/buildah-build/tags)
|
||||||
[](./LICENSE)
|
[](./LICENSE)
|
||||||
[](./dist)
|
[](./dist)
|
||||||
|
|
||||||
Buildah is a GitHub Action for building Docker and Kubernetes-compatible images quickly and easily.
|
Buildah Build is a GitHub Action for building Docker and Kubernetes-compatible images quickly and easily.
|
||||||
|
|
||||||
Buildah only works on Linux. GitHub's [Ubuntu Environments](https://github.com/actions/virtual-environments#available-environments) (`ubuntu-18.04` and newer) come with buildah installed. If you are not using these environments, or if you want to use a different version, you must first [install buildah](https://github.com/containers/buildah/blob/master/install.md).
|
[Buildah](https://github.com/containers/buildah/tree/master/docs) only works on Linux. GitHub's [Ubuntu Environments](https://github.com/actions/virtual-environments#available-environments) (`ubuntu-18.04` and newer) come with buildah installed. If you are not using these environments, or if you want to use a different version, you must first [install buildah](https://github.com/containers/buildah/blob/master/install.md).
|
||||||
|
|
||||||
After building your image, use [push-to-registry](https://github.com/redhat-actions/push-to-registry) to push the image and make it pullable.
|
After building your image, use [push-to-registry](https://github.com/redhat-actions/push-to-registry) to push the image and make it pullable.
|
||||||
|
|
||||||
|
<a id="action-inputs"></a>
|
||||||
|
|
||||||
## Action Inputs
|
## Action Inputs
|
||||||
|
|
||||||
<table>
|
<a id="dockerfile-build-inputs"></a>
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Input</th>
|
|
||||||
<th>Required</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tr>
|
### [Inputs for build from containerfile](https://github.com/containers/buildah/blob/main/docs/buildah-build.1.md)
|
||||||
<td>image</td>
|
|
||||||
<td>Yes</td>
|
|
||||||
<td>Name to give the output image.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
| Input Name | Description | Default |
|
||||||
<td>tag</td>
|
| ---------- | ----------- | ------- |
|
||||||
<td>No</td>
|
| archs | Label the image with this architecture, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) for more information. For multiple architectures, seperate them by a comma | None (host architecture)
|
||||||
<td>
|
| platforms | Label the image with this platform, instead of defaulting to the host platform. Refer to [Multi arch builds](#multi-arch-builds) for more information. For multiple platforms, seperate them by a comma | None (host platform)
|
||||||
Tag to give to the output image.<br>
|
| 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
|
||||||
Default: <code>latest</code>
|
| context | Path to directory to use as the build context. | `.`
|
||||||
</td>
|
| containerfiles\* | The list of Containerfile paths to perform a build using docker instructions. Separate filenames by newline. | **Required**
|
||||||
</tr>
|
| extra-args | Extra args to be passed to `buildah bud`. Separate arguments by newline. Do not use quotes. | None
|
||||||
|
| image | Name to give to the output image. Refer to the [Image and Tag Inputs](#image-tag-inputs) section. | **Required** - unless all `tags` include image name
|
||||||
|
| layers | Set to true to cache intermediate layers during the build process. | None
|
||||||
|
| oci | Build the image using the OCI metadata format, instead of the Docker format. | `false`
|
||||||
|
| tags | One or more tags to give the new image. Separate by whitespace. Refer to the [Image and Tag Inputs](#image-tag-inputs) section. | `latest`
|
||||||
|
| labels | One or more labels to give the new image. Separate by newline. | None
|
||||||
|
| tls-verify | Require HTTPS and verify certificates when accessing the registry. Set to `false` to skip the verification | `true`
|
||||||
|
|
||||||
<tr>
|
> \* The `containerfiles` input was previously `dockerfiles`. Refer to [this issue](https://github.com/redhat-actions/buildah-build/issues/57).
|
||||||
<td>base-image</td>
|
|
||||||
<td>No</td>
|
|
||||||
<td>The base image to use to create the initial container. If not specified, the action will try to pick one automatically. (N.B: At this time the action is only able to auto select Java base image)</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
<a id="scratch-build-inputs"></a>
|
||||||
<td>dockerfiles</td>
|
|
||||||
<td>No</td>
|
|
||||||
<td>The list of Dockerfile paths to perform a build using docker instructions. This is a multiline input to allow multiple Dockerfiles.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
### [Inputs for build without containerfile](https://github.com/containers/buildah/blob/main/docs/buildah-config.1.md)
|
||||||
<td>oci</td>
|
|
||||||
<td>No</td>
|
|
||||||
<td>
|
|
||||||
Build the image using the OCI format, instead of the Docker format.<br>
|
|
||||||
By default, this is <code>false</code>, because images built using the OCI format have <a href="https://github.com/docker/hub-feedback/issues/1871">issues</a> when published to Dockerhub.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
| Input Name | Description | Default |
|
||||||
<td>context</td>
|
| ---------- | ----------- | ------- |
|
||||||
<td>No</td>
|
| archs | Label the image with this architecture, instead of defaulting to the host architecture. Refer to [Multi arch builds](#multi-arch-builds) for more information. For multiple architectures, seperate them by a comma | None (host architecture)
|
||||||
<td>Path to directory to use as the build context.<br>
|
| base-image | The base image to use for the container. | **Required**
|
||||||
Default: <code>.</code></td>
|
| 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
|
||||||
</tr>
|
| entrypoint | The entry point to set for the container. Separate arguments by newline. | None
|
||||||
|
| envs | The environment variables to be set when running the container. Separate key=value pairs by newline. | None
|
||||||
|
| image | Name to give to the output image. Refer to the [Image and Tag Inputs](#image-tag-inputs) section. | **Required** - unless all tags include image name
|
||||||
|
| oci | Build the image using the OCI metadata format, instead of the Docker format. | `false`
|
||||||
|
| port | The port to expose when running the container. | None
|
||||||
|
| tags | One or more tags to give the new image. Separate by whitespace. Refer to the [Image and Tag Inputs](#image-tag-inputs) section. | `latest`
|
||||||
|
| labels | One or more labels to give the new image. Separate by newline. | None
|
||||||
|
| workdir | The working directory to use within the container. | None
|
||||||
|
| extra-args | Extra args to be passed to `buildah from`. Separate arguments by newline. Do not use quotes. | None
|
||||||
|
| tls-verify | Require HTTPS and verify certificates when accessing the registry. Set to `false` to skip the verification. This will be used with `buildah from` command. | `true`
|
||||||
|
|
||||||
<tr>
|
<a id="image-tag-inputs"></a>
|
||||||
<td>build-args</td>
|
### Image and Tags Inputs
|
||||||
<td>No</td>
|
The `image` and `tags` inputs can be provided in one of two forms.
|
||||||
<td>Build arguments to pass to the Docker build using <code>--build-arg</code>, if using a Dockerfile that requires ARGs.<br>
|
|
||||||
Uses the form <code>arg_name=arg_value</code>, and separate arguments with newlines.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
At least one tag must always be provided in `tags`. Multiple tags are separated by whitespace.
|
||||||
<td>content</td>
|
|
||||||
<td>No</td>
|
|
||||||
<td>The content to copy inside the container to create the final image. This is a multiline input to allow you to copy more than one file/directory.<br>
|
|
||||||
<pre>content: |
|
|
||||||
target/spring-petclinic-2.3.0.BUILD-SNAPSHOT.jar</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
**Option 1**: Provide both `image` and `tags` inputs. The image will be built, and then tagged in the form `${image}:${tag}` for each tag.
|
||||||
<td>entrypoint</td>
|
|
||||||
<td>No</td>
|
|
||||||
<td>The entry point to set for the container. This is a multiline input; split arguments across lines.
|
|
||||||
<pre>entrypoint: |
|
|
||||||
java
|
|
||||||
-jar
|
|
||||||
spring-petclinic-2.3.0.BUILD-SNAPSHOT.jar</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
For example:
|
||||||
<td>port</td>
|
```yaml
|
||||||
<td>No</td>
|
image: quay.io/my-namespace/my-image
|
||||||
<td>The port to expose when running the container.</td>
|
tags: v1 v1.0.0
|
||||||
</tr>
|
```
|
||||||
|
will create the image and apply two tags: `quay.io/my-namespace/my-image:v1` and `quay.io/my-namespace/my-image:v1.0.0`.
|
||||||
|
|
||||||
<tr>
|
**Option 2**: Provide only the `tags` input, including the image name in each tag. The image will be built, and then tagged with each `tag`. In this case, the `image` input is ignored.
|
||||||
<td>workdir</td>
|
|
||||||
<td>No</td>
|
|
||||||
<td>The working directory to use within the container.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
For example:
|
||||||
<td>envs</td>
|
```yaml
|
||||||
<td>No</td>
|
# 'image' input is not set
|
||||||
<td>The environment variables to be set when running the container. This is a multiline input to add multiple environment variables.<br>
|
tags: quay.io/my-namespace/my-image:v1 quay.io/my-namespace/my-image:v1.0.0
|
||||||
<pre>
|
```
|
||||||
envs: |
|
will also apply two tags: `quay.io/my-namespace/my-image:v1` and `quay.io/my-namespace/my-image:v1.0.0`.
|
||||||
GOPATH=/root/buildah/go</pre>
|
|
||||||
</td>
|
If the `tags` input does not have image names in the `${name}:${tag}` form, then the `image` input must be set.
|
||||||
</tr>
|
|
||||||
</table>
|
<a id="outputs"></a>
|
||||||
|
|
||||||
|
## Action Outputs
|
||||||
|
|
||||||
|
`image`: The name of the image as it was input.<br>
|
||||||
|
`tags`: A space-separated list of the tags that were applied to the new image.<br>
|
||||||
|
`image-with-tag`: The name of the image, tagged with the first tag.<br>
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
``` yml
|
||||||
|
image: "spring-image"
|
||||||
|
tags: "latest ${{ github.sha }}"
|
||||||
|
image-with-tag: "spring-image:latest"
|
||||||
|
```
|
||||||
|
|
||||||
|
<a id="build-types"></a>
|
||||||
|
|
||||||
## Build Types
|
## Build Types
|
||||||
|
|
||||||
You can configure the `buildah` action to build your image using one or more Dockerfiles, or none at all.
|
You can configure the `buildah` action to build your image using one or more Containerfiles, or none at all.
|
||||||
|
|
||||||
### Building using Dockerfiles
|
<a id="build-using-dockerfile"></a>
|
||||||
|
|
||||||
If you have been building your images with an existing Dockerfile, `buildah` can reuse your Dockerfile.
|
### Building using Containerfiles
|
||||||
|
|
||||||
In this case the inputs needed are `image` and `dockerfiles`. `tag` is also recommended. If your Dockerfile requires ARGs, these can be passed using `build-arg`.
|
If you have been building your images with an existing Containerfile, `buildah` can reuse your Containerfile.
|
||||||
|
|
||||||
|
In this case the inputs needed are `image` and `containerfiles`. `tag` is also recommended. If your Containerfile requires ARGs, these can be passed using `build-arg`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: Build Image using Dockerfile
|
name: Build Image using Containerfile
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -138,32 +126,33 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Buildah Action
|
- name: Buildah Action
|
||||||
uses: redhat-actions/buildah-build@v1
|
uses: redhat-actions/buildah-build@v2
|
||||||
with:
|
with:
|
||||||
image: my-new-image
|
image: my-new-image
|
||||||
tag: v1
|
tags: v1 ${{ github.sha }}
|
||||||
dockerfiles: |
|
containerfiles: |
|
||||||
./Dockerfile
|
./Containerfile
|
||||||
build-args: |
|
build-args: |
|
||||||
some_arg=some_value
|
some_arg=some_value
|
||||||
```
|
```
|
||||||
|
<a id="scratch-build"></a>
|
||||||
|
|
||||||
### Building without a Dockerfile
|
### Building without a Containerfile
|
||||||
|
|
||||||
Building without a Dockerfile requires additional inputs, that would normally be specified in the Dockerfile.
|
Building without a Containerfile requires additional inputs, that would normally be specified in the Containerfile.
|
||||||
|
|
||||||
Do not set `dockerfiles` if you are doing a build from scratch. Otherwise those Dockerfiles will be used, and the inputs below will be ignored.
|
Do not set `containerfiles` if you are doing a build from scratch. Otherwise those Containerfiles will be used, and the inputs below will be ignored.
|
||||||
|
|
||||||
- An output `image` name and usually a `tag`.
|
- An output `image` name and usually a `tag`.
|
||||||
- `base-image`
|
- `base-image`
|
||||||
- In a Dockerfile, this would be the `FROM` directive.
|
- In a Containerfile, this would be the `FROM` directive.
|
||||||
- `content` to copy into the new image
|
- `content` to copy into the new image
|
||||||
- In a Dockerfile, this would be `COPY` directives.
|
- In a Containerfile, this would be `COPY` directives.
|
||||||
- `entrypoint` so the container knows what command to run.
|
- `entrypoint` so the container knows what command to run.
|
||||||
- In a Dockerfile, this would be the `ENTRYPOINT`.
|
- In a Containerfile, this would be the `ENTRYPOINT`.
|
||||||
- All other optional configuration inputs, such as `port`, `envs`, and `workdir`.
|
- All other optional configuration inputs, such as `port`, `envs`, and `workdir`.
|
||||||
|
|
||||||
Example of building a Spring Boot Java app image:
|
Example of building a Spring Boot Java app image:
|
||||||
|
@ -173,34 +162,75 @@ on: [push]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-image:
|
build-image:
|
||||||
name: Build image
|
name: Build image without Containerfile
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- run: mvn package
|
- run: mvn package
|
||||||
|
|
||||||
- name: Build Image
|
- name: Build Image
|
||||||
uses: redhat-actions/buildah-build@v1
|
uses: redhat-actions/buildah-build@v2
|
||||||
with:
|
with:
|
||||||
base-image: docker.io/fabric8/java-alpine-openjdk11-jre
|
base-image: docker.io/fabric8/java-alpine-openjdk11-jre
|
||||||
image: my-new-image
|
image: my-new-image
|
||||||
tag: v1
|
tags: v1
|
||||||
content: |
|
content: |
|
||||||
target/spring-petclinic-2.3.0.BUILD-SNAPSHOT.jar
|
target/spring-petclinic-2.3.0.BUILD-SNAPSHOT.jar
|
||||||
entrypoint: java -jar spring-petclinic-2.3.0.BUILD-SNAPSHOT.jar
|
entrypoint: java -jar spring-petclinic-2.3.0.BUILD-SNAPSHOT.jar
|
||||||
port: 8080
|
port: 8080
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
<a id="multi-arch-builds"></a>
|
||||||
|
|
||||||
This is an open source project open to anyone. This project welcomes contributions and suggestions!
|
## Multi arch builds
|
||||||
|
|
||||||
## Feedback & Questions
|
Refer to the [multi-arch example](./.github/workflows/multiarch.yml).
|
||||||
|
|
||||||
If you discover an issue please file a bug in [GitHub issues](https://github.com/redhat-actions/buildah/issues) and we will fix it as soon as possible.
|
### Emulating RUN instructions
|
||||||
|
|
||||||
## License
|
Cross-architecture builds from containerfiles containing `RUN` instructions require `qemu-user-static` emulation registered in the Linux kernel.
|
||||||
|
|
||||||
MIT, See [LICENSE](https://github.com/redhat-actions/buildah/blob/main/LICENSE.md) for more information.
|
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
|
||||||
|
```
|
||||||
|
This registration remains active until the host reboots.
|
||||||
|
|
||||||
|
### The `archs` and `platforms` inputs
|
||||||
|
|
||||||
|
The `archs` and `platforms` 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).
|
||||||
|
|
||||||
|
### Creating a Multi-Arch Image List
|
||||||
|
|
||||||
|
Input `archs` and `platforms` is provided to build the multi architecture images. If one of these input is provided with the multiple archs or platforms then a [manifest](https://github.com/containers/buildah/blob/main/docs/buildah-manifest.1.md) is built with the multiple architecture images. Name of the manifest is taken from the inputs `image` and `tags`.
|
||||||
|
Incase multiple tags are provided then multiple manifest is created based on the provided tags.
|
||||||
|
|
||||||
|
Use the `archs` and `platforms` inputs to build multi-architecture images. The name of the manifest is determined by the image and tags inputs.
|
||||||
|
|
||||||
|
If multiple tags are provided, multiple equivalent manifests will be created with the given tags.
|
||||||
|
|
||||||
|
[`push-to-registry`](https://github.com/redhat-actions/push-to-registry) action can be used to push the generated image manifest.
|
||||||
|
|
||||||
|
## Build with docker/metadata-action
|
||||||
|
|
||||||
|
Refer to the [docker/metadata-action example](./.github/workflows/docker_metadata_action.yml).
|
||||||
|
|
||||||
|
## Using private images
|
||||||
|
|
||||||
|
If your build references a private image, run [**podman-login**](https://github.com/redhat-actions/podman-login) in a step before this action so you can pull the image.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Log in to Red Hat Registry
|
||||||
|
uses: redhat-actions/podman-login@v1
|
||||||
|
with:
|
||||||
|
registry: registry.redhat.io
|
||||||
|
username: ${{ secrets.REGISTRY_REDHAT_IO_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_REDHAT_IO_PASSWORD }}
|
||||||
|
```
|
||||||
|
|
61
action.yml
61
action.yml
|
@ -1,5 +1,5 @@
|
||||||
name: 'Buildah Build'
|
name: 'Buildah Build'
|
||||||
description: 'Build a container image, with or without a Dockerfile'
|
description: 'Build a container image, with or without a Containerfile'
|
||||||
author: 'Red Hat'
|
author: 'Red Hat'
|
||||||
branding:
|
branding:
|
||||||
icon: circle
|
icon: circle
|
||||||
|
@ -7,16 +7,22 @@ branding:
|
||||||
inputs:
|
inputs:
|
||||||
image:
|
image:
|
||||||
description: 'The name (reference) of the image to build'
|
description: 'The name (reference) of the image to build'
|
||||||
required: true
|
required: false
|
||||||
tag:
|
tags:
|
||||||
description: 'The tag of the image to build'
|
description: 'The tags of the image to build. For multiple tags, seperate by whitespace. For example, "latest v1".'
|
||||||
required: false
|
required: false
|
||||||
default: latest
|
default: latest
|
||||||
|
labels:
|
||||||
|
description: 'The labels of the image to build. Seperate by newline. For example, "io.containers.capabilities=sys_admin,mknod".'
|
||||||
|
required: false
|
||||||
base-image:
|
base-image:
|
||||||
description: 'The base image to use to create a new container image'
|
description: 'The base image to use to create a new container image'
|
||||||
required: false
|
required: false
|
||||||
|
containerfiles:
|
||||||
|
description: 'List of Containerfile paths (eg: ./Containerfile)'
|
||||||
|
required: false
|
||||||
dockerfiles:
|
dockerfiles:
|
||||||
description: 'List of Dockerfile paths (eg: ./Dockerfile)'
|
description: 'Alias for "containerfiles". "containerfiles" takes precedence if both are set.'
|
||||||
required: false
|
required: false
|
||||||
context:
|
context:
|
||||||
description: 'Path of the directory to use as context (default: .)'
|
description: 'Path of the directory to use as context (default: .)'
|
||||||
|
@ -28,6 +34,9 @@ inputs:
|
||||||
entrypoint:
|
entrypoint:
|
||||||
description: 'The entry point to set for containers based on image'
|
description: 'The entry point to set for containers based on image'
|
||||||
required: false
|
required: false
|
||||||
|
layers:
|
||||||
|
description: 'Set to true to cache intermediate layers during build process'
|
||||||
|
required: false
|
||||||
port:
|
port:
|
||||||
description: 'The port to expose when running containers based on image'
|
description: 'The port to expose when running containers based on image'
|
||||||
required: false
|
required: false
|
||||||
|
@ -38,12 +47,48 @@ inputs:
|
||||||
description: 'List of environment variables to be set when running containers based on image'
|
description: 'List of environment variables to be set when running containers based on image'
|
||||||
required: false
|
required: false
|
||||||
build-args:
|
build-args:
|
||||||
description: 'List of --build-args to pass to buildah.'
|
description: 'List of --build-args to pass to buildah'
|
||||||
required: false
|
required: false
|
||||||
oci:
|
oci:
|
||||||
description: 'Set to true to build using the OCI image format instead of the Docker image format.'
|
description: 'Set to true to build using the OCI image format instead of the Docker image format'
|
||||||
default: 'false'
|
default: 'false'
|
||||||
required: false
|
required: false
|
||||||
|
arch:
|
||||||
|
description:
|
||||||
|
'Label the image with this ARCH, instead of defaulting to the host architecture'
|
||||||
|
required: false
|
||||||
|
archs:
|
||||||
|
description: |
|
||||||
|
'Same as input 'arch', use this for multiple architectures.
|
||||||
|
Seperate them by a comma'
|
||||||
|
required: false
|
||||||
|
platform:
|
||||||
|
description: |
|
||||||
|
Label the image with this PLATFORM, instead of defaulting to the host platform.
|
||||||
|
Only supported for containerfile builds.
|
||||||
|
required: false
|
||||||
|
platforms:
|
||||||
|
description: |
|
||||||
|
'Same as input 'platform', use this for multiple platforms.
|
||||||
|
Seperate them by a comma'
|
||||||
|
required: false
|
||||||
|
extra-args:
|
||||||
|
description: |
|
||||||
|
Extra args to be passed to buildah bud and buildah from.
|
||||||
|
Separate arguments by newline. Do not use quotes - @actions/exec will do the quoting for you.
|
||||||
|
required: false
|
||||||
|
tls-verify:
|
||||||
|
description: |
|
||||||
|
Require HTTPS and verify certificates when accessing the registry. Defaults to true.
|
||||||
|
required: false
|
||||||
|
default: 'true'
|
||||||
|
outputs:
|
||||||
|
image:
|
||||||
|
description: 'Name of the image built'
|
||||||
|
tags:
|
||||||
|
description: 'List of the tags that were created, separated by spaces'
|
||||||
|
image-with-tag:
|
||||||
|
description: 'Name of the image tagged with the first tag present'
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node20'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|
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
3
dist/language-image.json
vendored
3
dist/language-image.json
vendored
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"java": "docker.io/fabric8/java-alpine-openjdk11-jre"
|
|
||||||
}
|
|
6622
dist/languages.yaml
vendored
6622
dist/languages.yaml
vendored
File diff suppressed because it is too large
Load diff
3911
dist/sourcemap-register.js
vendored
3911
dist/sourcemap-register.js
vendored
File diff suppressed because one or more lines are too long
11
git-hooks/pre-commit
Executable file
11
git-hooks/pre-commit
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
### Copy this into .git/hooks and overwrite the empty one.
|
||||||
|
### This will ensure the bundle and ins-outs verification checks won't fail for you.
|
||||||
|
|
||||||
|
echo "----- Pre-commit -----"
|
||||||
|
set -ex
|
||||||
|
npx action-io-generator -o src/generated/inputs-outputs.ts
|
||||||
|
npm run lint
|
||||||
|
npm run bundle
|
||||||
|
git add -v dist/ src/generated
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"java": "docker.io/fabric8/java-alpine-openjdk11-jre"
|
|
||||||
}
|
|
4552
package-lock.json
generated
4552
package-lock.json
generated
File diff suppressed because it is too large
Load diff
30
package.json
30
package.json
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "buildah-build",
|
"name": "buildah-build",
|
||||||
"version": "0.0.1",
|
"version": "3.0",
|
||||||
|
"engines": {
|
||||||
|
"node": "20"
|
||||||
|
},
|
||||||
"description": "Action for building OCI-compatible images using buildah",
|
"description": "Action for building OCI-compatible images using buildah",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -10,20 +13,29 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": "tsc -p .",
|
"compile": "tsc -p .",
|
||||||
"bundle": "ncc build src/index.ts --source-map --minify",
|
"bundle": "ncc build src/index.ts --source-map --minify",
|
||||||
"clean": "rm -rf out/ dist/"
|
"clean": "rm -rf out/ dist/",
|
||||||
|
"lint": "eslint . --max-warnings=0",
|
||||||
|
"generate-ios": "npx action-io-generator -w -o ./src/generated/inputs-outputs.ts"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Red Hat",
|
"author": "Red Hat",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "1.10.1",
|
||||||
"@actions/exec": "^1.0.4",
|
"@actions/exec": "1.1.1",
|
||||||
"@actions/io": "^1.0.2",
|
"@actions/io": "1.1.3",
|
||||||
"language-recognizer": "0.0.1"
|
"ini": "4.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^12",
|
"@redhat-actions/action-io-generator": "1.5.0",
|
||||||
"@vercel/ncc": "^0.25.1",
|
"@redhat-actions/eslint-config": "1.3.2",
|
||||||
"typescript": "^4.0.5"
|
"@redhat-actions/tsconfig": "1.2.0",
|
||||||
|
"@types/ini": "1.3.31",
|
||||||
|
"@types/node": "^20.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "6.7.3",
|
||||||
|
"@typescript-eslint/parser": "6.7.3",
|
||||||
|
"@vercel/ncc": "0.38.0",
|
||||||
|
"eslint": "8.50.0",
|
||||||
|
"typescript": "5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
258
src/buildah.ts
258
src/buildah.ts
|
@ -1,111 +1,253 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) Red Hat, Inc. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See LICENSE file in the project root for license information.
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as exec from "@actions/exec";
|
import * as exec from "@actions/exec";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
import CommandResult from "./types";
|
||||||
interface Buildah {
|
import { isStorageDriverOverlay, findFuseOverlayfsPath, getFullImageName } from "./utils";
|
||||||
buildUsingDocker(image: string, context: string, dockerFiles: string[], buildArgs: string[], useOCI: boolean): Promise<CommandResult>;
|
|
||||||
from(baseImage: string): Promise<CommandResult>;
|
|
||||||
copy(container: string, contentToCopy: string[]): Promise<CommandResult>;
|
|
||||||
config(container: string, setting: {}): Promise<CommandResult>;
|
|
||||||
commit(container: string, newImageName: string, useOCI: boolean): Promise<CommandResult>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BuildahConfigSettings {
|
export interface BuildahConfigSettings {
|
||||||
entrypoint?: string[];
|
entrypoint?: string[];
|
||||||
envs?: string[];
|
envs?: string[];
|
||||||
port?: string;
|
port?: string;
|
||||||
workingdir?: string;
|
workingdir?: string;
|
||||||
|
arch?: string;
|
||||||
|
labels?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Buildah {
|
||||||
|
buildUsingDocker(
|
||||||
|
image: string, context: string, containerFiles: string[], buildArgs: string[],
|
||||||
|
useOCI: boolean, labels: string[], layers: string,
|
||||||
|
extraArgs: string[], tlsVerify: boolean, arch?: string, platform?: string,
|
||||||
|
): Promise<CommandResult>;
|
||||||
|
from(baseImage: string, tlsVerify: boolean, extraArgs: string[]): Promise<CommandResult>;
|
||||||
|
config(container: string, setting: BuildahConfigSettings): Promise<CommandResult>;
|
||||||
|
copy(container: string, contentToCopy: string[]): Promise<CommandResult | undefined>;
|
||||||
|
commit(container: string, newImageName: string, useOCI: boolean): Promise<CommandResult>;
|
||||||
|
manifestCreate(manifest: string): Promise<void>;
|
||||||
|
manifestAdd(manifest: string, imageName: string, tags: string[]): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BuildahCli implements Buildah {
|
export class BuildahCli implements Buildah {
|
||||||
|
private readonly executable: string;
|
||||||
|
|
||||||
private executable: string;
|
public storageOptsEnv = "";
|
||||||
|
|
||||||
constructor(executable: string) {
|
constructor(executable: string) {
|
||||||
this.executable = executable;
|
this.executable = executable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getImageFormatOption(useOCI: boolean): string[] {
|
// Checks for storage driver if found "overlay",
|
||||||
return [ '--format', useOCI ? 'oci' : 'docker' ];
|
// then checks if "fuse-overlayfs" is installed.
|
||||||
|
// If yes, add mount program to use "fuse-overlayfs"
|
||||||
|
async setStorageOptsEnv(): Promise<void> {
|
||||||
|
if (await isStorageDriverOverlay()) {
|
||||||
|
const fuseOverlayfsPath = await findFuseOverlayfsPath();
|
||||||
|
if (fuseOverlayfsPath) {
|
||||||
|
core.info(`Overriding storage mount_program with "fuse-overlayfs" in environment`);
|
||||||
|
this.storageOptsEnv = `overlay.mount_program=${fuseOverlayfsPath}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.warning(`"fuse-overlayfs" is not found. Install it before running this action. `
|
||||||
|
+ `For more detail see https://github.com/redhat-actions/buildah-build/issues/45`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info("Storage driver is not 'overlay', so not overriding storage configuration");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildUsingDocker(image: string, context: string, dockerFiles: string[], buildArgs: string[], useOCI: boolean): Promise<CommandResult> {
|
private static getImageFormatOption(useOCI: boolean): string[] {
|
||||||
const args: string[] = ['bud'];
|
return [ "--format", useOCI ? "oci" : "docker" ];
|
||||||
dockerFiles.forEach(file => {
|
}
|
||||||
args.push('-f');
|
|
||||||
|
async buildUsingDocker(
|
||||||
|
image: string,
|
||||||
|
context: string,
|
||||||
|
containerFiles: string[],
|
||||||
|
buildArgs: string[],
|
||||||
|
useOCI: boolean,
|
||||||
|
labels: string[],
|
||||||
|
layers: string,
|
||||||
|
extraArgs: string[],
|
||||||
|
tlsVerify: boolean,
|
||||||
|
arch?: string,
|
||||||
|
platform?: 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);
|
args.push(file);
|
||||||
});
|
});
|
||||||
|
labels.forEach((label) => {
|
||||||
|
args.push("--label");
|
||||||
|
args.push(label);
|
||||||
|
});
|
||||||
buildArgs.forEach((buildArg) => {
|
buildArgs.forEach((buildArg) => {
|
||||||
args.push('--build-arg');
|
args.push("--build-arg");
|
||||||
args.push(buildArg);
|
args.push(buildArg);
|
||||||
});
|
});
|
||||||
args.push(...this.getImageFormatOption(useOCI));
|
args.push(...BuildahCli.getImageFormatOption(useOCI));
|
||||||
args.push('-t');
|
args.push(`--tls-verify=${tlsVerify}`);
|
||||||
|
if (layers) {
|
||||||
|
args.push(`--layers=${layers}`);
|
||||||
|
}
|
||||||
|
if (extraArgs.length > 0) {
|
||||||
|
args.push(...extraArgs);
|
||||||
|
}
|
||||||
|
args.push("-t");
|
||||||
args.push(image);
|
args.push(image);
|
||||||
args.push(context);
|
args.push(context);
|
||||||
return this.execute(args);
|
return this.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
async from(baseImage: string): Promise<CommandResult> {
|
async from(baseImage: string, tlsVerify: boolean, extraArgs: string[]): Promise<CommandResult> {
|
||||||
return this.execute(['from', baseImage]);
|
const args: string[] = [ "from" ];
|
||||||
|
args.push(`--tls-verify=${tlsVerify}`);
|
||||||
|
if (extraArgs.length > 0) {
|
||||||
|
args.push(...extraArgs);
|
||||||
|
}
|
||||||
|
args.push(baseImage);
|
||||||
|
return this.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
async copy(container: string, contentToCopy: string[], path?: string): Promise<CommandResult | undefined> {
|
async copy(container: string, contentToCopy: string[], contentPath?: string): Promise<CommandResult | undefined> {
|
||||||
if (contentToCopy.length === 0) {
|
if (contentToCopy.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
core.debug('copy');
|
core.debug("copy");
|
||||||
core.debug(container);
|
core.debug(container);
|
||||||
for (const content of contentToCopy) {
|
core.debug("content: " + contentToCopy.join(" "));
|
||||||
const args: string[] = ["copy", container, content];
|
if (contentToCopy.length > 0) {
|
||||||
if (path) {
|
const args: string[] = [ "copy", container ].concat(contentToCopy);
|
||||||
args.push(path);
|
if (contentPath) {
|
||||||
|
args.push(contentPath);
|
||||||
}
|
}
|
||||||
return this.execute(args);
|
return this.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
async config(container: string, settings: BuildahConfigSettings): Promise<CommandResult> {
|
async config(container: string, settings: BuildahConfigSettings): Promise<CommandResult> {
|
||||||
core.debug('config');
|
core.debug("config");
|
||||||
core.debug(container);
|
core.debug(container);
|
||||||
const args: string[] = ['config'];
|
const args: string[] = [ "config" ];
|
||||||
if (settings.entrypoint) {
|
if (settings.entrypoint) {
|
||||||
args.push('--entrypoint');
|
args.push("--entrypoint");
|
||||||
args.push(this.convertArrayToStringArg(settings.entrypoint));
|
args.push(BuildahCli.convertArrayToStringArg(settings.entrypoint));
|
||||||
}
|
}
|
||||||
if (settings.port) {
|
if (settings.port) {
|
||||||
args.push('--port');
|
args.push("--port");
|
||||||
args.push(settings.port);
|
args.push(settings.port);
|
||||||
}
|
}
|
||||||
if (settings.envs) {
|
if (settings.envs) {
|
||||||
settings.envs.forEach((env) => {
|
settings.envs.forEach((env) => {
|
||||||
args.push('--env');
|
args.push("--env");
|
||||||
args.push(env);
|
args.push(env);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (settings.arch) {
|
||||||
|
args.push("--arch");
|
||||||
|
args.push(settings.arch);
|
||||||
|
}
|
||||||
|
if (settings.workingdir) {
|
||||||
|
args.push("--workingdir");
|
||||||
|
args.push(settings.workingdir);
|
||||||
|
}
|
||||||
|
if (settings.labels) {
|
||||||
|
settings.labels.forEach((label) => {
|
||||||
|
args.push("--label");
|
||||||
|
args.push(label);
|
||||||
|
});
|
||||||
|
}
|
||||||
args.push(container);
|
args.push(container);
|
||||||
return this.execute(args);
|
return this.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
async commit(container: string, newImageName: string, useOCI: boolean): Promise<CommandResult> {
|
async commit(container: string, newImageName: string, useOCI: boolean): Promise<CommandResult> {
|
||||||
core.debug('commit');
|
core.debug("commit");
|
||||||
core.debug(container);
|
core.debug(container);
|
||||||
core.debug(newImageName);
|
core.debug(newImageName);
|
||||||
const args: string[] = [ 'commit', ...this.getImageFormatOption(useOCI), '--squash', container, newImageName ];
|
const args: string[] = [
|
||||||
|
"commit", ...BuildahCli.getImageFormatOption(useOCI),
|
||||||
|
"--squash", container, newImageName,
|
||||||
|
];
|
||||||
return this.execute(args);
|
return this.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertArrayToStringArg(args: string[]): string {
|
async tag(imageName: string, tags: string[]): Promise<void> {
|
||||||
let arrayAsString = '[';
|
const args: string[] = [ "tag" ];
|
||||||
args.forEach(arg => {
|
const builtImage = [];
|
||||||
|
for (const tag of tags) {
|
||||||
|
args.push(getFullImageName(imageName, tag));
|
||||||
|
builtImage.push(getFullImageName(imageName, tag));
|
||||||
|
}
|
||||||
|
core.info(`Tagging the built image with tags ${tags.toString()}`);
|
||||||
|
await this.execute(args);
|
||||||
|
core.info(`✅ Successfully built image${builtImage.length !== 1 ? "s" : ""} "${builtImage.join(", ")}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfortunately buildah doesn't support the exists command yet
|
||||||
|
// https://github.com/containers/buildah/issues/4217
|
||||||
|
|
||||||
|
// async manifestExists(manifest: string): Promise<boolean> {
|
||||||
|
// const args: string[] = [ "manifest", "exists" ];
|
||||||
|
// args.push(manifest);
|
||||||
|
// const execOptions: exec.ExecOptions = {ignoreReturnCode: true};
|
||||||
|
// core.info(`Checking if manifest ${manifest} exists`);
|
||||||
|
// const {exitCode} = await this.execute(args, execOptions);
|
||||||
|
// return exitCode ? false : true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
async manifestRm(manifest: string): Promise<void> {
|
||||||
|
const execOptions: exec.ExecOptions = { ignoreReturnCode: true };
|
||||||
|
const args: string[] = [ "manifest", "rm" ];
|
||||||
|
args.push(manifest);
|
||||||
|
core.info(`Removing existing manifest ${manifest}`);
|
||||||
|
await this.execute(args, execOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
async manifestCreate(manifest: string): Promise<void> {
|
||||||
|
const args: string[] = [ "manifest", "create" ];
|
||||||
|
args.push(manifest);
|
||||||
|
core.info(`Creating manifest ${manifest}`);
|
||||||
|
await this.execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
async manifestAdd(manifest: string, image: string): Promise<void> {
|
||||||
|
const args: string[] = [ "manifest", "add" ];
|
||||||
|
args.push(manifest);
|
||||||
|
args.push(image);
|
||||||
|
core.info(`Adding image "${image}" to the manifest.`);
|
||||||
|
await this.execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static convertArrayToStringArg(args: string[]): string {
|
||||||
|
let arrayAsString = "[";
|
||||||
|
args.forEach((arg) => {
|
||||||
arrayAsString += `"${arg}",`;
|
arrayAsString += `"${arg}",`;
|
||||||
});
|
});
|
||||||
return `${arrayAsString.slice(0, -1)}]`;
|
return `${arrayAsString.slice(0, -1)}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async execute(args: string[], execOptions: exec.ExecOptions = {}): Promise<CommandResult> {
|
async execute(
|
||||||
|
args: string[],
|
||||||
|
execOptions: exec.ExecOptions & { group?: boolean } = {},
|
||||||
|
): Promise<CommandResult> {
|
||||||
// ghCore.info(`${EXECUTABLE} ${args.join(" ")}`)
|
// ghCore.info(`${EXECUTABLE} ${args.join(" ")}`)
|
||||||
|
|
||||||
let stdout = "";
|
let stdout = "";
|
||||||
|
@ -115,18 +257,39 @@ export class BuildahCli implements Buildah {
|
||||||
finalExecOptions.ignoreReturnCode = true; // the return code is processed below
|
finalExecOptions.ignoreReturnCode = true; // the return code is processed below
|
||||||
|
|
||||||
finalExecOptions.listeners = {
|
finalExecOptions.listeners = {
|
||||||
stdline: (line) => {
|
stdline: (line): void => {
|
||||||
stdout += line + "\n";
|
stdout += line + "\n";
|
||||||
},
|
},
|
||||||
errline: (line) => {
|
errline: (line):void => {
|
||||||
stderr += line + "\n"
|
stderr += line + "\n";
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (execOptions.group) {
|
||||||
|
const groupName = [ this.executable, ...args ].join(" ");
|
||||||
|
core.startGroup(groupName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To solve https://github.com/redhat-actions/buildah-build/issues/45
|
||||||
|
const execEnv: { [key: string] : string } = {};
|
||||||
|
Object.entries(process.env).forEach(([ key, value ]) => {
|
||||||
|
if (value != null) {
|
||||||
|
execEnv[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.storageOptsEnv) {
|
||||||
|
execEnv.STORAGE_OPTS = this.storageOptsEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
finalExecOptions.env = execEnv;
|
||||||
|
|
||||||
|
try {
|
||||||
const exitCode = await exec.exec(this.executable, args, finalExecOptions);
|
const exitCode = await exec.exec(this.executable, args, finalExecOptions);
|
||||||
|
|
||||||
if (execOptions.ignoreReturnCode !== true && exitCode !== 0) {
|
if (execOptions.ignoreReturnCode !== true && exitCode !== 0) {
|
||||||
// Throwing the stderr as part of the Error makes the stderr show up in the action outline, which saves some clicking when debugging.
|
// Throwing the stderr as part of the Error makes the stderr
|
||||||
|
// show up in the action outline, which saves some clicking when debugging.
|
||||||
let error = `${path.basename(this.executable)} exited with code ${exitCode}`;
|
let error = `${path.basename(this.executable)} exited with code ${exitCode}`;
|
||||||
if (stderr) {
|
if (stderr) {
|
||||||
error += `\n${stderr}`;
|
error += `\n${stderr}`;
|
||||||
|
@ -135,7 +298,14 @@ export class BuildahCli implements Buildah {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
exitCode, output: stdout, error: stderr
|
exitCode, output: stdout, error: stderr,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finally {
|
||||||
|
if (execOptions.group) {
|
||||||
|
core.endGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
154
src/generated/inputs-outputs.ts
Normal file
154
src/generated/inputs-outputs.ts
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
// This file was auto-generated by action-io-generator. Do not edit by hand!
|
||||||
|
export enum Inputs {
|
||||||
|
/**
|
||||||
|
* Label the image with this ARCH, instead of defaulting to the host architecture
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
ARCH = "arch",
|
||||||
|
/**
|
||||||
|
* 'Same as input 'arch', use this for multiple architectures.
|
||||||
|
* Seperate them by a comma'
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
ARCHS = "archs",
|
||||||
|
/**
|
||||||
|
* The base image to use to create a new container image
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
BASE_IMAGE = "base-image",
|
||||||
|
/**
|
||||||
|
* List of --build-args to pass to buildah
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
BUILD_ARGS = "build-args",
|
||||||
|
/**
|
||||||
|
* List of Containerfile paths (eg: ./Containerfile)
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
CONTAINERFILES = "containerfiles",
|
||||||
|
/**
|
||||||
|
* List of files/directories to copy inside the base image
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
CONTENT = "content",
|
||||||
|
/**
|
||||||
|
* Path of the directory to use as context (default: .)
|
||||||
|
* Required: false
|
||||||
|
* Default: "."
|
||||||
|
*/
|
||||||
|
CONTEXT = "context",
|
||||||
|
/**
|
||||||
|
* Alias for "containerfiles". "containerfiles" takes precedence if both are set.
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
DOCKERFILES = "dockerfiles",
|
||||||
|
/**
|
||||||
|
* The entry point to set for containers based on image
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
ENTRYPOINT = "entrypoint",
|
||||||
|
/**
|
||||||
|
* List of environment variables to be set when running containers based on image
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
ENVS = "envs",
|
||||||
|
/**
|
||||||
|
* Extra args to be passed to buildah bud and buildah from.
|
||||||
|
* Separate arguments by newline. Do not use quotes - @actions/exec will do the quoting for you.
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
EXTRA_ARGS = "extra-args",
|
||||||
|
/**
|
||||||
|
* The name (reference) of the image to build
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
IMAGE = "image",
|
||||||
|
/**
|
||||||
|
* The labels of the image to build. Seperate by newline. For example, "io.containers.capabilities=sys_admin,mknod".
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
LABELS = "labels",
|
||||||
|
/**
|
||||||
|
* Set to true to cache intermediate layers during build process
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
LAYERS = "layers",
|
||||||
|
/**
|
||||||
|
* Set to true to build using the OCI image format instead of the Docker image format
|
||||||
|
* Required: false
|
||||||
|
* Default: "false"
|
||||||
|
*/
|
||||||
|
OCI = "oci",
|
||||||
|
/**
|
||||||
|
* Label the image with this PLATFORM, instead of defaulting to the host platform.
|
||||||
|
* Only supported for containerfile builds.
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
PLATFORM = "platform",
|
||||||
|
/**
|
||||||
|
* 'Same as input 'platform', use this for multiple platforms.
|
||||||
|
* Seperate them by a comma'
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
PLATFORMS = "platforms",
|
||||||
|
/**
|
||||||
|
* The port to expose when running containers based on image
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
PORT = "port",
|
||||||
|
/**
|
||||||
|
* The tags of the image to build. For multiple tags, seperate by whitespace. For example, "latest v1".
|
||||||
|
* Required: false
|
||||||
|
* Default: "latest"
|
||||||
|
*/
|
||||||
|
TAGS = "tags",
|
||||||
|
/**
|
||||||
|
* Require HTTPS and verify certificates when accessing the registry. Defaults to true.
|
||||||
|
* Required: false
|
||||||
|
* Default: "true"
|
||||||
|
*/
|
||||||
|
TLS_VERIFY = "tls-verify",
|
||||||
|
/**
|
||||||
|
* The working directory to use within the container
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
WORKDIR = "workdir",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Outputs {
|
||||||
|
/**
|
||||||
|
* Name of the image built
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
IMAGE = "image",
|
||||||
|
/**
|
||||||
|
* Name of the image tagged with the first tag present
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
IMAGE_WITH_TAG = "image-with-tag",
|
||||||
|
/**
|
||||||
|
* List of the tags that were created, separated by spaces
|
||||||
|
* Required: false
|
||||||
|
* Default: None.
|
||||||
|
*/
|
||||||
|
TAGS = "tags",
|
||||||
|
}
|
366
src/index.ts
366
src/index.ts
|
@ -1,125 +1,311 @@
|
||||||
import * as core from '@actions/core';
|
/***************************************************************************************************
|
||||||
import * as io from '@actions/io';
|
* Copyright (c) Red Hat, Inc. All rights reserved.
|
||||||
import { BuildahCli, BuildahConfigSettings } from './buildah';
|
* Licensed under the MIT License. See LICENSE file in the project root for license information.
|
||||||
import * as recognizer from 'language-recognizer';
|
**************************************************************************************************/
|
||||||
import {promises as fs} from 'fs';
|
|
||||||
import * as path from 'path';
|
import * as core from "@actions/core";
|
||||||
import { Language } from 'language-recognizer/lib/types';
|
import * as io from "@actions/io";
|
||||||
|
import * as path from "path";
|
||||||
|
import { Inputs, Outputs } from "./generated/inputs-outputs";
|
||||||
|
import { BuildahCli, BuildahConfigSettings } from "./buildah";
|
||||||
|
import {
|
||||||
|
getArch, getPlatform, getContainerfiles, getInputList, splitByNewline,
|
||||||
|
isFullImageName, getFullImageName, removeIllegalCharacters,
|
||||||
|
} from "./utils";
|
||||||
|
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
|
if (process.env.RUNNER_OS !== "Linux") {
|
||||||
if (process.env.RUNNER_OS !== 'Linux') {
|
throw new Error("buildah, and therefore this action, only works on Linux. Please use a Linux runner.");
|
||||||
throw new Error('buildah, and therefore this action, only works on Linux. Please use a Linux runner.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show message if user is using older version
|
|
||||||
core.info(`⚠️ redhat-actions/buildah-build@v2 is now available. https://github.com/redhat-actions/buildah-build/blob/main/CHANGELOG.md`);
|
|
||||||
|
|
||||||
// get buildah cli
|
// get buildah cli
|
||||||
const buildahPath = await io.which("buildah", true);
|
const buildahPath = await io.which("buildah", true);
|
||||||
const cli: BuildahCli = new BuildahCli(buildahPath);
|
const cli: BuildahCli = new BuildahCli(buildahPath);
|
||||||
|
|
||||||
const workspace = process.env['GITHUB_WORKSPACE'];
|
// print buildah version
|
||||||
let dockerFiles = getInputList('dockerfiles');
|
await cli.execute([ "version" ], { group: true });
|
||||||
const newImage = `${core.getInput('image', { required: true })}:${core.getInput('tag', { required: true })}`;
|
|
||||||
|
|
||||||
const useOCI = core.getInput("oci") == "true";
|
// Check if fuse-overlayfs exists and find the storage driver
|
||||||
|
await cli.setStorageOptsEnv();
|
||||||
|
|
||||||
if (dockerFiles.length !== 0) {
|
const DEFAULT_TAG = "latest";
|
||||||
await doBuildUsingDockerFiles(cli, newImage, workspace, dockerFiles, useOCI);
|
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
|
||||||
} else {
|
const containerFiles = getContainerfiles();
|
||||||
await doBuildFromScratch(cli, newImage, workspace, useOCI);
|
const image = core.getInput(Inputs.IMAGE);
|
||||||
|
const tags = core.getInput(Inputs.TAGS);
|
||||||
|
const tagsList: string[] = tags.trim().split(/\s+/);
|
||||||
|
const labels = core.getInput(Inputs.LABELS);
|
||||||
|
const labelsList: string[] = labels ? splitByNewline(labels) : [];
|
||||||
|
|
||||||
|
const normalizedTagsList: string[] = [];
|
||||||
|
let isNormalized = false;
|
||||||
|
for (const tag of tagsList) {
|
||||||
|
normalizedTagsList.push(tag.toLowerCase());
|
||||||
|
if (tag.toLowerCase() !== tag) {
|
||||||
|
isNormalized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const normalizedImage = image.toLowerCase();
|
||||||
|
if (isNormalized || image !== normalizedImage) {
|
||||||
|
core.warning(`Reference to image and/or tag must be lowercase.`
|
||||||
|
+ ` Reference has been converted to be compliant with standard.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
core.setOutput("image", newImage);
|
// info message if user doesn't provides any tag
|
||||||
}
|
if (tagsList.length === 0) {
|
||||||
|
core.info(`Input "${Inputs.TAGS}" is not provided, using default tag "${DEFAULT_TAG}"`);
|
||||||
|
tagsList.push(DEFAULT_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
async function doBuildUsingDockerFiles(cli: BuildahCli, newImage: string, workspace: string, dockerFiles: string[], useOCI: boolean): Promise<void> {
|
const inputExtraArgsStr = core.getInput(Inputs.EXTRA_ARGS);
|
||||||
if (dockerFiles.length === 1) {
|
let buildahExtraArgs: string[] = [];
|
||||||
core.info(`Performing build from Dockerfile`);
|
if (inputExtraArgsStr) {
|
||||||
|
// transform the array of lines into an array of arguments
|
||||||
|
// by splitting over lines, then over spaces, then trimming.
|
||||||
|
const lines = splitByNewline(inputExtraArgsStr);
|
||||||
|
buildahExtraArgs = lines.flatMap((line) => line.split(" ")).map((arg) => arg.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if all tags provided are in `image:tag` format
|
||||||
|
const isFullImageNameTag = isFullImageName(normalizedTagsList[0]);
|
||||||
|
if (normalizedTagsList.some((tag) => isFullImageName(tag) !== isFullImageNameTag)) {
|
||||||
|
throw new Error(`Input "${Inputs.TAGS}" cannot have a mix of full name and non full name tags. Refer to https://github.com/redhat-actions/buildah-build#image-tag-inputs`);
|
||||||
|
}
|
||||||
|
if (!isFullImageNameTag && !normalizedImage) {
|
||||||
|
throw new Error(`Input "${Inputs.IMAGE}" must be provided when not using full image name tags. Refer to https://github.com/redhat-actions/buildah-build#image-tag-inputs`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newImage = getFullImageName(normalizedImage, normalizedTagsList[0]);
|
||||||
|
const useOCI = core.getInput(Inputs.OCI) === "true";
|
||||||
|
|
||||||
|
const archs = getArch();
|
||||||
|
const platforms = getPlatform();
|
||||||
|
|
||||||
|
if ((archs.length > 0) && (platforms.length > 0)) {
|
||||||
|
throw new Error("The --platform option may not be used in combination with the --arch option.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const builtImage = [];
|
||||||
|
if (containerFiles.length !== 0) {
|
||||||
|
builtImage.push(...await doBuildUsingContainerFiles(
|
||||||
|
cli,
|
||||||
|
newImage,
|
||||||
|
workspace,
|
||||||
|
containerFiles,
|
||||||
|
useOCI,
|
||||||
|
archs,
|
||||||
|
platforms,
|
||||||
|
labelsList,
|
||||||
|
buildahExtraArgs
|
||||||
|
));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.info(`Performing build from ${dockerFiles.length} Dockerfiles`);
|
if (platforms.length > 0) {
|
||||||
|
throw new Error("The --platform option is not supported for builds without containerfiles.");
|
||||||
|
}
|
||||||
|
builtImage.push(...await doBuildFromScratch(cli, newImage, useOCI, archs, labelsList, buildahExtraArgs));
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = path.join(workspace, core.getInput('context'));
|
if ((archs.length > 1) || (platforms.length > 1)) {
|
||||||
const buildArgs = getInputList('build-args');
|
core.info(`Creating manifest with tag${normalizedTagsList.length !== 1 ? "s" : ""} `
|
||||||
dockerFiles = dockerFiles.map(file => path.join(workspace, file));
|
+ `"${normalizedTagsList.join(", ")}"`);
|
||||||
await cli.buildUsingDocker(newImage, context, dockerFiles, buildArgs, useOCI);
|
const builtManifest = [];
|
||||||
|
for (const tag of normalizedTagsList) {
|
||||||
|
const manifestName = getFullImageName(normalizedImage, tag);
|
||||||
|
// Force-remove existing manifest to prevent errors on recurring build on the same machine
|
||||||
|
await cli.manifestRm(manifestName);
|
||||||
|
await cli.manifestCreate(manifestName);
|
||||||
|
builtManifest.push(manifestName);
|
||||||
|
|
||||||
|
for (const arch of archs) {
|
||||||
|
const tagSuffix = removeIllegalCharacters(arch);
|
||||||
|
await cli.manifestAdd(manifestName, `${newImage}-${tagSuffix}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const platform of platforms) {
|
||||||
|
const tagSuffix = removeIllegalCharacters(platform);
|
||||||
|
await cli.manifestAdd(manifestName, `${newImage}-${tagSuffix}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`✅ Successfully built image${builtImage.length !== 1 ? "s" : ""} "${builtImage.join(", ")}" `
|
||||||
|
+ `and manifest${builtManifest.length !== 1 ? "s" : ""} "${builtManifest.join(", ")}"`);
|
||||||
|
}
|
||||||
|
else if (normalizedTagsList.length > 1) {
|
||||||
|
await cli.tag(normalizedImage, normalizedTagsList);
|
||||||
|
}
|
||||||
|
else if (normalizedTagsList.length === 1) {
|
||||||
|
core.info(`✅ Successfully built image "${getFullImageName(normalizedImage, normalizedTagsList[0])}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
core.setOutput(Outputs.IMAGE, normalizedImage);
|
||||||
|
core.setOutput(Outputs.TAGS, tags);
|
||||||
|
core.setOutput(Outputs.IMAGE_WITH_TAG, newImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doBuildFromScratch(cli: BuildahCli, newImage: string, workspace: string, useOCI: boolean): Promise<void> {
|
async function doBuildUsingContainerFiles(
|
||||||
core.info(`Performing build from scratch`)
|
cli: BuildahCli,
|
||||||
|
newImage: string,
|
||||||
let baseImage = core.getInput('base-image');
|
workspace: string,
|
||||||
const content = getInputList('content');
|
containerFiles: string[],
|
||||||
const entrypoint = getInputList('entrypoint');
|
useOCI: boolean,
|
||||||
const port = core.getInput('port');
|
archs: string[],
|
||||||
const workingDir = core.getInput('workdir');
|
platforms: string[],
|
||||||
const envs = getInputList('envs');
|
labels: string[],
|
||||||
|
extraArgs: string[]
|
||||||
// if base-image is not specified by the user we need to pick one automatically
|
): Promise<string[]> {
|
||||||
if (!baseImage) {
|
if (containerFiles.length === 1) {
|
||||||
if (workspace) {
|
core.info(`Performing build from Containerfile`);
|
||||||
// check language/framework used and pick base-image automatically
|
|
||||||
const languages = await recognizer.detectLanguages(workspace);
|
|
||||||
baseImage = await getSuggestedBaseImage(languages);
|
|
||||||
if (!baseImage) {
|
|
||||||
throw new Error('No base image found to create a new container');
|
|
||||||
}
|
}
|
||||||
} else {
|
else {
|
||||||
throw new Error('No base image found to create a new container');
|
core.info(`Performing build from ${containerFiles.length} Containerfiles`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = path.join(workspace, core.getInput(Inputs.CONTEXT));
|
||||||
|
const buildArgs = getInputList(Inputs.BUILD_ARGS);
|
||||||
|
const containerFileAbsPaths = containerFiles.map((file) => path.join(workspace, file));
|
||||||
|
const layers = core.getInput(Inputs.LAYERS);
|
||||||
|
const tlsVerify = core.getInput(Inputs.TLS_VERIFY) === "true";
|
||||||
|
|
||||||
|
const builtImage = [];
|
||||||
|
// since multi arch image can not have same tag
|
||||||
|
// therefore, appending arch/platform in the tag
|
||||||
|
if (archs.length > 0 || platforms.length > 0) {
|
||||||
|
for (const arch of archs) {
|
||||||
|
// handling it seperately as, there is no need of
|
||||||
|
// tagSuffix if only one image has to be built
|
||||||
|
let tagSuffix = "";
|
||||||
|
if (archs.length > 1) {
|
||||||
|
tagSuffix = `-${removeIllegalCharacters(arch)}`;
|
||||||
|
}
|
||||||
|
await cli.buildUsingDocker(
|
||||||
|
`${newImage}${tagSuffix}`,
|
||||||
|
context,
|
||||||
|
containerFileAbsPaths,
|
||||||
|
buildArgs,
|
||||||
|
useOCI,
|
||||||
|
labels,
|
||||||
|
layers,
|
||||||
|
extraArgs,
|
||||||
|
tlsVerify,
|
||||||
|
arch
|
||||||
|
);
|
||||||
|
builtImage.push(`${newImage}${tagSuffix}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const platform of platforms) {
|
||||||
|
let tagSuffix = "";
|
||||||
|
if (platforms.length > 1) {
|
||||||
|
tagSuffix = `-${removeIllegalCharacters(platform)}`;
|
||||||
|
}
|
||||||
|
await cli.buildUsingDocker(
|
||||||
|
`${newImage}${tagSuffix}`,
|
||||||
|
context,
|
||||||
|
containerFileAbsPaths,
|
||||||
|
buildArgs,
|
||||||
|
useOCI,
|
||||||
|
labels,
|
||||||
|
layers,
|
||||||
|
extraArgs,
|
||||||
|
tlsVerify,
|
||||||
|
undefined,
|
||||||
|
platform
|
||||||
|
);
|
||||||
|
builtImage.push(`${newImage}${tagSuffix}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const container = await cli.from(baseImage);
|
else if (archs.length === 1 || platforms.length === 1) {
|
||||||
const containerId = container.output.replace('\n', '');
|
await cli.buildUsingDocker(
|
||||||
|
newImage,
|
||||||
|
context,
|
||||||
|
containerFileAbsPaths,
|
||||||
|
buildArgs,
|
||||||
|
useOCI,
|
||||||
|
labels,
|
||||||
|
layers,
|
||||||
|
extraArgs,
|
||||||
|
tlsVerify,
|
||||||
|
archs[0],
|
||||||
|
platforms[0]
|
||||||
|
);
|
||||||
|
builtImage.push(newImage);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await cli.buildUsingDocker(
|
||||||
|
newImage,
|
||||||
|
context,
|
||||||
|
containerFileAbsPaths,
|
||||||
|
buildArgs,
|
||||||
|
useOCI,
|
||||||
|
labels,
|
||||||
|
layers,
|
||||||
|
extraArgs,
|
||||||
|
tlsVerify
|
||||||
|
);
|
||||||
|
builtImage.push(newImage);
|
||||||
|
}
|
||||||
|
|
||||||
await cli.copy(containerId, content);
|
return builtImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doBuildFromScratch(
|
||||||
|
cli: BuildahCli,
|
||||||
|
newImage: string,
|
||||||
|
useOCI: boolean,
|
||||||
|
archs: string[],
|
||||||
|
labels: string[],
|
||||||
|
extraArgs: string[]
|
||||||
|
): Promise<string[]> {
|
||||||
|
core.info(`Performing build from scratch`);
|
||||||
|
|
||||||
|
const baseImage = core.getInput(Inputs.BASE_IMAGE, { required: true });
|
||||||
|
const content = getInputList(Inputs.CONTENT);
|
||||||
|
const entrypoint = getInputList(Inputs.ENTRYPOINT);
|
||||||
|
const port = core.getInput(Inputs.PORT);
|
||||||
|
const workingDir = core.getInput(Inputs.WORKDIR);
|
||||||
|
const envs = getInputList(Inputs.ENVS);
|
||||||
|
const tlsVerify = core.getInput(Inputs.TLS_VERIFY) === "true";
|
||||||
|
|
||||||
|
const container = await cli.from(baseImage, tlsVerify, extraArgs);
|
||||||
|
const containerId = container.output.replace("\n", "");
|
||||||
|
|
||||||
|
const builtImage = [];
|
||||||
|
if (archs.length > 0) {
|
||||||
|
for (const arch of archs) {
|
||||||
|
let tagSuffix = "";
|
||||||
|
if (archs.length > 1) {
|
||||||
|
tagSuffix = `-${removeIllegalCharacters(arch)}`;
|
||||||
|
}
|
||||||
const newImageConfig: BuildahConfigSettings = {
|
const newImageConfig: BuildahConfigSettings = {
|
||||||
entrypoint: entrypoint,
|
entrypoint,
|
||||||
port: port,
|
port,
|
||||||
workingdir: workingDir,
|
workingdir: workingDir,
|
||||||
envs: envs
|
envs,
|
||||||
|
arch,
|
||||||
|
labels,
|
||||||
};
|
};
|
||||||
await cli.config(containerId, newImageConfig);
|
await cli.config(containerId, newImageConfig);
|
||||||
|
await cli.copy(containerId, content);
|
||||||
|
await cli.commit(containerId, `${newImage}${tagSuffix}`, useOCI);
|
||||||
|
builtImage.push(`${newImage}${tagSuffix}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const newImageConfig: BuildahConfigSettings = {
|
||||||
|
entrypoint,
|
||||||
|
port,
|
||||||
|
workingdir: workingDir,
|
||||||
|
envs,
|
||||||
|
labels,
|
||||||
|
};
|
||||||
|
await cli.config(containerId, newImageConfig);
|
||||||
|
await cli.copy(containerId, content);
|
||||||
await cli.commit(containerId, newImage, useOCI);
|
await cli.commit(containerId, newImage, useOCI);
|
||||||
}
|
builtImage.push(newImage);
|
||||||
|
|
||||||
function getInputList(name: string): string[] {
|
|
||||||
const items = core.getInput(name);
|
|
||||||
if (!items) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return items
|
|
||||||
.split(/\r?\n/)
|
|
||||||
.filter(x => x)
|
|
||||||
.reduce<string[]>(
|
|
||||||
(acc, line) => acc.concat(line).map(pat => pat.trim()),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getSuggestedBaseImage(languages: Language[]): Promise<string> {
|
|
||||||
if (!languages || languages.length === 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const language of languages) {
|
return builtImage;
|
||||||
const baseImage = await getBaseImageByLanguage(language);
|
|
||||||
if (baseImage) {
|
|
||||||
return baseImage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getBaseImageByLanguage(language: Language): Promise<string> {
|
|
||||||
const rawData = await fs.readFile(path.join(__dirname, '..', 'language-image.json'), 'utf-8');
|
|
||||||
const languageImageJSON = JSON.parse(rawData);
|
|
||||||
return languageImageJSON[language.name];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(core.setFailed);
|
run().catch(core.setFailed);
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) Red Hat, Inc. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See LICENSE file in the project root for license information.
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
type CommandResult = {
|
type CommandResult = {
|
||||||
exitCode: number
|
exitCode: number
|
||||||
output: string
|
output: string
|
||||||
error: string
|
error: string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default CommandResult;
|
||||||
|
|
173
src/utils.ts
Normal file
173
src/utils.ts
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Copyright (c) Red Hat, Inc. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See LICENSE file in the project root for license information.
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
import * as ini from "ini";
|
||||||
|
import { promises as fs } from "fs";
|
||||||
|
import * as core from "@actions/core";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as io from "@actions/io";
|
||||||
|
import * as os from "os";
|
||||||
|
import { Inputs } from "./generated/inputs-outputs";
|
||||||
|
|
||||||
|
async function findStorageDriver(filePaths: string[]): Promise<string> {
|
||||||
|
let storageDriver = "";
|
||||||
|
for (const filePath of filePaths) {
|
||||||
|
core.debug(`Checking if the storage file exists at ${filePath}`);
|
||||||
|
if (await fileExists(filePath)) {
|
||||||
|
core.debug(`Storage file exists at ${filePath}`);
|
||||||
|
const fileContent = ini.parse(await fs.readFile(filePath, "utf-8"));
|
||||||
|
if (fileContent.storage.driver) {
|
||||||
|
storageDriver = fileContent.storage.driver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return storageDriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isStorageDriverOverlay(): Promise<boolean> {
|
||||||
|
let xdgConfigHome = path.join(os.homedir(), ".config");
|
||||||
|
if (process.env.XDG_CONFIG_HOME) {
|
||||||
|
xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
||||||
|
}
|
||||||
|
const filePaths: string[] = [
|
||||||
|
"/etc/containers/storage.conf",
|
||||||
|
path.join(xdgConfigHome, "containers/storage.conf"),
|
||||||
|
];
|
||||||
|
const storageDriver = await findStorageDriver(filePaths);
|
||||||
|
return (storageDriver === "overlay");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fileExists(filePath: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await fs.access(filePath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function findFuseOverlayfsPath(): Promise<string | undefined> {
|
||||||
|
let fuseOverlayfsPath;
|
||||||
|
try {
|
||||||
|
fuseOverlayfsPath = await io.which("fuse-overlayfs");
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err instanceof Error) {
|
||||||
|
core.debug(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fuseOverlayfsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function splitByNewline(s: string): string[] {
|
||||||
|
return s.split(/\r?\n/);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getArch(): string[] {
|
||||||
|
const archs = getCommaSeperatedInput(Inputs.ARCHS);
|
||||||
|
|
||||||
|
const arch = core.getInput(Inputs.ARCH);
|
||||||
|
|
||||||
|
if (arch && archs.length > 0) {
|
||||||
|
core.warning(
|
||||||
|
`Both "${Inputs.ARCH}" and "${Inputs.ARCHS}" inputs are set. `
|
||||||
|
+ `Please use "${Inputs.ARCH}" if you want to provide multiple `
|
||||||
|
+ `ARCH else use ${Inputs.ARCH}". "${Inputs.ARCHS}" takes preference.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archs.length > 0) {
|
||||||
|
return archs;
|
||||||
|
}
|
||||||
|
else if (arch) {
|
||||||
|
return [ arch ];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlatform(): string[] {
|
||||||
|
const platform = core.getInput(Inputs.PLATFORM);
|
||||||
|
const platforms = getCommaSeperatedInput(Inputs.PLATFORMS);
|
||||||
|
|
||||||
|
if (platform && platforms.length > 0) {
|
||||||
|
core.warning(
|
||||||
|
`Both "${Inputs.PLATFORM}" and "${Inputs.PLATFORMS}" inputs are set. `
|
||||||
|
+ `Please use "${Inputs.PLATFORMS}" if you want to provide multiple `
|
||||||
|
+ `PLATFORM else use ${Inputs.PLATFORM}". "${Inputs.PLATFORMS}" takes preference.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platforms.length > 0) {
|
||||||
|
core.debug("return platforms");
|
||||||
|
return platforms;
|
||||||
|
}
|
||||||
|
else if (platform) {
|
||||||
|
core.debug("return platform");
|
||||||
|
return [ platform ];
|
||||||
|
}
|
||||||
|
core.debug("return empty");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getContainerfiles(): string[] {
|
||||||
|
// 'containerfile' should be used over 'dockerfile',
|
||||||
|
// see https://github.com/redhat-actions/buildah-build/issues/57
|
||||||
|
const containerfiles = getInputList(Inputs.CONTAINERFILES);
|
||||||
|
const dockerfiles = getInputList(Inputs.DOCKERFILES);
|
||||||
|
|
||||||
|
if (containerfiles.length !== 0 && dockerfiles.length !== 0) {
|
||||||
|
core.warning(
|
||||||
|
`Both "${Inputs.CONTAINERFILES}" and "${Inputs.DOCKERFILES}" inputs are set. `
|
||||||
|
+ `Please use only one of these two inputs, as they are aliases of one another. `
|
||||||
|
+ `"${Inputs.CONTAINERFILES}" takes precedence.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return containerfiles.length !== 0 ? containerfiles : dockerfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInputList(name: string): string[] {
|
||||||
|
const items = core.getInput(name);
|
||||||
|
if (!items) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const splitItems = splitByNewline(items);
|
||||||
|
return splitItems
|
||||||
|
.reduce<string[]>(
|
||||||
|
(acc, line) => acc.concat(line).map((item) => item.trim()),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCommaSeperatedInput(name: string): string[] {
|
||||||
|
const items = core.getInput(name);
|
||||||
|
if (items.length === 0) {
|
||||||
|
core.debug("empty");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const splitItems = items.split(",");
|
||||||
|
return splitItems
|
||||||
|
.reduce<string[]>(
|
||||||
|
(acc, line) => acc.concat(line).map((item) => item.trim()),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isFullImageName(image: string): boolean {
|
||||||
|
return image.indexOf(":") > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFullImageName(image: string, tag: string): string {
|
||||||
|
if (isFullImageName(tag)) {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
return `${image}:${tag}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeIllegalCharacters(item: string): string {
|
||||||
|
return item.replace(/[^a-zA-Z0-9 ]/g, "");
|
||||||
|
}
|
|
@ -1,15 +1,10 @@
|
||||||
{
|
{
|
||||||
|
"extends": "@redhat-actions/tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES6",
|
"rootDir": "src/",
|
||||||
"module": "commonjs",
|
"outDir": "out/"
|
||||||
"lib": [
|
|
||||||
"ES2017"
|
|
||||||
],
|
|
||||||
"outDir": "out",
|
|
||||||
"rootDir": ".",
|
|
||||||
},
|
},
|
||||||
"exclude": [
|
"include": [
|
||||||
"node_modules",
|
"src/"
|
||||||
"scripts"
|
],
|
||||||
]
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue