aboutsummaryrefslogtreecommitdiffstats
path: root/overlay-chroot.sh
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-06-22 12:18:19 +0200
committerDanilo M. <danix@danix.xyz>2026-06-22 12:18:19 +0200
commite39d54ff7dcd17a3ab64c66aba6a2e9f75585485 (patch)
tree3f97a769e8a8dec2df0a0c928956d9b5ba675061 /overlay-chroot.sh
downloadsbo-batch-tester-e39d54ff7dcd17a3ab64c66aba6a2e9f75585485.tar.gz
sbo-batch-tester-e39d54ff7dcd17a3ab64c66aba6a2e9f75585485.zip
Initial commit: sbo-batch-test
Batch-test SlackBuilds against a clean Slackware 15.0 overlay chroot. Non-interactive, local-tree-only dependency resolution with topological sort, per-target disposable overlay, persistent per-package logs, and a color summary. Includes README.md, CLAUDE.md working notes, the reference overlay-chroot.sh, the original spec, and test-logic.sh (resolver + BLOCKED-BY-DEP self-check, 12 checks passing). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'overlay-chroot.sh')
-rw-r--r--overlay-chroot.sh257
1 files changed, 257 insertions, 0 deletions
diff --git a/overlay-chroot.sh b/overlay-chroot.sh
new file mode 100644
index 0000000..332311b
--- /dev/null
+++ b/overlay-chroot.sh
@@ -0,0 +1,257 @@
+#!/bin/bash
+#
+# Copyright 2023-2025 Jeremy Hansen <jebrhansen -at- gmail.com>
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# -----------------------------------------------------------------------------
+
+# Create a chroot from a maintained and updated Slackware stable base to allow
+# easy testing of SlackBuild scripts in a clean environment. Ensure that base
+# is updated every time this script is ran along with updating sbopkg and
+# running sqg to update all queues. Offer to remove chroot files when exiting
+# the chroot.
+
+# Supports passing "cleanup" to remove any existing chroots and their files.
+
+# Supports passing "update" to update the base image with slackpkg and sbopkg
+# and then exiting without starting the chroot.
+
+# TODO
+# Currently empty
+
+# -----------------------------------------------------------------------------
+
+# --------------------------Global Settings Beginning--------------------------
+
+# Set where you want the chroot located and the base name of the folder
+CHROOT_LOCATION=/tmp/
+CHROOT_TEMPLATE_BASE="chroot"
+
+# Set variables for the base image and location of the local Slackware mirror
+VERSION=15.0
+SLACKWARE_BASE=/share/gothrough/sbo-build/$VERSION
+LOCAL_MIRROR=/share/gothrough/slackware-mirrors/slackware64-$VERSION/
+
+# To allow you to open GUI programs from within the chroot, you need to
+# allow "remote" access to the x server. This could possibly open up
+# security issues, but it is limited to non-network local connections.
+# Change to "no" if you want this disabled or pass ACCESS=no to the script.
+ACCESS=${ACCESS:-yes}
+
+# ---------------------------Global Settings Ending----------------------------
+
+# --------------------------Custom Commands Beginning--------------------------
+# This will allow you to add custom aliases or functions into the chroot
+# Make sure you escape single quotes and variables and that all commands are on
+# their own lines
+custom_cmd='
+# Check all listed deps in a .info to see if they are installed
+alias checkdeps=". *.info; for i in \$REQUIRES; do ls /var/log/packages/*SBo* | cut -d/ -f5 | rev | cut -d- -f4- | rev | grep ^\$i$; done"
+'
+# ---------------------------Custom Commands Ending----------------------------
+
+# Check that we're root
+if [ "$EUID" -ne 0 ]; then
+ echo "Please run as root"
+ exit
+fi
+
+# Provide an easy cleanup for older tmp files and exit
+if [ "$1" == "cleanup" ]; then
+
+ for i in "$CHROOT_LOCATION"/"$CHROOT_TEMPLATE_BASE".*; do
+ if [ -d "$i" ]; then
+ echo "Found $i"
+ else
+ echo "No chroots to clean up."
+ exit 2
+ fi
+
+ if mountpoint -q "$i"/chroot/dev/pts; then
+ printf "\tUnmounting %s/chroot/dev/pts\n" "$i"
+ umount "$i"/chroot/dev/pts
+ fi
+ for j in dev proc sys; do
+ if mountpoint -q "$i"/chroot/$j; then
+ printf "\tUnmounting %s/chroot/%s\n" "$i" "$j"
+ umount "$i"/chroot/$j
+ fi
+ done
+
+ if mountpoint -q "$i"/chroot/etc/resolv.conf; then
+ printf "\tUnmounting %s/chroot/etc/resolv.conf\n" "$i"
+ umount "$i"/chroot/etc/resolv.conf
+ fi
+
+ if mountpoint -q "$i"/chroot/var/lib/dbus/machine-id; then
+ printf "\tUnmounting %s/chroot/var/lib/dbus/machine-id\n" "$i"
+ umount "$i"/chroot/var/lib/dbus/machine-id
+ fi
+
+ # umount overlayfs
+ if mountpoint -q "$i"/chroot; then
+ printf "\tUnmounting %s/chroot/%s/chroot\n" "$i" "$j"
+ umount "$i"/chroot
+ fi
+
+ # Remove dirs
+ if [ -d "$i" ]; then
+ printf "\tRemoving %s.\n" "$i"
+ rm -r "$i"
+ fi
+ done
+ echo "Cleanup complete"
+ exit
+fi
+
+# Track the latest updates to prevent attempting to update system
+# packages and rebuilding sbopkg's queues
+touch $SLACKWARE_BASE/last-base-update
+
+# Make sure the base image is up-to-date
+if [ "$(head -n1 $LOCAL_MIRROR/ChangeLog.txt)" != "$(cat $SLACKWARE_BASE/last-base-update)" ]; then
+ for i in "$LOCAL_MIRROR"/patches/packages/*.t?z; do
+ if [ ! -e "$SLACKWARE_BASE"/var/lib/pkgtools/packages/"$(basename "${i%.*}")" ]; then
+ ROOT=$SLACKWARE_BASE upgradepkg --install-new "$i"
+ fi
+ done
+ echo "Slackware has been updated with local mirror."
+ head -n1 $LOCAL_MIRROR/ChangeLog.txt > $SLACKWARE_BASE/last-base-update
+else
+ echo "Slackware is up-to-date with the local mirror."
+fi
+
+# Set up directories for the chroot
+echo "Creating required directories for the overlay"
+TMPDIR=$(mktemp -d "$CHROOT_LOCATION"/"$CHROOT_TEMPLATE_BASE".XXXXX)
+mkdir "$TMPDIR"/{changes,tmp,chroot}
+
+# Mount the overlayfs
+echo "Mounting the overlay"
+mount -t overlay overlay -olowerdir="$SLACKWARE_BASE",upperdir="$TMPDIR"/changes,workdir="$TMPDIR"/tmp "$TMPDIR"/chroot
+
+# Bind mount the pertinent system dirs
+echo "Binding required directories"
+mkdir -p "$TMPDIR"/changes/{dev,proc,sys}
+for i in dev proc sys; do
+ mount -o bind /$i "$TMPDIR"/chroot/$i
+done
+
+# Mount /dev/pts for sudo
+mkdir -p "$TMPDIR"/changes/dev/pts
+mount -o bind /dev/pts "$TMPDIR"/chroot/dev/pts
+
+# Give the chroot internet
+echo "Setting up internet"
+mount -o bind /etc/resolv.conf "$TMPDIR"/chroot/etc/resolv.conf
+chroot "$TMPDIR"/chroot /bin/bash -c "/usr/sbin/update-ca-certificates --fresh > /dev/null"
+
+# Setting up DBUS binding required for certain apps
+echo "Binding DBUS to local machine"
+touch "$TMPDIR"/chroot/var/lib/dbus/machine-id
+mount -o bind /var/lib/dbus/machine-id "$TMPDIR"/chroot/var/lib/dbus/machine-id
+
+# Update sbopkg (if installed) and queues
+# Do it in the chroot to prevent GPG errors, but copy files back to the
+# base image so we only need to do it during updates.
+if [ -e "$SLACKWARE_BASE"/usr/sbin/sbopkg ]; then
+ echo "Checking for SBo updates for sbopkg"
+ # Get the latest changelog date from server
+ SERVDATE="$(wget -qO- https://slackbuilds.org/slackbuilds/15.0/ChangeLog.txt | head -n1)"
+ if [ -z "$SERVDATE" ]; then
+ echo "Upstream address did not provide a changelog."
+ echo "Please validate internet is working and address is correct"
+ echo "This will continue in 5 seconds. Ctrl+C if you'd like to exit."
+ sleep 5
+ fi
+ # Get latest changelog date on local copy
+ LOCALDATE="$(head -n1 $SLACKWARE_BASE/var/lib/sbopkg/SBo/15.0/ChangeLog.txt)"
+ # If they don't match, update sbopkg and run sqg. Copy updates back to base image.
+ if [ "$SERVDATE" != "$LOCALDATE" ]; then
+ chroot "$TMPDIR"/chroot /bin/bash -c "/usr/sbin/sbopkg -r; /usr/sbin/sqg -a"
+ rsync -a --delete "$TMPDIR"/chroot/var/lib/sbopkg/ "$SLACKWARE_BASE"/var/lib/sbopkg
+ rsync -a --delete "$TMPDIR"/chroot/root/.gnupg "$SLACKWARE_BASE"/root/
+ else
+ echo "sbopkg is up-to-date."
+ fi
+fi
+
+# Only set up X server access and launch the chroot if update isn't passed
+if [ "$1" != "update" ]; then
+ # Checking if we can add local connection access
+ if [ "$ACCESS" == "yes" ]; then
+ echo "Setting up X server access"
+ echo "STATUS: $(xhost +local:hosts)"
+ fi
+
+ # Check if there are custom commands to add by checking for text
+ if [[ "$custom_cmd" =~ [a-zA-Z] ]]; then
+ echo "Adding custom commands to chroot's /etc/profile.d/chroot_custom_cmds.sh"
+ echo "$custom_cmd" > "$TMPDIR"/chroot/etc/profile.d/chroot_custom_cmds.sh
+ chmod +x "$TMPDIR"/chroot/etc/profile.d/chroot_custom_cmds.sh
+ fi
+
+ # Let's save the following in the root of the chroot structure to allow
+ # the user to enter into that chroot from another prompt and/or if they
+ # accidentally leave the chroot.
+ # Then we'll just execute the file to actually enter the chroot.
+ cat << EOH > "$TMPDIR"/start-chroot.sh
+#!/bin/bash
+# Time to actually chroot and do our work
+# Need to type 'exit' to leave the chroot and start the cleanup
+# Use custom PS1 so we know we're in the chroot
+echo "Entering chroot. Please type \"exit\" to exit it."
+echo "You can add files to the chroot by placing them in $TMPDIR/chroot/"
+chroot "$TMPDIR"/chroot env PS1="\[\e[41m\]\u\[\e[49m\]@\[\e[33m\]$(basename "$TMPDIR")\[\e[0m\]:\w$ " bash -l
+EOH
+
+ # Start the chroot
+ bash "$TMPDIR"/start-chroot.sh
+fi
+
+# Start cleanup
+
+# Undo bind mounts
+umount "$TMPDIR"/chroot/dev/pts
+for i in dev proc sys; do
+ umount "$TMPDIR"/chroot/$i
+done
+
+umount "$TMPDIR"/chroot/etc/resolv.conf
+umount "$TMPDIR"/chroot/var/lib/dbus/machine-id
+
+# umount overlayfs
+umount "$TMPDIR"/chroot
+
+# Only ask to delete chroot if update isn't passed, otherwise delete without asking
+if [ "$1" != "update" ]; then
+ # Ask if tmp dirs should be removed
+ # Could be kept to review filesystem changes
+ echo -n "Would you like to remove the unneeded overlay directories? y/N "
+ read -r answer
+ # If anything other than y, rm them
+ if ! /usr/bin/grep -qi "y" <<< "$answer"; then
+ echo "Temp overlay dirs will not be removed. They can be found at $TMPDIR."
+ else
+ rm -r "$TMPDIR"
+ fi
+else
+ rm -r "$TMPDIR"
+fi