Files
computer-playbook/scripts/tests/deploy/utils/filesystem/resolve.sh
T
kevinveenbirkenbachandClaude Opus 5 3c55052a0b fix(ci): measure what the kernel serves instead of listing it
RUNNER_POOL and NODE_POOL were assertions. With a distro list of just debian
and ubuntu the node pool offered zfs, because the table records that those
distros ship the zfs userland - but the module comes from the runner's kernel,
which carries none. One run in three would then have drawn zfs and either
declined silently, testing ext4 while the summary claimed zfs, or hard-failed on
all five nodes with nothing actually broken.

Ask the kernel instead: /proc/filesystems for what is loaded, modinfo for what
could be. Both answer unprivileged, which resolve.sh needs since it runs without
sudo. The modinfo half carries weight rather than being belt-and-braces - xfs is
absent from /proc/filesystems on this host while modinfo finds the module, so
without it the pool would shrink to whatever happens to be loaded.

The distro table stays above it for the other question: which userland a
container can install. Two layers because they are two things, and only the
kernel one cannot be fixed by a package.

Every exclusion now names its reason on stderr and distinguishes a missing tool
from a missing capability; a filesystem used to drop out of the pool in silence.

For the full five-distro sweep the pool is unchanged: ext4 btrfs, measured
before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 12:05:16 +02:00

103 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Resolve which filesystem one matrix entry runs its docker data root on and
# record the decision for the steps that follow.
#
# A random pick draws from what this kernel serves, measured here, narrowed to
# what every distro of the entry carries a userland for. A stated pick is
# honoured even where it is unsupported, and the applying step then fails. The
# choice goes to the step summary, since reproducing a red run means re-stating
# it verbatim.
#
# Arguments:
# $1 STATED ext4 | btrfs | zfs; 'auto' or empty for a random pick
# $2 LABEL matrix entry the pick belongs to, e.g. compose/web-app-gitea
# $3 DISTROS space-separated distributions the entry deploys on
# $4 SCOPE node every distro in DISTROS must carry the userland too
# runner DISTROS is ignored; only the kernel decides
set -euo pipefail
STATED="${1:-}"
LABEL="${2:?usage: resolve.sh STATED LABEL DISTROS SCOPE}"
DISTROS="${3:-}"
SCOPE="${4:?usage: resolve.sh STATED LABEL DISTROS SCOPE}"
POOL="ext4 btrfs zfs"
note() { echo "filesystem: $*" >&2; }
kernel_serves() {
local fs="$1"
[ "${fs}" != zfs ] || [ ! -c /dev/zfs ] || return 0
if [ "${fs}" != zfs ] && grep -qw "${fs}" /proc/filesystems 2>/dev/null; then
return 0
fi
if ! command -v modinfo >/dev/null; then
note "${fs} left out: not loaded and modinfo is unavailable to ask for the module"
return 1
fi
modinfo "${fs}" >/dev/null 2>&1 && return 0
note "${fs} left out: this kernel carries no module for it"
return 1
}
userland_for() {
case "$1" in
centos | arch | fedora) echo "ext4 btrfs" ;;
*) echo "ext4 btrfs zfs" ;;
esac
}
every_distro_carries() {
local fs="$1" distro
[ "${SCOPE}" = node ] || return 0
for distro in ${DISTROS}; do
case " $(userland_for "${distro}") " in
*" ${fs} "*) ;;
*) return 1 ;;
esac
done
return 0
}
candidates() {
local kept="" fs
for fs in ${POOL}; do
if ! kernel_serves "${fs}"; then
continue
fi
if ! every_distro_carries "${fs}"; then
note "${fs} left out: not every distro of this entry carries the userland"
continue
fi
kept="${kept} ${fs}"
done
kept="${kept# }"
echo "${kept:-ext4}"
}
if [ -n "${STATED}" ] && [ "${STATED}" != auto ]; then
PICKED="${STATED}"
ORIGIN="stated"
REQUIRED=true
else
POOL="$(candidates)"
read -ra POOL_ENTRIES <<<"${POOL}"
PICKED="$(printf '%s\n' "${POOL_ENTRIES[@]}" | shuf -n1)"
ORIGIN="random out of '${POOL}' on the ${SCOPE}; re-state it to reproduce this run"
REQUIRED=false
fi
echo "filesystem for ${LABEL}: ${PICKED} (${ORIGIN})"
if [ -n "${GITHUB_ENV:-}" ]; then
{
echo "INFINITO_DOCKER_FILESYSTEM=${PICKED}"
echo "INFINITO_DOCKER_FILESYSTEM_REQUIRED=${REQUIRED}"
} >>"${GITHUB_ENV}"
fi
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
echo "- \`${LABEL}\` runs its docker data root on \`${PICKED}\` (${ORIGIN})" \
>>"${GITHUB_STEP_SUMMARY}"
fi