Filter stale APKs from CI package cache
Build Alpine Packages / build-and-publish (v3.24, 3.24) (push) Has been cancelled

This commit is contained in:
Joachim Schlöffel
2026-07-12 10:09:45 +02:00
parent 7781653941
commit faf7d5e404
4 changed files with 134 additions and 21 deletions
+44 -19
View File
@@ -14,7 +14,7 @@ command_name="${1:-prepare}"
all_packages() { all_packages() {
while IFS= read -r package_dir; do while IFS= read -r package_dir; do
apk_package_name "${package_dir}" apk_package_name "${package_dir}"
done < <(apk_package_dirs "${repo_root}") done < <(apk_all_package_dirs "${repo_root}")
} }
mark_all_packages() { mark_all_packages() {
@@ -97,23 +97,7 @@ package_apk_names() {
local package_dir="$1" local package_dir="$1"
local arch="$2" local arch="$2"
( apk_package_apk_names "${package_dir}" "${arch}"
set +u
local pkgname
local pkgver
local pkgrel
local subpackages
export CARCH="${arch}"
cd "${package_dir}"
# shellcheck source=/dev/null
. ./APKBUILD
printf '%s-%s-r%s.apk\n' "${pkgname}" "${pkgver}" "${pkgrel}"
for subpackage in ${subpackages:-}; do
subpackage="${subpackage%%:*}"
printf '%s-%s-r%s.apk\n' "${subpackage}" "${pkgver}" "${pkgrel}"
done
)
} }
package_cache_complete() { package_cache_complete() {
@@ -155,7 +139,46 @@ select_missing_packages() {
if ! package_cache_complete "${package_dir}"; then if ! package_cache_complete "${package_dir}"; then
printf '%s\n' "${package_name}" printf '%s\n' "${package_name}"
fi fi
done < <(apk_package_dirs "${repo_root}") done < <(apk_all_package_dirs "${repo_root}")
}
prune_stale_apks() {
local package_dir
local arch
local apk_name
local current_apk
declare -A expected_apks=()
if [[ ! -d "${repo_dest}" ]]; then
return
fi
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
for arch in ${arches}; do
case "${arch}" in
x86_64|aarch64) ;;
*) printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2; exit 2 ;;
esac
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
continue
fi
while IFS= read -r apk_name; do
expected_apks["${repo_dest}/${arch}/${apk_name}"]=1
done < <(package_apk_names "${package_dir}" "${arch}")
done
done < <(apk_all_package_dirs "${repo_root}")
shopt -s nullglob
for current_apk in "${repo_dest}"/*/*.apk; do
if [[ -z "${expected_apks[${current_apk}]:-}" ]]; then
rm -f "${current_apk}"
printf 'Pruned stale cached APK: %s\n' "${current_apk#"${repo_root}/"}"
fi
done
shopt -u nullglob
} }
prepare() { prepare() {
@@ -164,6 +187,7 @@ prepare() {
declare -A selected_map=() declare -A selected_map=()
restore_cache restore_cache
prune_stale_apks
while IFS= read -r selected; do while IFS= read -r selected; do
[[ -n "${selected}" ]] || continue [[ -n "${selected}" ]] || continue
@@ -205,6 +229,7 @@ sync_cache() {
exit 1 exit 1
fi fi
prune_stale_apks
mkdir -p "${cache_root}" mkdir -p "${cache_root}"
find "${cache_root}" -mindepth 1 -maxdepth 1 -exec rm -rf {} + find "${cache_root}" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
cp -a "${repo_dest}/." "${cache_root}/" cp -a "${repo_dest}/." "${cache_root}/"
+22
View File
@@ -2,7 +2,25 @@
set -euo pipefail set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=scripts/apk/package-lib.sh
. "${repo_root}/scripts/apk/package-lib.sh"
repo_dir="${repo_root}/packages/local" repo_dir="${repo_root}/packages/local"
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
declare -A expected_apks=()
while IFS= read -r package_source_dir; do
apk_validate_package_dir "${package_source_dir}"
for arch in ${arches}; do
if ! apk_package_supports_arch "${package_source_dir}" "${arch}"; then
continue
fi
while IFS= read -r apk_name; do
expected_apks["${repo_dir}/${arch}/${apk_name}"]=1
done < <(apk_package_apk_names "${package_source_dir}" "${arch}")
done
done < <(apk_all_package_dirs "${repo_root}")
if [[ -n "${ALPINE_ARCH:-}" ]]; then if [[ -n "${ALPINE_ARCH:-}" ]]; then
package_dirs=("${repo_dir}/${ALPINE_ARCH}") package_dirs=("${repo_dir}/${ALPINE_ARCH}")
@@ -29,6 +47,10 @@ for package_dir in "${package_dirs[@]}"; do
printf '## %s\n' "$(basename "${package_dir}")" printf '## %s\n' "$(basename "${package_dir}")"
for apk in "${apks[@]}"; do for apk in "${apks[@]}"; do
if [[ -z "${expected_apks[${apk}]:-}" ]]; then
printf 'Skipping stale local APK: %s\n' "${apk#"${repo_root}/"}"
continue
fi
printf '### %s\n' "$(basename "${apk}")" printf '### %s\n' "$(basename "${apk}")"
tar -xOf "${apk}" .PKGINFO 2>/dev/null \ tar -xOf "${apk}" .PKGINFO 2>/dev/null \
| sed -n '/^pkgname =/p;/^pkgver =/p;/^arch =/p;/^depend =/p;/^provides =/p;/^install_if =/p' | sed -n '/^pkgname =/p;/^pkgver =/p;/^arch =/p;/^depend =/p;/^provides =/p;/^install_if =/p'
+32
View File
@@ -37,6 +37,14 @@ apk_package_dirs() {
return return
fi fi
apk_all_package_dirs "${repo_root}"
}
apk_all_package_dirs() {
local repo_root="$1"
local package_root
package_root="$(apk_package_root "${repo_root}")"
find "${package_root}" -mindepth 2 -maxdepth 2 -name APKBUILD -print \ find "${package_root}" -mindepth 2 -maxdepth 2 -name APKBUILD -print \
| sed 's#/APKBUILD$##' \ | sed 's#/APKBUILD$##' \
| sort | sort
@@ -87,6 +95,30 @@ apk_package_supports_arch() {
return 1 return 1
} }
apk_package_apk_names() {
local package_dir="$1"
local arch="$2"
(
set +u
local pkgname
local pkgver
local pkgrel
local subpackage
local subpackages
export CARCH="${arch}"
cd "${package_dir}"
# shellcheck source=/dev/null
. ./APKBUILD
printf '%s-%s-r%s.apk\n' "${pkgname}" "${pkgver}" "${pkgrel}"
for subpackage in ${subpackages:-}; do
subpackage="${subpackage%%:*}"
printf '%s-%s-r%s.apk\n' "${subpackage}" "${pkgver}" "${pkgrel}"
done
)
}
apk_container_package_dir() { apk_container_package_dir() {
local repo_root="$1" local repo_root="$1"
local package_dir="$2" local package_dir="$2"
+36 -2
View File
@@ -2,8 +2,12 @@
set -euo pipefail set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck source=scripts/apk/package-lib.sh
. "${repo_root}/scripts/apk/package-lib.sh"
repo_name="${ALPINE_REPO_NAME:-local}" repo_name="${ALPINE_REPO_NAME:-local}"
alpine_version="${ALPINE_VERSION:-3.24}" alpine_version="${ALPINE_VERSION:-3.24}"
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
branch="${ALPINE_REGISTRY_BRANCH:-v${alpine_version}}" branch="${ALPINE_REGISTRY_BRANCH:-v${alpine_version}}"
repository="${ALPINE_REGISTRY_REPOSITORY:-${PACKAGE_NAME:-main}}" repository="${ALPINE_REGISTRY_REPOSITORY:-${PACKAGE_NAME:-main}}"
instance_url="${INSTANCE_URL:-}" instance_url="${INSTANCE_URL:-}"
@@ -46,20 +50,50 @@ if [[ "${#apks[@]}" -eq 0 ]]; then
exit 1 exit 1
fi fi
declare -A expected_apks=()
while IFS= read -r package_dir; do
apk_validate_package_dir "${package_dir}"
for arch in ${arches}; do
if ! apk_package_supports_arch "${package_dir}" "${arch}"; then
continue
fi
while IFS= read -r apk_name; do
expected_apks["${package_root}/${arch}/${apk_name}"]=1
done < <(apk_package_apk_names "${package_dir}" "${arch}")
done
done < <(apk_all_package_dirs "${repo_root}")
declare -A published_filenames=() declare -A published_filenames=()
unique_apks=() unique_apks=()
stale_count=0
duplicate_count=0
for apk in "${apks[@]}"; do for apk in "${apks[@]}"; do
filename="$(basename "${apk}")" filename="$(basename "${apk}")"
if [[ -z "${expected_apks[${apk}]:-}" ]]; then
printf 'Skipping stale local APK: %s\n' "${apk#"${repo_root}/"}"
stale_count=$((stale_count + 1))
continue
fi
if [[ -n "${published_filenames[${filename}]:-}" ]]; then if [[ -n "${published_filenames[${filename}]:-}" ]]; then
duplicate_count=$((duplicate_count + 1))
continue continue
fi fi
published_filenames["${filename}"]=1 published_filenames["${filename}"]=1
unique_apks+=("${apk}") unique_apks+=("${apk}")
done done
if [[ "${#unique_apks[@]}" -eq 0 ]]; then
printf 'no current APK files found under %s\n' "${package_root}" >&2
exit 1
fi
printf 'Publishing %d APK files to %s\n' "${#unique_apks[@]}" "${upload_url}" printf 'Publishing %d APK files to %s\n' "${#unique_apks[@]}" "${upload_url}"
if [[ "${#unique_apks[@]}" -ne "${#apks[@]}" ]]; then if [[ "${duplicate_count}" -ne 0 ]]; then
printf 'Skipping %d duplicate local APK filename(s)\n' "$((${#apks[@]} - ${#unique_apks[@]}))" printf 'Skipping %d duplicate local APK filename(s)\n' "${duplicate_count}"
fi
if [[ "${stale_count}" -ne 0 ]]; then
printf 'Skipping %d stale local APK file(s)\n' "${stale_count}"
fi fi
for apk in "${unique_apks[@]}"; do for apk in "${unique_apks[@]}"; do