diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 6ba43cf..1c48d82 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -6,10 +6,35 @@ jobs: test: runs-on: ubuntu-latest - + permissions: + contents: write steps: + - name: Maximize build space + run: | + df -h + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/share/swift + sudo rm -rf /usr/share/java + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc + sudo rm -rf /opt/hostedtoolcache + sudo rm -rf /opt/az + df -h - uses: actions/checkout@v3 + - name: Fix files permission + run: | + chmod +x frzr* __frzr* - name: Run tests run: | cd test ./run.sh + - name: Test Deployment creation & installation + run: | + docker run --name test_deploy -u root --rm --entrypoint=/workdir/test/test-deploy.sh -v $(pwd):/workdir -v /dev:/dev --privileged archlinux:latest + - name: Test Install + run: | + docker run --name test_install -u root --rm --entrypoint=/workdir/test/test-install.sh -v $(pwd):/workdir -v /dev:/dev --privileged archlinux:latest + - name: Test Removal + run: | + docker run --name test_removal -u root --rm --entrypoint=/workdir/test/test-removal.sh -v $(pwd):/workdir -v /dev:/dev --privileged archlinux:latest + diff --git a/__frzr b/__frzr index 8117e93..a899563 100644 --- a/__frzr +++ b/__frzr @@ -48,7 +48,7 @@ write_tracker_file() { local running_user=$(whoami) if [ ! -f "${TRACKER_FILE_PATH}" ]; then touch "${TRACKER_FILE_PATH}" - chown :frzr "${TRACKER_FILE_PATH}" + chown $UID:379 "${TRACKER_FILE_PATH}" chmod g+w "${TRACKER_FILE_PATH}" fi @@ -308,18 +308,30 @@ install_image() { if [ -d "${deploy_path}" ]; then if [[ "${IMG_FILE##*.}" == "img" ]]; then - btrfs receive --quiet ${DEPLOY_PATH} <${IMG_FILE} - echo "OK" + if btrfs receive --quiet "${DEPLOY_PATH}" < "${IMG_FILE}"; then + echo "OK" + else + echo "ERROR: Could not install raw image '${IMG_FILE}' to '${DEPLOY_PATH}'" + fi elif [[ "${IMG_FILE##*.}" == "zst" ]]; then - zstd -d -c ${IMG_FILE} | btrfs receive --quiet ${DEPLOY_PATH} - echo "OK" + if zstd -d -c "${IMG_FILE}" | btrfs receive --quiet "${DEPLOY_PATH}"; then + echo "OK" + else + echo "ERROR: Could not install zstd image '${IMG_FILE}' to '${DEPLOY_PATH}'" + fi elif [[ "${IMG_FILE##*.}" == "xz" ]]; then if [[ "${IMG_FILE}" == *".tar.xz" ]]; then - tar xfO ${IMG_FILE} | btrfs receive --quiet ${DEPLOY_PATH} - echo "OK" + if tar xfO ${IMG_FILE} | btrfs receive --quiet "${DEPLOY_PATH}"; then + echo "OK" + else + echo "ERROR: Could not install tar.xz image '${IMG_FILE}' to '${DEPLOY_PATH}'" + fi else - xz -dc ${IMG_FILE} | btrfs receive --quiet ${DEPLOY_PATH} - echo "OK" + if xz -dc "${IMG_FILE}" | btrfs receive --quiet "${DEPLOY_PATH}"; then + echo "OK" + else + echo "ERROR: Could not install xz image '${IMG_FILE}' to '${DEPLOY_PATH}'" + fi fi else echo "ERROR: Unsupported file format for file '${IMG_FILE}'" diff --git a/__frzr-bootloader b/__frzr-bootloader index b6b0814..c506747 100644 --- a/__frzr-bootloader +++ b/__frzr-bootloader @@ -32,12 +32,11 @@ frzr_bootloader() { continue fi - MOUNT_PATH="/frzr_root" # Make sure the frzr_root is mounted during the deployment procedure # this code is based on the fact that when a btrfs filesystem is created # the default subvolid that is created contextually has the ID set to 256 # also as a matter of fact in btrfs is impossible to change subvolumes IDs - if mount | grep -Fq "${MOUNT_PATH}"; then + if mount | grep -Fq "on ${MOUNT_PATH}"; then local MOUNTED_MOUNT_PATH="no" else MOUNT_PATH="/tmp/frzr_root" @@ -58,9 +57,9 @@ frzr_bootloader() { fi # Make sure the EFI partition is mounted during the deployment procedure - EFI_MOUNT_PATH="${MOUNT_PATH}/efi" - - if mount | grep -Fq "${EFI_MOUNT_PATH}"; then + TASK_MSG="Checking for EFI partition" + send_data + if mount | grep -Fq "on ${EFI_MOUNT_PATH}"; then local MOUNTED_EFI_MOUNT_PATH="no" else mkdir -p "${EFI_MOUNT_PATH}" diff --git a/__frzr-bootstrap b/__frzr-bootstrap index 0d7b0c6..84cc351 100644 --- a/__frzr-bootstrap +++ b/__frzr-bootstrap @@ -168,8 +168,8 @@ fresh_install() { local root_part=$(fdisk -o Device --list ${disk} | grep "^${disk}.*${ROOT_PART_NUMBER}$") mkfs.btrfs -L frzr_root -f ${root_part} local root_uuid=$(blkid -s UUID -o value "${root_part}") - mount ${root_part} ${frzr_root} # mount rootfs - mkdir -p ${frzr_root}/efi # prepare to mount vfat + mount -t btrfs -o compress-force=zstd:15 "${root_part}" "${frzr_root}" # mount rootfs + mkdir -p "${frzr_root}/efi" # prepare to mount vfat #echo "${root_uuid}" > "${frzr_root}/root_uuid" btrfs subvolume create ${frzr_root}/var mkdir -p "${frzr_root}/etc" @@ -264,29 +264,40 @@ frzr_bootstrap() { echo "Checking for drives connected to the system" MOUNT_PATH=/tmp/frzr_root - device_list=() - device_output=$(lsblk --list -n -o name,model,size,type | grep disk | tr -s ' ' '\t') - while read -r line; do - name=/dev/$(echo "$line" | cut -f 1) - model=$(echo "$line" | cut -f 2) - size=$(echo "$line" | cut -f 3) - device_list+=($name) - device_list+=("$model ($size)") - done <<<"$device_output" - DISK=$(whiptail --nocancel --menu "Choose a disk to install to:" 20 50 5 "${device_list[@]}" 3>&1 1>&2 2>&3) + if [ -z "${DISK}" ]; then + device_list=() + device_output=$(lsblk --list -n -o name,model,size,type | grep disk | tr -s ' ' '\t') + while read -r line; do + name=/dev/$(echo "$line" | cut -f 1) + model=$(echo "$line" | cut -f 2) + size=$(echo "$line" | cut -f 3) + device_list+=($name) + device_list+=("$model ($size)") + done <<<"$device_output" + DISK=$(whiptail --nocancel --menu "Choose a disk to install to:" 20 50 5 "${device_list[@]}" 3>&1 1>&2 2>&3) + else + echo "specified disk is '$DISK'" + fi echo "Checking for existing FRZR deployments" # Checking for existing installation if (lsblk -o label ${DISK} | grep -q frzr_efi); then echo "Existing installation found" - if (whiptail --yesno --yes-button "Repair" --no-button "Clean" "WARNING: $DISK appears to already have a system installed. Would you like to repair it or do a clean install?\n\nNOTE: A clean install will delete everything on the disk, but a repair install will preserve your user data." 13 70); then - echo "User chose to do a repair install" + if [ "$REPAIR_INSTALL" = "1"]; then REPAIR_INSTALL=1 STATE="REPAIR" - else - echo "User chose to do a clean install" + elif [ "$REPAIR_INSTALL" = "0"]; then STATE="FORMAT" + else + if (whiptail --yesno --yes-button "Repair" --no-button "Clean" "WARNING: $DISK appears to already have a system installed. Would you like to repair it or do a clean install?\n\nNOTE: A clean install will delete everything on the disk, but a repair install will preserve your user data." 13 70); then + echo "User chose to do a repair install" + REPAIR_INSTALL=1 + STATE="REPAIR" + else + echo "User chose to do a clean install" + STATE="FORMAT" + fi fi else echo "Existing installation not found" diff --git a/__frzr-deploy b/__frzr-deploy index 5b59713..9bcfb2d 100644 --- a/__frzr-deploy +++ b/__frzr-deploy @@ -38,16 +38,19 @@ frzr_deploy() { continue fi - TASK_MSG="Checking if the system has booted via UEFI" - send_data - check_uefi_result=$(check_uefi) - if echo "${check_uefi_result}" | grep -Fq 'ERROR'; then - TASK_ERROR=1 - TASK_ERROR_MSG="UEFI boot check failed: ${check_uefi_result}" - STATE="FAIL" - send_data - continue - fi + # Since this code is tested in GitHub CI it is important to to disable the UEFI test in that scenario + if [ -z "${SKIP_UEFI_CHECK}" ]; then + TASK_MSG="Checking if the system has booted via UEFI" + send_data + check_uefi_result=$(check_uefi) + if echo "${check_uefi_result}" | grep -Fq 'ERROR'; then + TASK_ERROR=1 + TASK_ERROR_MSG="UEFI boot check failed: ${check_uefi_result}" + STATE="FAIL" + send_data + continue + fi + fi # Check if any updates are available and preserve FRZR parameters while (("$#")); do @@ -75,8 +78,8 @@ frzr_deploy() { # keep only the first param as source FRZR_SOURCE="${FRZR_PARAMS%% *}" - if frzr-release > /dev/null; then - CURRENT=`frzr-release` + if "${BASH_SOURCE%/*}/frzr-release" > /dev/null; then + CURRENT=$("${BASH_SOURCE%/*}/frzr-release") fi STATE="BEGIN" @@ -85,7 +88,7 @@ frzr_deploy() { TASK_STATE="BEGIN" send_data - local version=$(frzr-version) + local version=$("${BASH_SOURCE%/*}/frzr-version") if echo "${version}" | grep -Fq "ERROR"; then TASK_ERROR=1 TASK_ERROR_MSG="Could not fetch frzr version: ${version}" @@ -98,8 +101,7 @@ frzr_deploy() { # this code is based on the fact that when a btrfs filesystem is created # the default subvolid that is created contextually has the ID set to 256 # also as a matter of fact in btrfs is impossible to change subvolumes IDs - MOUNT_PATH="/frzr_root" - if mount | grep -Fq "${MOUNT_PATH}"; then + if mount | grep -Fq "on ${MOUNT_PATH}"; then local MOUNTED_MOUNT_PATH="no" else MOUNT_PATH="/tmp/frzr_root" @@ -135,12 +137,9 @@ frzr_deploy() { fi # Make sure the EFI partition is mounted during the deployment procedure - EFI_MOUNT_PATH="${MOUNT_PATH}/efi" - TASK_MSG="Preparing '${EFI_MOUNT_PATH}' to be used as the EFI System path" send_data - - if mount | grep -Fq "${EFI_MOUNT_PATH}"; then + if mount | grep -Fq "on ${EFI_MOUNT_PATH}"; then local MOUNTED_EFI_MOUNT_PATH="no" else mkdir -p "${EFI_MOUNT_PATH}" @@ -170,7 +169,6 @@ frzr_deploy() { TASK_WARNING=1 TASK_WARNING_MSG="Could not retrieve deployment to keep: ${CURRENT}" send_data - continue fi local default_btrfs_subvolid_cmd_res=$(btrfs subvolume get-default "${MOUNT_PATH}") @@ -182,7 +180,7 @@ frzr_deploy() { local removal_deployment=$(basename "${deployment_to_be_removed}") local removal_deployment_subvolid=$(btrfs_subvol_get_id "${deployment_to_be_removed}") - if echo "${removal_deployment}" | grep -Fq "${CURRENT}"; then + if echo "${removal_deployment}" | grep -Fq "${CURRENT}" && ! echo "${CURRENT}" | grep -Fq "ERROR"; then TASK_MSG="Deployment '${removal_deployment}' will be kept: is the current deployment" send_data elif echo "${removal_deployment_subvolid}" | grep -Fq "ERROR"; then @@ -212,16 +210,18 @@ frzr_deploy() { done # Execute deployment removal scripts - TASK_MSG="Executing removal hooks" - send_data - local deployment_removal_hooks=$(execute_removal "${removal_deployment}" "${deployment_to_be_removed}" "${MOUNT_PATH}" "${version}") - if echo "${deployment_removal_hooks}" | grep -Fq "ERROR"; then - TASK_ERROR=1 - TASK_ERROR_MSG="Removal hook on subvolume '${deployment_to_be_removed}' failed: ${deployment_removal_hooks}" - STATE="FAIL" - send_data - continue - fi + if [ -d "${deployment_to_be_removed}/usr/lib/frzr.d" ]; then + TASK_MSG="Executing removal hooks" + send_data + local deployment_removal_hooks=$(execute_removal "${removal_deployment}" "${deployment_to_be_removed}" "${MOUNT_PATH}" "${version}") + if echo "${deployment_removal_hooks}" | grep -Fq "ERROR"; then + TASK_ERROR=1 + TASK_ERROR_MSG="Removal hook on subvolume '${deployment_to_be_removed}' failed: ${deployment_removal_hooks}" + STATE="FAIL" + send_data + continue + fi + fi # Delete the deployment btrfs subvolume local deployment_removal_result=$(btrfs_subvolume_simple_delete "${DEPLOY_PATH}/${removal_deployment}") @@ -270,6 +270,11 @@ frzr_deploy() { NAME=$(echo "${FILE_NAME}" | cut -f 1 -d '.') SUBVOL="${DEPLOY_PATH}/${NAME}" IMG_FILE="${FRZR_SOURCE}" + elif [[ "$FRZR_SOURCE" == *".img.xz" ]]; then + FILE_NAME=$(basename ${FRZR_SOURCE}) + NAME=$(echo "${FILE_NAME}" | cut -f 1 -d '.') + SUBVOL="${DEPLOY_PATH}/${NAME}" + IMG_FILE="${FRZR_SOURCE}" elif [[ "$FRZR_SOURCE" == *".img" ]]; then FILE_NAME=$(basename ${FRZR_SOURCE}) NAME=$(echo "${FILE_NAME}" | cut -f 1 -d '.') @@ -361,21 +366,32 @@ frzr_deploy() { STATE="CHECKSUM" ;; "CHECKSUM") + # If the image is a local one try to fetch its sha256sum + if [ -z "$EXPECTED_CHECKSUM" ] && [ -f "${IMG_FILE}.sha256" ]; then + EXPECTED_CHECKSUM=$(cat "${IMG_FILE}.sha256") + fi + TASK_STATE="CHECKSUM" TASK_MSG="Verifying if checksums match" send_data ACTUAL_CHECKSUM=$(sha256sum "${IMG_FILE}" | cut -d' ' -f 1) - if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then - rm -f "${IMG_FILE}" - - # We can attempt to redownload the image again here instead of aborting like the original behavior - TASK_ERROR=1 - TASK_ERROR_MSG="Checksum does not match" - STATE="FAIL" + if [ ! -z "$EXPECTED_CHECKSUM" ]; then + if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then + rm -f "${IMG_FILE}" + + # We can attempt to redownload the image again here instead of aborting like the original behavior + TASK_ERROR=1 + TASK_ERROR_MSG="Checksum does not match" + STATE="FAIL" + send_data + continue + fi + else + TASK_WARNING=1 + TASK_WARNING_MSG="Could not fetch the deployment checksum" send_data - continue - fi - TASK_TRACKER=1 # Tell any listeners this task was completed, I'm not sure this variable will be needed in the end + fi + TASK_TRACKER=1 # Tell any listeners this task was completed, I'm not sure this variable will be needed in the end send_data STATE="EXTRACT" @@ -489,7 +505,7 @@ frzr_deploy() { send_data # This is used to update the EFI partition: setting up systemd-boot (or whatever else bootlader might be supported) to boot the new deployment - local efi_update_result=$(frzr-bootloader "${NAME}") + local efi_update_result=$("${BASH_SOURCE%/*}/frzr-bootloader" "${NAME}") if echo "${efi_update_result}" | grep -Fq 'ERROR'; then # bootloader configuration could not be updated TASK_ERROR=1 diff --git a/__frzr-envars b/__frzr-envars index bf6df0e..923d1c6 100644 --- a/__frzr-envars +++ b/__frzr-envars @@ -8,15 +8,26 @@ if [ -z $TARGET ]; then TARGET="" # Set to the target deployment channel. This should only be set by the installer script fi -if [ -z $LOCAL_INSTALL ]; then +if [ -z "$LOCAL_INSTALL" ]; then LOCAL_INSTALL=0 # Set to 1 to perform a local media install. This should be set by the installer script fi UPGRADE=0 -REPAIR_INSTALL=0 # Set to 1 if you want to do a repair install. This should be set by frzr-bootstrap later if an existing install is found. + +if [ -z "$REPAIR_INSTALL" ]; then + REPAIR_INSTALL=0 # Set to 1 if you want to do a repair install. This should be set by frzr-bootstrap later if an existing install is found. +fi + NAME="" # Name of the OS to be deployed -EFI_MOUNT_PATH="" # EFI mount path -MOUNT_PATH="" # This is set as /tmp/frzr_root/ in the installer and /frzr_root during upgrades + +if [ -z "$MOUNT_PATH" ]; then + MOUNT_PATH="/frzr_root" # This is set as /tmp/frzr_root/ in the installer and /frzr_root during upgrades +fi + +if [ -z "$EFI_MOUNT_PATH" ]; then + EFI_MOUNT_PATH="${MOUNT_PATH}/efi" # EFI mount path +fi + SUBVOL="" DEPLOY_PATH="" # ${MOUNT_PATH}/deployments FRZR_CHECK_UPDATE=0 diff --git a/__frzr-kernel b/__frzr-kernel index ae7486e..495c843 100644 --- a/__frzr-kernel +++ b/__frzr-kernel @@ -13,13 +13,11 @@ frzr_kernel() { while $RUNNING; do case "$STATE" in "BEGIN") - MOUNT_PATH="/frzr_root" - # Make sure the frzr_root is mounted during the deployment procedure # this code is based on the fact that when a btrfs filesystem is created # the default subvolid that is created contextually has the ID set to 256 # also as a matter of fact in btrfs is impossible to change subvolumes IDs - if mount | grep -Fq "${MOUNT_PATH}"; then + if mount | grep -Fq "on ${MOUNT_PATH}"; then local MOUNTED_MOUNT_PATH="no" else MOUNT_PATH="/tmp/frzr_root" @@ -37,9 +35,7 @@ frzr_kernel() { fi # Make sure the EFI partition is mounted during the deployment procedure - EFI_MOUNT_PATH="${MOUNT_PATH}/efi" - - if mount | grep -Fq "${EFI_MOUNT_PATH}"; then + if mount | grep -Fq "on ${EFI_MOUNT_PATH}"; then local MOUNTED_EFI_MOUNT_PATH="no" else sudo mkdir -p "${EFI_MOUNT_PATH}" @@ -371,7 +367,7 @@ frzr_kernel() { fi # This is used to update the EFI partition: setting up systemd-boot (or whatever else bootlader might be supported) to boot the new deployment - local efi_update_result=$(frzr-bootloader) + local efi_update_result=$("${BASH_SOURCE%/*}/frzr-bootloader") if echo "${efi_update_result}" | grep -Fq 'ERROR'; then # bootloader configuration could not be updated TASK_ERROR=1 diff --git a/__frzr-unlock b/__frzr-unlock index f5244f3..49b563a 100644 --- a/__frzr-unlock +++ b/__frzr-unlock @@ -52,15 +52,14 @@ frzr_unlock() { done # keep only the first param as source - FRZR_SOURCE="${FRZR_PARAMS%% *}" - if frzr-release > /dev/null; then - CURRENT=`frzr-release` - fi + if "${BASH_SOURCE%/*}/frzr-release" > /dev/null; then + CURRENT=$("${BASH_SOURCE%/*}/frzr-release") + fi STATE="BEGIN" ;; "BEGIN") - FRZR_VERSION=$(frzr-version) + FRZR_VERSION=$("${BASH_SOURCE%/*}/frzr-version") if echo "${FRZR_VERSION}" | grep -Fq "ERROR"; then TASK_ERROR=1 TASK_ERROR_MSG="Could not fetch frzr version: ${FRZR_VERSION}" @@ -73,7 +72,6 @@ frzr_unlock() { # this code is based on the fact that when a btrfs filesystem is created # the default subvolid that is created contextually has the ID set to 256 # also as a matter of fact in btrfs is impossible to change subvolumes IDs - MOUNT_PATH="/frzr_root" if ! mountpoint -q "${MOUNT_PATH}" && ls -1 /dev/disk/by-label | grep frzr_root > /dev/null; then MOUNT_PATH="/tmp/frzr_root" #TASK_MSG="Preparing '${MOUNT_PATH}' to be used as the main subvolume mount path" @@ -122,17 +120,24 @@ frzr_unlock() { STATE="UNLOCK" ;; "UNLOCK") - # set rootfs btrfs subvolume to read-write mode - UNLOCK_RESULT=$(execute_unlock "${NAME}" "${SUBVOL}" "${MOUNT_PATH}" "${FRZR_VERSION}") - if echo "${UNLOCK_RESULT}" | grep -Fq 'ERROR'; then - echo "frzr deployment ${NAME} unlock failed: ${UNLOCK_RESULT}" + if [ -d "${SUBVOL}/usr/lib/frzr.d" ]; then + # set rootfs btrfs subvolume to read-write mode + UNLOCK_RESULT=$(execute_unlock "${NAME}" "${SUBVOL}" "${MOUNT_PATH}" "${FRZR_VERSION}") + if echo "${UNLOCK_RESULT}" | grep -Fq 'ERROR'; then + echo "frzr deployment ${NAME} unlock failed: ${UNLOCK_RESULT}" + STATE="FAIL" + continue + fi + + systemctl daemon-reload + + STATE="SUCCESS" + else + TASK_ERROR=1 + TASK_ERROR_MSG="Could not find unlock migrations for deployment '${NAME}', '${SUBVOL}/usr/lib/frzr.d' does not exists" STATE="FAIL" continue fi - - systemctl daemon-reload - - STATE="SUCCESS" ;; "SUCCESS") # This state should only be used if the unlock completed without errors diff --git a/frzr-release b/frzr-release index 791bfb3..88b2513 100755 --- a/frzr-release +++ b/frzr-release @@ -1,10 +1,7 @@ #! /bin/bash -set -e - if [ -e "/build_info" ]; then cat "/build_info" | head -1 else echo "ERROR: not currently running a frzr deployment" - exit 1 fi diff --git a/output/.gitkeep b/output/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/run.sh b/test/run.sh index aff4bff..5d99294 100755 --- a/test/run.sh +++ b/test/run.sh @@ -1,5 +1,8 @@ #! /bin/bash +set -e +set -x + source ../__frzr check() { diff --git a/test/test-deploy.sh b/test/test-deploy.sh new file mode 100755 index 0000000..1393cba --- /dev/null +++ b/test/test-deploy.sh @@ -0,0 +1,105 @@ +#! /bin/bash + +set -e +set -x + +# Prepare the image +pacman -Sy --noconfirm +pacman -S --noconfirm archlinux-keyring +pacman-key --init +pacman-key --populate archlinux +pacman -Syu --noconfirm + +pacman -S --noconfirm parted btrfs-progs file libnewt dosfstools jq util-linux zstd xz curl wget arch-install-scripts + +# Create the frzr group +groupadd -g 379 frzr +usermod -a -G frzr $(whoami) + + +# Define variables +export IMG_FILE="archlinux.img" +export IMG_SIZE="4G" +export MOUNT_POINT="/mnt/arch" +export ARCH_MIRRORLIST="Server = http://mirror.rackspace.com/archlinux/\$repo/os/\$arch" +export TARGET_FILENAME="/workdir/output/archlinux.img.xz" + +# Create an empty img file +truncate -s $IMG_SIZE $IMG_FILE + +# Format the img file as btrfs +mkfs.btrfs $IMG_FILE + +# Create the mount directory +mkdir -p $MOUNT_POINT + +# Mount the img file +mount -o loop $IMG_FILE $MOUNT_POINT + +btrfs subvol create $MOUNT_POINT/archlinux + +# Bootstrap Arch Linux into the img file +yes | pacstrap $MOUNT_POINT/archlinux base base-devel linux linux-firmware mkinitcpio + +# Generate fstab +#genfstab -U $MOUNT_POINT >> $MOUNT_POINT/archlinux/etc/fstab + +echo "archlinux-frzr" > $MOUNT_POINT/archlinux/build_info + +# Make the subvolume read-only (btrfs send cannot work on rw/ subvolumes) +btrfs property set -fts $MOUNT_POINT/archlinux ro true + +# Create the deployment file +if btrfs send $MOUNT_POINT/archlinux | xz -e -9 --memory=95% -T0 > $TARGET_FILENAME; then + + # Unmount the img file + umount $MOUNT_POINT + + rm -rf $IMG_FILE + + # Perform the deployment + + export FILENAME=install_deploy.img + export BUILD_DIR="/workdir/output" + export BUILD_IMG="$BUILD_DIR/$FILENAME" + + mkdir -p "$BUILD_DIR" + dd if=/dev/zero of=$BUILD_IMG bs=1M count=8192 + + # Associate the image file with a loop device + losetup -fP "$BUILD_IMG" + + # Find the loop device associated with the image file + MOUNTED_DEVICE=$(losetup -a | grep "$FILENAME" | cut -d ' ' -f 1 | sed 's/://') + + export DISK="$MOUNTED_DEVICE" + export SWAP_GIB=0 + bash /workdir/frzr bootstrap + + export SKIP_UEFI_CHECK="yes" + export MOUNT_PATH="/tmp/frzr_root" + export EFI_MOUNT_PATH="/tmp/frzr_root/efi" + export FRZR_SKIP_CHECK="yes" + export SYSTEMD_RELAX_ESP_CHECKS=1 + + # deploy archlinux + bash /workdir/frzr deploy $TARGET_FILENAME + + # old releases used an older frzr + INSTALLED_RELEASE=$(cat "$MOUNT_PATH/deployments/archlinux/build_info" | head -n 1) + + # Umount the loopback device + losetup -d "$MOUNTED_DEVICE" + + # Remove the file + rm -f $BUILD_IMG + rm -f $TARGET_FILENAME + + if [ "$INSTALLED_RELEASE" = "archlinux-frzr" ]; then + echo "VERIFIED" + else + exit 1 + fi +else + exit 1 +fi \ No newline at end of file diff --git a/test/test-install.sh b/test/test-install.sh new file mode 100644 index 0000000..98e4c8b --- /dev/null +++ b/test/test-install.sh @@ -0,0 +1,56 @@ +#! /bin/bash + +set -e +set -x + +# Prepare the image +pacman -Sy --noconfirm +pacman -S --noconfirm archlinux-keyring +pacman-key --init +pacman-key --populate archlinux +pacman -Syu --noconfirm + +pacman -S --noconfirm parted btrfs-progs file libnewt dosfstools jq util-linux zstd xz curl wget arch-install-scripts + +# Create the frzr group +groupadd -g 379 frzr +usermod -a -G frzr $(whoami) + +export FILENAME=install_image.img +export BUILD_DIR="/workdir/output" +export BUILD_IMG="$BUILD_DIR/$FILENAME" + +mkdir -p "$BUILD_DIR" +dd if=/dev/zero of=$BUILD_IMG bs=1M count=8192 + +# Associate the image file with a loop device +losetup -fP "$BUILD_IMG" + +# Find the loop device associated with the image file +MOUNTED_DEVICE=$(losetup -a | grep "$FILENAME" | cut -d ' ' -f 1 | sed 's/://') + +export DISK="$MOUNTED_DEVICE" +export SWAP_GIB=0 +bash /workdir/frzr bootstrap + +export SKIP_UEFI_CHECK="yes" +export MOUNT_PATH="/tmp/frzr_root" +export EFI_MOUNT_PATH="/tmp/frzr_root/efi" +export FRZR_SKIP_CHECK="yes" +export SYSTEMD_RELAX_ESP_CHECKS=1 + +# deploy chimeraos-45-1_9a95912 +bash /workdir/frzr deploy chimeraos/chimeraos:45_1 + +# old releases used an older frzr +INSTALLED_RELEASE=$(cat "$MOUNT_PATH/deployments/chimeraos-45-1_9a95912/build_info" | head -n 1) + +# Umount the loopback device +losetup -d "$MOUNTED_DEVICE" + +# Remove the file +rm -f $BUILD_IMG + +if ! echo "$INSTALLED_RELEASE" | grep -Fq "chimeraos-45"; then + exit 1 +fi \ No newline at end of file diff --git a/test/test-removal.sh b/test/test-removal.sh new file mode 100755 index 0000000..27fe382 --- /dev/null +++ b/test/test-removal.sh @@ -0,0 +1,79 @@ +#! /bin/bash + +set -e +set -x + +# Prepare the image +pacman -Sy --noconfirm +pacman -S --noconfirm archlinux-keyring +pacman-key --init +pacman-key --populate archlinux +pacman -Syu --noconfirm + +pacman -S --noconfirm parted btrfs-progs file libnewt dosfstools jq util-linux zstd xz curl wget arch-install-scripts + +# Create the frzr group +groupadd -g 379 frzr +usermod -a -G frzr $(whoami) + +export FILENAME=removal_image.img +export BUILD_DIR="/workdir/output" +export BUILD_IMG="$BUILD_DIR/$FILENAME" + +mkdir -p "$BUILD_DIR" +dd if=/dev/zero of=$BUILD_IMG bs=1M count=16384 + +# Associate the image file with a loop device +losetup -fP "$BUILD_IMG" + +# Find the loop device associated with the image file +MOUNTED_DEVICE=$(losetup -a | grep "$FILENAME" | cut -d ' ' -f 1 | sed 's/://') + +export DISK="$MOUNTED_DEVICE" +export SWAP_GIB=0 +bash /workdir/frzr bootstrap + +export SKIP_UEFI_CHECK="yes" +export MOUNT_PATH="/tmp/frzr_root" +export EFI_MOUNT_PATH="/tmp/frzr_root/efi" +export FRZR_SKIP_CHECK="yes" +export SYSTEMD_RELAX_ESP_CHECKS=1 + +# deploy chimeraos-43_6978095 +bash /workdir/frzr deploy chimeraos/chimeraos:43 + +if [ ! -d "$MOUNT_PATH/deployments/chimeraos-43_6978095" ]; then + exit 1 +fi + +# deploy chimeraos-44_c3670dd +bash /workdir/frzr deploy chimeraos/chimeraos:44 + +if [ ! -d "$MOUNT_PATH/deployments/chimeraos-43_6978095" ] || [ ! -d "$MOUNT_PATH/deployments/chimeraos-44_c3670dd" ]; then + exit 1 +fi + +ls -lah "$MOUNT_PATH/deployments" + +# deploy chimeraos-45_1e44050 +bash /workdir/frzr deploy chimeraos/chimeraos:45 + +if [ -d "$MOUNT_PATH/deployments/chimeraos-43_6978095" ] || [ ! -d "$MOUNT_PATH/deployments/chimeraos-44_c3670dd" ] || [ ! -d "$MOUNT_PATH/deployments/chimeraos-45_1e44050" ]; then + exit 1 +fi + +ls -lah "$MOUNT_PATH/deployments" + +# deploy chimeraos-45-1_9a95912 +bash /workdir/frzr deploy chimeraos/chimeraos:45_1 + +if [ -d "$MOUNT_PATH/deployments/chimeraos-44_c3670dd" ] || [ ! -d "$MOUNT_PATH/deployments/chimeraos-45_1e44050" ] || [ ! -d "$MOUNT_PATH/deployments/chimeraos-45-1_9a95912" ]; then + exit 1 +fi + +# Umount the loopback device +losetup -d "$MOUNTED_DEVICE" + +# Remove the file +rm -f $BUILD_IMG +