Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 67 additions & 21 deletions build-images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,75 @@ repobase="${REPOBASE:-ghcr.io/nethserver}"
# Configure the image name
reponame="webserver"

# Function to build PHP FPM images
build_php_image() {
local version=$1
local php_image=$2

podman build \
--force-rm \
--layers \
--tag "${repobase}/php${version}-fpm" \
--build-arg "PHP_VERSION_IMAGE=${php_image}" \
container

images+=("${repobase}/php${version}-fpm")
# PHP versions to build: "version" "base-image" (pairs)
declare -a PHP_VERSIONS=(
"8.5" "docker.io/library/php:8.5.4-fpm-bookworm"
"8.4" "docker.io/library/php:8.4.19-fpm-bookworm"
"8.3" "docker.io/library/php:8.3.30-fpm-bookworm"
"8.2" "docker.io/library/php:8.2.30-fpm-bookworm"
"8.1" "docker.io/library/php:8.1.34-fpm-bookworm"
"8.0" "docker.io/library/php:8.0.30-fpm-bullseye"
"7.4" "docker.io/library/php:7.4.33-fpm-bullseye"
)

# Secure temp dir for FIFO (avoids TOCTOU race of mktemp -u)
tmpdir=$(mktemp -d)
result_fifo="${tmpdir}/result.fifo"
mkfifo "${result_fifo}"
# Open FIFO read-write to avoid blocking on open (no writer needed yet)
exec 3<> "${result_fifo}"

declare -a pids=()

kill_all_builds() {
for pid in "${pids[@]}"; do
pkill -P "${pid}" 2>/dev/null || true # kill podman and other children first
kill "${pid}" 2>/dev/null || true # then kill the bash wrapper
done
}
trap 'kill_all_builds; exec 3<&-; exec 3>&-; rm -rf "${tmpdir}"' EXIT
trap 'kill_all_builds; exit 130' INT
trap 'kill_all_builds; exit 143' TERM

# Launch all PHP FPM builds in parallel
for (( i=0; i<${#PHP_VERSIONS[@]}; i+=2 )); do
version="${PHP_VERSIONS[$i]}"
php_image="${PHP_VERSIONS[$((i+1))]}"
echo "Starting build php${version}-fpm (${php_image})..."
(
result=0
# Reports result to FIFO on exit; handles normal exit and SIGTERM.
# SIGKILL would bypass this trap, but is an acceptable limitation for a build script.
trap 'printf "%s %d\n" "${version}" "${result}" > "${result_fifo}" 2>/dev/null || true' EXIT
set -o pipefail
podman build \
--force-rm \
--layers \
--cache-from "${repobase}/php${version}-fpm" \
--tag "${repobase}/php${version}-fpm" \
--build-arg "PHP_VERSION_IMAGE=${php_image}" \
container 2>&1 | sed -u "s/^/[php${version}] /" || result=$?
) &
pids+=("$!")
done

# Read results in completion order; stop everything on first failure
total=${#pids[@]}
for (( completed=0; completed<total; completed++ )); do
read -r done_version done_result <&3
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result-collection loop doesn’t check whether read succeeded. If the FIFO hits EOF or read is interrupted, done_result can be empty/non-numeric and [[ ... -ne 0 ]] will error under set -e, aborting the script without a clear message. Handle read failures explicitly and validate done_result before numeric comparison.

Suggested change
read -r done_version done_result <&3
if ! read -r done_version done_result <&3; then
echo "[main] Failed to read build result from result FIFO"
exit 1
fi
if [[ -z "${done_version}" || -z "${done_result}" || ! "${done_result}" =~ ^-?[0-9]+$ ]]; then
echo "[main] Malformed build result from result FIFO: version='${done_version}' result='${done_result}'"
exit 1
fi

Copilot uses AI. Check for mistakes.
if [[ "${done_result}" -ne 0 ]]; then
echo "[php${done_version}] BUILD FAILED - killing remaining builds..."
exit 1
fi
echo "[php${done_version}] BUILD OK"
done

# Reap all background build jobs to avoid zombies
wait "${pids[@]}"

# Build all PHP FPM images
build_php_image "8.5" "docker.io/library/php:8.5.4-fpm-bookworm"
build_php_image "8.4" "docker.io/library/php:8.4.19-fpm-bookworm"
build_php_image "8.3" "docker.io/library/php:8.3.30-fpm-bookworm"
build_php_image "8.2" "docker.io/library/php:8.2.30-fpm-bookworm"
build_php_image "8.1" "docker.io/library/php:8.1.34-fpm-bookworm"
build_php_image "8.0" "docker.io/library/php:8.0.30-fpm-bullseye"
build_php_image "7.4" "docker.io/library/php:7.4.33-fpm-bullseye"
for (( i=0; i<${#PHP_VERSIONS[@]}; i+=2 )); do
images+=("${repobase}/php${PHP_VERSIONS[$i]}-fpm")
done

# Create a new empty container image
container=$(buildah from scratch)
Expand Down
1 change: 0 additions & 1 deletion container/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ ARG PHP_EXTENSIONS="\
RUN set -eux \
# --- Install runtime libraries depending on Debian codename ---
&& apt update \
&& apt upgrade -y \
&& apt install -y ca-certificates openssl\
&& if echo "$PHP_VERSION_IMAGE" | grep -q "bullseye$"; then \
apt install -y --no-install-recommends \
Expand Down
Loading