Skip to content

fix(ci): release.yml AUR step — match builder UID to host runner UID … #332

fix(ci): release.yml AUR step — match builder UID to host runner UID …

fix(ci): release.yml AUR step — match builder UID to host runner UID … #332

Workflow file for this run

name: install-flow
on: [push, pull_request]
concurrency:
group: install-flow-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
install-sandbox:
name: install / rootless-docker sandbox
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install Zig
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Build padctl (no libusb — install flow only needs the static binary)
run: zig build -Dlibusb=false
- name: Run install-flow sandbox
run: |
set -euo pipefail
# Stage assets into a directory the container can read
STAGE="$PWD/_ci_stage"
mkdir -p "$STAGE/bin"
cp zig-out/bin/padctl "$STAGE/bin/padctl"
cp -r devices "$STAGE/devices"
cp -r mappings "$STAGE/mappings" 2>/dev/null || true
docker run --rm \
--privileged \
-v "$STAGE:/opt/padctl:ro" \
-v "$PWD:/src:ro" \
debian:12 \
/bin/bash -euo pipefail -c '
# ---- bootstrap ----
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
sudo adduser coreutils procps 2>/dev/null
# Create test user with passwordless sudo
useradd -m -s /bin/bash testuser
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
cp /opt/padctl/bin/padctl /usr/local/bin/padctl
chmod +x /usr/local/bin/padctl
# ---- install ----
# Run as testuser so SUDO_USER is set when they call sudo padctl install.
# udevadm/systemctl calls inside padctl will fail silently (no daemon) —
# that is expected; file installation and ensureUserXdgDirs still execute.
su - testuser -c "sudo SUDO_USER=testuser SUDO_UID=$(id -u testuser) \
HOME=/home/testuser \
/usr/local/bin/padctl install --prefix /usr/local 2>&1"
# ---- invariant checks ----
FAIL=0
check() {
local desc="$1"; shift
if eval "$@"; then
echo " PASS: $desc"
else
echo " FAIL: $desc"
FAIL=1
fi
}
echo "=== install invariants ==="
check "/etc/systemd/user/padctl.service exists" \
"[ -f /etc/systemd/user/padctl.service ]"
check "/etc/systemd/user/padctl.service is a regular file (not symlink)" \
"[ ! -L /etc/systemd/user/padctl.service ]"
check "/home/testuser/.local/state/padctl exists" \
"[ -e /home/testuser/.local/state/padctl ]"
check "/home/testuser/.local/state/padctl is NOT a symlink (issue #139)" \
"[ ! -L /home/testuser/.local/state/padctl ]"
check "/home/testuser/.local/state/padctl is a directory (issue #139 v2)" \
"[ -d /home/testuser/.local/state/padctl ]"
check "/home/testuser/.local/state/padctl owned by testuser" \
"[ \"\$(stat -c %U /home/testuser/.local/state/padctl)\" = testuser ]"
check "/usr/local/bin/padctl installed" \
"[ -f /usr/local/bin/padctl ]"
if [ $FAIL -ne 0 ]; then
echo "=== INSTALL INVARIANTS FAILED ==="
echo "--- /home/testuser tree ---"
find /home/testuser -maxdepth 4 2>/dev/null || true
echo "--- /etc/systemd/user ---"
ls -la /etc/systemd/user/ 2>/dev/null || true
exit 1
fi
# ---- uninstall ----
su - testuser -c "sudo SUDO_USER=testuser SUDO_UID=$(id -u testuser) \
HOME=/home/testuser \
/usr/local/bin/padctl uninstall --prefix /usr/local 2>&1"
echo "=== uninstall invariants ==="
FAIL=0
check "/usr/local/bin/padctl removed after uninstall" \
"[ ! -f /usr/local/bin/padctl ]"
check "/etc/systemd/user/padctl.service removed after uninstall" \
"[ ! -f /etc/systemd/user/padctl.service ]"
if [ $FAIL -ne 0 ]; then
echo "=== UNINSTALL INVARIANTS FAILED ==="
exit 1
fi
echo "=== all invariants passed ==="
'
pkg-deb-smoke:
name: pkg / deb structure invariants
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Build static padctl (musl)
run: zig build -Doptimize=ReleaseSafe -Dtarget=x86_64-linux-musl -Dlibusb=false
- name: Stage release tarball (mirror release.yml build job)
run: |
set -euo pipefail
STAGING=padctl-ci-x86_64-linux-musl
mkdir -p "${STAGING}/bin" "${STAGING}/install"
for bin in padctl padctl-capture padctl-debug; do
[ -f "zig-out/bin/${bin}" ] && cp "zig-out/bin/${bin}" "${STAGING}/bin/"
done
sudo ./zig-out/bin/padctl install --destdir "$PWD/_install_stage" --prefix /usr --no-enable --no-start
cp _install_stage/usr/lib/systemd/user/*.service "${STAGING}/install/"
cp _install_stage/usr/lib/udev/rules.d/*.rules "${STAGING}/install/"
[ -f _install_stage/usr/bin/padctl-reconnect ] && cp _install_stage/usr/bin/padctl-reconnect "${STAGING}/install/"
cp -r devices "${STAGING}/"
cp LICENSE README.md "${STAGING}/"
tar czf "${STAGING}.tar.gz" "${STAGING}"
- name: Build .deb (mirror release.yml build-deb job)
run: |
set -euo pipefail
VERSION=0.0.0-ci
DEB_ARCH=amd64
TARGET=x86_64-linux-musl
TARBALL="padctl-ci-${TARGET}.tar.gz"
PKG="padctl_${VERSION}_${DEB_ARCH}"
DEST="${PWD}/${PKG}"
tar -xzf "${TARBALL}"
SRC="padctl-ci-${TARGET}"
mkdir -p "${DEST}/DEBIAN"
for f in control postinst prerm postrm; do
cp "contrib/deb/DEBIAN-BIN/$f" "${DEST}/DEBIAN/$f"
done
chmod 0644 "${DEST}/DEBIAN/control"
chmod 0755 "${DEST}/DEBIAN/postinst" "${DEST}/DEBIAN/prerm" "${DEST}/DEBIAN/postrm"
sed -i "s/^Version:.*/Version: ${VERSION}/" "${DEST}/DEBIAN/control"
sed -i "s/^Architecture:.*/Architecture: ${DEB_ARCH}/" "${DEST}/DEBIAN/control"
mkdir -p "${DEST}/usr/bin" "${DEST}/usr/lib/systemd/user" \
"${DEST}/usr/lib/udev/rules.d" "${DEST}/usr/share/padctl" \
"${DEST}/usr/share/doc/padctl"
for bin in padctl padctl-capture padctl-debug padctl-reconnect; do
[ -f "${SRC}/bin/${bin}" ] && install -Dm755 "${SRC}/bin/${bin}" "${DEST}/usr/bin/${bin}"
done
[ -f "${SRC}/install/padctl-reconnect" ] && install -Dm755 "${SRC}/install/padctl-reconnect" "${DEST}/usr/bin/padctl-reconnect"
cp "${SRC}/install/"*.service "${DEST}/usr/lib/systemd/user/"
cp "${SRC}/install/"*.rules "${DEST}/usr/lib/udev/rules.d/"
cp -r "${SRC}/devices" "${DEST}/usr/share/padctl/"
install -Dm644 "${SRC}/LICENSE" "${DEST}/usr/share/doc/padctl/copyright"
dpkg-deb --build --root-owner-group "${DEST}" "${PKG}.deb"
- name: Verify .deb file layout
run: |
set -euo pipefail
OUT=$(dpkg-deb -c padctl_0.0.0-ci_amd64.deb)
echo "${OUT}" | grep -q ' \./usr/bin/padctl$' \
|| { echo "FAIL: /usr/bin/padctl missing"; echo "${OUT}"; exit 1; }
echo "${OUT}" | grep -q ' \./usr/lib/systemd/user/padctl\.service$' \
|| { echo "FAIL: padctl.service missing"; echo "${OUT}"; exit 1; }
echo "${OUT}" | grep -q ' \./usr/share/padctl/devices/flydigi/vader5\.toml$' \
|| { echo "FAIL: vader5.toml not under /usr/share/padctl/devices/"; echo "${OUT}"; exit 1; }
DEVICES=$(echo "${OUT}" | grep -c '^.* \./usr/share/padctl/devices/.\+/.\+\.toml$' || true)
[ "${DEVICES}" -ge 5 ] \
|| { echo "FAIL: expected >=5 .toml under devices/, got ${DEVICES}"; echo "${OUT}"; exit 1; }
echo "PASS: .deb structure invariants (${DEVICES} device TOMLs under devices/)"
- name: Install .deb in Debian 12 + post-install structural check
run: |
docker run --rm -v "$PWD:/work:ro" debian:12 /bin/bash -euo pipefail -c '
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends systemd 2>/dev/null
dpkg -i /work/padctl_0.0.0-ci_amd64.deb || (apt-get install -fy && dpkg -i /work/padctl_0.0.0-ci_amd64.deb)
test -d /usr/share/padctl/devices
test -f /usr/share/padctl/devices/flydigi/vader5.toml
test -x /usr/bin/padctl
/usr/bin/padctl --help >/dev/null
'