fix(ci): ensure /dev/fd symlinks exist for mkinitcpio and procsub
Tests / tests (push) Successful in 2m33s
Tests / tests (push) Successful in 2m33s
The chroot's /dev only gains fd/stdin/stdout/stderr symlinks at boot, and
container executors often lack them, which breaks mkinitcpio's preset step
(pipes through /dev/stdin) and bash process substitution
("/dev/fd/63: No such file or directory").
- build-iso workflow: create the links in the executor's /dev, then mount a
fresh devtmpfs and create them there too so the chroot tree is covered
whether the executor's /dev is devtmpfs or a plain tmpfs
- customize_airootfs.sh: self-heal the same links inside the chroot
This commit is contained in:
@@ -43,13 +43,36 @@ jobs:
|
||||
set -euo pipefail
|
||||
pacman -Syu --noconfirm --needed archiso jq
|
||||
|
||||
- name: Ensure /dev/stdin exists for mkinitcpio
|
||||
- name: Ensure /dev/fd symlinks exist for mkinitcpio and procsub
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Docker/container environments may lack /dev/stdin; mkinitcpio needs it
|
||||
[ -e /dev/stdin ] || ln -sf /proc/self/fd/0 /dev/stdin
|
||||
[ -e /dev/stdout ] || ln -sf /proc/self/fd/1 /dev/stdout
|
||||
[ -e /dev/stderr ] || ln -sf /proc/self/fd/2 /dev/stderr
|
||||
# mkinitcpio's preset step pipes through /dev/stdin and bash process
|
||||
# substitution (< <(...)) uses /dev/fd; both break if these symlinks
|
||||
# are missing (they are normally created once at boot by mkinitcpio's
|
||||
# init). Two places need them, so cover both:
|
||||
# 1. the executor's own /dev: mkarchiso reads /dev/stdin on the host
|
||||
# (machine-id, version, pkglist) and the workflow's own scripts use
|
||||
# process substitution here. A no-op if the links already exist.
|
||||
ln -sfn /proc/self/fd /dev/fd
|
||||
ln -sfn /proc/self/fd/0 /dev/stdin
|
||||
ln -sfn /proc/self/fd/1 /dev/stdout
|
||||
ln -sfn /proc/self/fd/2 /dev/stderr
|
||||
# 2. the chroot's /dev: devtmpfs is single-instance, so mounting it
|
||||
# here yields the same tree that pacstrap/arch-chroot expose as
|
||||
# <chroot>/dev. When the executor's /dev is itself devtmpfs (1)
|
||||
# already fixed that tree; this pass is what makes it work when
|
||||
# the executor's /dev is a plain tmpfs or directory instead.
|
||||
d="$(mktemp -d)"
|
||||
trap 'umount "$d" 2>/dev/null || true; rmdir "$d" 2>/dev/null || true' EXIT
|
||||
mount -t devtmpfs devtmpfs "$d"
|
||||
ln -sfn /proc/self/fd "$d/fd"
|
||||
ln -sfn /proc/self/fd/0 "$d/stdin"
|
||||
ln -sfn /proc/self/fd/1 "$d/stdout"
|
||||
ln -sfn /proc/self/fd/2 "$d/stderr"
|
||||
ls -l "$d/fd" "$d/stdin" "$d/stdout" "$d/stderr"
|
||||
umount "$d"
|
||||
rmdir "$d"
|
||||
trap - EXIT
|
||||
|
||||
- name: Build Arch ISO
|
||||
run: |
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# The chroot's /dev is the kernel's single shared devtmpfs, which only gets the
|
||||
# fd/stdin/stdout/stderr symlinks at boot (from mkinitcpio's init). If the
|
||||
# runner environment lacks them, process substitution (< <(...)) and upstream
|
||||
# tools (pacman-key) fail with "… /dev/fd/63: No such file or directory".
|
||||
# Self-heal here; the CI build-iso workflow does the same before pacstrap so
|
||||
# that mkinitcpio's hook (which pipes through /dev/stdin) works too.
|
||||
for _link in "fd:/proc/self/fd" "stdin:/proc/self/fd/0" \
|
||||
"stdout:/proc/self/fd/1" "stderr:/proc/self/fd/2"; do
|
||||
[[ -e "/dev/${_link%%:*}" || -L "/dev/${_link%%:*}" ]] ||
|
||||
ln -sfn "${_link#*:}" "/dev/${_link%%:*}"
|
||||
done
|
||||
unset _link
|
||||
|
||||
# Populate the keyring in the built root from the keyring bundles
|
||||
# (/usr/share/pacman/keyrings, incl. the copied cachyos keyring).
|
||||
# This mirrors the guide; it runs inside the image you are making.
|
||||
|
||||
Reference in New Issue
Block a user