Add multi-package Alpine packaging

This commit is contained in:
Joachim Schlöffel
2026-06-08 23:43:29 +02:00
parent d5a32abcd4
commit edc68c825b
22 changed files with 1013 additions and 146 deletions

View File

@@ -4,6 +4,8 @@ set -euo pipefail
command_name="${1:-build}"
requested_arch="${2:-${ALPINE_ARCH:-x86_64}}"
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
. "${repo_root}/scripts/apk/package-lib.sh"
alpine_version="${ALPINE_VERSION:-3.23}"
repo_name="${ALPINE_REPO_NAME:-local}"
build_platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
@@ -27,10 +29,14 @@ validate_arch() {
run_for_arch() {
local arch="$1"
local subcommand="$2"
local package_dir="$3"
local image_name
local container_package_dir
validate_arch "${arch}"
image_name="${ALPINE_APK_BUILDER_IMAGE:-seaweedfs-apk-builder:${arch}}"
apk_validate_package_dir "${package_dir}"
container_package_dir="$(apk_container_package_dir "${repo_root}" "${package_dir}")"
image_name="${ALPINE_APK_BUILDER_IMAGE:-alpine-apk-builder:${arch}}"
docker build \
--platform "${build_platform}" \
@@ -50,6 +56,7 @@ run_for_arch() {
-e "ALPINE_ARCH=${arch}" \
-e "CARCH=${arch}" \
-e "ALPINE_REPO_NAME=${repo_name}" \
-e "APKBUILD_DIR=${container_package_dir}" \
-e "PACKAGER=${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}" \
-v "${repo_root}:/work" \
-v "${repo_root}/.cache/abuild:/home/builder/.abuild" \
@@ -66,12 +73,38 @@ mkdir -p \
case "${command_name}" in
build-all)
for arch in ${ALPINE_ARCHES:-x86_64 aarch64}; do
run_for_arch "${arch}" build
done
while IFS= read -r package_dir; do
for arch in ${ALPINE_ARCHES:-x86_64 aarch64}; do
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
printf 'Skipping %s for unsupported arch %s\n' "$(apk_package_name "${package_dir}")" "${arch}"
continue
fi
run_for_arch "${arch}" build "${package_dir}"
done
done < <(apk_package_dirs "${repo_root}")
;;
build|checksum|lint|shell)
run_for_arch "${requested_arch}" "${command_name}"
build|checksum|lint)
while IFS= read -r package_dir; do
if [[ "${command_name}" == "build" ]] && ! apk_package_supports_arch "${package_dir}" "${requested_arch}"; then
printf 'Skipping %s for unsupported arch %s\n' "$(apk_package_name "${package_dir}")" "${requested_arch}"
continue
fi
run_for_arch "${requested_arch}" "${command_name}" "${package_dir}"
done < <(apk_package_dirs "${repo_root}")
;;
shell)
package_count=0
selected_package_dir=""
while IFS= read -r package_dir; do
package_count=$((package_count + 1))
selected_package_dir="${package_dir}"
done < <(apk_package_dirs "${repo_root}")
if [[ "${package_count}" -ne 1 ]]; then
printf 'apk:shell needs exactly one package; set ALPINE_PACKAGE=<name>\n' >&2
exit 2
fi
run_for_arch "${requested_arch}" "${command_name}" "${selected_package_dir}"
;;
*)
printf 'unknown command: %s\n' "${command_name}" >&2

View File

@@ -2,10 +2,12 @@
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
package_dir="${APKBUILD_DIR:-${repo_root}/packaging/alpine/local/seaweedfs}"
. "${repo_root}/scripts/apk/package-lib.sh"
repo_name="${ALPINE_REPO_NAME:-local}"
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
packager="${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}"
selected_packages="${ALPINE_PACKAGE:-${ALPINE_PACKAGES:-}}"
if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
addgroup -g 1000 builder 2>/dev/null || addgroup builder
@@ -15,7 +17,7 @@ if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
printf 'permit nopass :wheel\n' > /etc/doas.d/wheel.conf
printf '%%wheel ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/wheel
chown -R builder:builder "${repo_root}"
exec su builder -c "ALPINE_ARCHES='${arches}' ALPINE_REPO_NAME='${repo_name}' PACKAGER='${packager}' '${BASH_SOURCE[0]}' --as-builder"
exec su builder -c "ALPINE_ARCHES='${arches}' ALPINE_REPO_NAME='${repo_name}' ALPINE_PACKAGES='${selected_packages}' PACKAGER='${packager}' '${BASH_SOURCE[0]}' --as-builder"
fi
export PACKAGER="${packager}"
@@ -36,20 +38,29 @@ fi
doas cp "${HOME}"/.abuild/*.rsa.pub /etc/apk/keys/
for arch in ${arches}; do
case "${arch}" in
x86_64|aarch64) ;;
*) printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2; exit 2 ;;
esac
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
printf 'Building %s for %s\n' "$(basename "${package_dir}")" "${arch}"
(
export ALPINE_ARCH="${arch}"
export CARCH="${arch}"
cd "${package_dir}"
abuild -r
)
for arch in ${arches}; do
case "${arch}" in
x86_64|aarch64) ;;
*) printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2; exit 2 ;;
esac
mkdir -p "${REPODEST}/${repo_name}/${arch}"
cp "${HOME}"/.abuild/*.rsa.pub "${REPODEST}/${repo_name}/${arch}/"
done
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
printf 'Skipping %s for unsupported arch %s\n' "$(basename "${package_dir}")" "${arch}"
continue
fi
printf 'Building %s for %s\n' "$(basename "${package_dir}")" "${arch}"
(
export ALPINE_ARCH="${arch}"
export CARCH="${arch}"
cd "${package_dir}"
abuild -r
)
mkdir -p "${REPODEST}/${repo_name}/${arch}"
cp "${HOME}"/.abuild/*.rsa.pub "${REPODEST}/${repo_name}/${arch}/"
done
done < <(apk_package_dirs "${repo_root}")

View File

@@ -4,7 +4,7 @@ set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
repo_name="${ALPINE_REPO_NAME:-local}"
arch="${ALPINE_ARCH:-$(apk --print-arch)}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc greptimedb}"
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
read -r -a package_list <<< "${packages}"
@@ -18,6 +18,9 @@ echo "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories
apk update
apk add "${package_list[@]}"
weed version
if command -v greptime >/dev/null 2>&1; then
greptime --version
fi
ls -1 /etc/seaweedfs
if ls /etc/init.d/seaweedfs.* >/dev/null 2>&1; then
find /etc/init.d -maxdepth 1 -name 'seaweedfs.*' -print | sort

View File

@@ -3,7 +3,7 @@ set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
rm -rf \
"${repo_root}/packages" \
"${repo_root}/packaging/alpine/local/seaweedfs/pkg" \
"${repo_root}/packaging/alpine/local/seaweedfs/src"
rm -rf "${repo_root}/packages"
find "${repo_root}/packaging/alpine/local" \
\( -type d -name pkg -o -type d -name src \) \
-prune -exec rm -rf {} +

131
scripts/apk/package-lib.sh Normal file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env bash
apk_repo_root() {
cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd
}
apk_package_root() {
local repo_root="$1"
printf '%s\n' "${ALPINE_PACKAGE_ROOT:-${repo_root}/packaging/alpine/local}"
}
apk_package_dirs() {
local repo_root="$1"
local package_root
local package
local dir
package_root="$(apk_package_root "${repo_root}")"
if [[ -n "${APKBUILD_DIR:-}" ]]; then
printf '%s\n' "${APKBUILD_DIR}"
return
fi
if [[ -n "${ALPINE_PACKAGE:-}" || -n "${ALPINE_PACKAGES:-}" ]]; then
for package in ${ALPINE_PACKAGE:-${ALPINE_PACKAGES:-}}; do
case "${package}" in
/*|.*/*|*/*)
dir="${package}"
;;
*)
dir="${package_root}/${package}"
;;
esac
printf '%s\n' "${dir}"
done
return
fi
find "${package_root}" -mindepth 2 -maxdepth 2 -name APKBUILD -print \
| sed 's#/APKBUILD$##' \
| sort
}
apk_validate_package_dir() {
local package_dir="$1"
if [[ ! -f "${package_dir}/APKBUILD" ]]; then
printf 'missing APKBUILD: %s\n' "${package_dir}/APKBUILD" >&2
return 1
fi
}
apk_package_name() {
basename "$1"
}
apk_package_arches() {
local package_dir="$1"
awk -F= '
$1 == "arch" {
gsub(/["'\'']/, "", $2)
gsub(/^[ \t]+|[ \t]+$/, "", $2)
print $2
exit
}
' "${package_dir}/APKBUILD"
}
apk_package_supports_arch() {
local package_dir="$1"
local arch="$2"
local supported_arches
local supported_arch
supported_arches="$(apk_package_arches "${package_dir}")"
for supported_arch in ${supported_arches}; do
case "${supported_arch}" in
all|noarch|"${arch}")
return 0
;;
esac
done
return 1
}
apk_container_package_dir() {
local repo_root="$1"
local package_dir="$2"
case "${package_dir}" in
"${repo_root}"/*)
printf '/work/%s\n' "${package_dir#"${repo_root}/"}"
;;
*)
printf 'package directory must be inside repository: %s\n' "${package_dir}" >&2
return 1
;;
esac
}
apk_run_package_hook() {
local repo_root="$1"
local package_dir="$2"
local hook_name="$3"
shift 3
local package_name
local hook_path
package_name="$(apk_package_name "${package_dir}")"
hook_path="${package_dir}/scripts/${hook_name}.sh"
if [[ ! -e "${hook_path}" ]]; then
printf 'Skipping %s: no %s hook\n' "${package_name}" "${hook_name}"
return
fi
if [[ ! -x "${hook_path}" ]]; then
printf 'package hook is not executable: %s\n' "${hook_path}" >&2
return 1
fi
printf 'Running %s hook for %s\n' "${hook_name}" "${package_name}"
REPO_ROOT="${repo_root}" \
PACKAGE_DIR="${package_dir}" \
PACKAGE_NAME="${package_name}" \
"${hook_path}" "$@"
}

10
scripts/apk/test-install.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
. "${repo_root}/scripts/apk/package-lib.sh"
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
apk_run_package_hook "${repo_root}" "${package_dir}" test-install
done < <(apk_package_dirs "${repo_root}")

View File

@@ -2,14 +2,9 @@
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
package_dir="${repo_root}/packaging/alpine/local/seaweedfs"
configs=(credential filer master notification replication security shell)
. "${repo_root}/scripts/apk/package-lib.sh"
for config in "${configs[@]}"; do
"${repo_root}/bin/weed" scaffold -config "${config}" 2>/dev/null \
> "${package_dir}/example-${config}.toml"
done
"${repo_root}/bin/weed" autocomplete bash 2>/dev/null \
| sed -E 's#complete -C "?[^"]*/weed"? weed#complete -C /usr/bin/weed weed#' \
> "${package_dir}/weed.bash-completion"
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
apk_run_package_hook "${repo_root}" "${package_dir}" update-generated-sources
done < <(apk_package_dirs "${repo_root}")