diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cdab935..5a7d0a5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,87 +12,57 @@ concurrency: cancel-in-progress: true jobs: - rubik: - env: - script: "./tmp/build/install_rubikpi3.sh" - base_image: "https://people.canonical.com/~platform/images/qualcomm-iot/rubikpi3/ubuntu-server-24.04/x00/ubuntu-24.04-preinstalled-server-arm64+rubikpi3-20250912-127.yaml" - - runs-on: ubuntu-24.04 - - name: "Build for RubikPi3" - - steps: - - uses: actions/checkout@v4.1.7 - with: - fetch-depth: 0 - - name: Fetch tags - run: git fetch --tags --force - - - name: Build rubikpi3 with mounting - run: | - chmod +x ./mount_rubikpi3.sh - ./mount_rubikpi3.sh ${{ env.base_image }} ${{ env.script }} ${{ github.ref_name }} - - - name: Compress built image - run: | - tar -I 'xz -T0' -cf photonvision_rubikpi3.tar.xz photonvision_rubikpi3 --checkpoint=10000 --checkpoint-action=echo='%T' - - - uses: actions/upload-artifact@v4.3.4 - with: - name: photonvision_rubikpi3.tar.xz - path: photonvision_rubikpi3.tar.xz - if-no-files-found: error - retention-days: 1 - build: - runs-on: ubuntu-24.04 - + runs-on: ubuntu-24.04-arm strategy: fail-fast: false matrix: include: - name: limelight - script: ./install_limelight.sh + script: install_limelight.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: limelight3 - script: ./install_limelight3.sh + script: install_limelight3.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: limelight3g - script: ./install_limelight3g.sh + script: install_limelight3g.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: limelight4 - script: ./install_limelight4.sh + script: install_limelight4.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: raspi - script: ./install_pi.sh + script: install_pi.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: raspi_dev - script: ./install_dev_pi.sh + script: install_dev_pi.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: snakeyes - script: ./install_snakeyes.sh + script: install_snakeyes.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: luma_p1 - script: ./install_luma_p1.sh + script: install_luma_p1.sh base_image: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz - name: opi5 script: ./install_opi5.sh base_image: https://github.com/Joshua-Riek/ubuntu-rockchip/releases/download/v2.4.0/ubuntu-24.04-preinstalled-server-arm64-orangepi-5.img.xz - name: opi5b - script: ./install_opi5.sh + script: install_opi5.sh base_image: https://github.com/Joshua-Riek/ubuntu-rockchip/releases/download/v2.4.0/ubuntu-24.04-preinstalled-server-arm64-orangepi-5b.img.xz - name: opi5plus - script: ./install_opi5.sh + script: install_opi5.sh base_image: https://github.com/Joshua-Riek/ubuntu-rockchip/releases/download/v2.4.0/ubuntu-24.04-preinstalled-server-arm64-orangepi-5-plus.img.xz - name: opi5pro - script: ./install_opi5.sh + script: install_opi5.sh base_image: https://github.com/Joshua-Riek/ubuntu-rockchip/releases/download/v2.4.0/ubuntu-24.04-preinstalled-server-arm64-orangepi-5-pro.img.xz - name: opi5max - script: ./install_opi5.sh + script: install_opi5.sh base_image: https://github.com/Joshua-Riek/ubuntu-rockchip/releases/download/v2.4.0/ubuntu-24.04-preinstalled-server-arm64-orangepi-5-max.img.xz - name: rock5c - script: ./install_opi5.sh + script: install_opi5.sh base_image: https://github.com/Joshua-Riek/ubuntu-rockchip/releases/download/v2.4.0/ubuntu-24.04-preinstalled-server-arm64-rock-5c.img.xz + - name: rubikpi3 + script: install_rubikpi3.sh + base_image: "https://people.canonical.com/~platform/images/qualcomm-iot/rubikpi3/ubuntu-server-24.04/x00/ubuntu-24.04-preinstalled-server-arm64+rubikpi3-20250912-127.yaml" name: "Build for ${{ matrix.name }}" @@ -103,34 +73,42 @@ jobs: - name: Fetch tags run: git fetch --tags --force - - uses: pguyot/arm-runner-action@HEAD - id: install_deps - with: - image_additional_mb: 1500 - bind_mount_repository: true - base_image: ${{ matrix.base_image }} - commands: | - chmod +x ${{matrix.script}} - ${{ matrix.script }} - chmod +x ./install_common.sh - ./install_common.sh - mkdir -p /opt/photonvision/ - echo "${{ github.ref_name }};${{ matrix.name }}" > /opt/photonvision/image-version + - name: Install dependencies and build image + run: | + chmod +x mount.sh + ./mount.sh ${{ matrix.base_image }} ${{ matrix.script}} install_common.sh ${{ github.ref_name }} ${{ matrix.name }} - name: Compress built image run: | - mv ${{ steps.install_deps.outputs.image }} photonvision_${{ matrix.name }}.img - sudo xz -T 0 -v photonvision_${{ matrix.name }}.img + NAME=photonvision_${{ matrix.name }} + if [[ "${{ matrix.name }}" == rubik* ]]; then + TARGET="$NAME" + tar -I 'xz -T0' -cf photonvision_rubikpi3.tar.xz photonvision_rubikpi3 --checkpoint=10000 --checkpoint-action=echo='%T' + else + TARGET="${NAME}.img" + mv "${{ env.FINAL_IMAGE }}" "$TARGET" + sudo xz -T 0 -v "$TARGET" + fi + + - uses: actions/upload-artifact@v4.3.4 + if: ${{ matrix.name == 'rubikpi3' }} + with: + name: "photonvision_${{ matrix.name }}.tar.xz" + path: photonvision_${{ matrix.name }}.*.xz + if-no-files-found: error + retention-days: 1 - uses: actions/upload-artifact@v4.3.4 + if: ${{ matrix.name != 'rubikpi3' }} with: - name: photonvision_${{ matrix.name }}.img.xz - path: photonvision_${{ matrix.name }}.img.xz + name: "photonvision_${{ matrix.name }}.img.xz" + path: photonvision_${{ matrix.name }}.*.xz if-no-files-found: error retention-days: 1 release: - needs: [build, rubik] + needs: [build] + if: github.event_name == 'push' runs-on: ubuntu-24.04 steps: # Download literally every single artifact @@ -145,4 +123,3 @@ jobs: rm: true files: | **/*.xz - if: github.event_name == 'push' diff --git a/install.sh b/install.sh index 7ad328e..7d9c734 100755 --- a/install.sh +++ b/install.sh @@ -214,9 +214,10 @@ fi DOWNLOAD_URL=$(curl -sk "$RELEASE_URL" | grep "browser_download_url.*$ARCH_NAME.jar" | cut -d : -f 2,3 | - tr -d '"' + tr -d '"'browser_download_url ) +echo $(curl -sk "$RELEASE_URL" | grep ".*$ARCH_NAME.jar") if [[ -z $DOWNLOAD_URL ]] ; then die "PhotonVision '$VERSION' is not available for $ARCH_NAME!" \ "See ./install --list-versions for a list of available versions." diff --git a/install_common.sh b/install_common.sh index a85ff6e..eccac28 100755 --- a/install_common.sh +++ b/install_common.sh @@ -3,6 +3,9 @@ # Verbose and exit on errors set -ex +GITHUB_REF_NAME=$1 +MATRIX_NAME=$2 + # Do additional tasks that are common across all images, # but not suitable for inclusion in install.sh echo "Running install_common.sh" @@ -26,6 +29,10 @@ echo "photon:vision" | chpasswd # Add a helpful message to the logon screen # ASCII Art generated by: https://www.asciiart.eu/image-to-ascii -cp -f ./files/issue.txt /etc/issue +cp -f /tmp/build/files/issue.txt /etc/issue cp -f /etc/issue /etc/issue.net sed -i 's/#Banner none/Banner \/etc\/issue.net/g' /etc/ssh/sshd_config + +# Add photon version file +mkdir -p /opt/photonvision/ +echo "${GITHUB_REF_NAME};${MATRIX_NAME}" > /opt/photonvision/image-version \ No newline at end of file diff --git a/install_dev_pi.sh b/install_dev_pi.sh index 0c60f5b..b4c04fe 100644 --- a/install_dev_pi.sh +++ b/install_dev_pi.sh @@ -3,8 +3,11 @@ # Verbose and exit on errors set -ex # Run normal photon installer + +cd /tmp/build + chmod +x ./install.sh -./install.sh --install-nm=yes --arch=aarch64 +./install.sh --install-nm=yes # and edit boot partition install -m 644 config.txt /boot/ diff --git a/install_limelight.sh b/install_limelight.sh index 7f0ac5f..220bb16 100755 --- a/install_limelight.sh +++ b/install_limelight.sh @@ -3,9 +3,11 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run normal photon installer chmod +x ./install.sh -./install.sh --install-nm=yes --arch=aarch64 +./install.sh --install-nm=yes # edit boot partition install -m 644 limelight/config.txt /boot/ diff --git a/install_limelight3.sh b/install_limelight3.sh index cacfae9..04ab624 100755 --- a/install_limelight3.sh +++ b/install_limelight3.sh @@ -3,6 +3,8 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run the pi install script chmod +x ./install_pi.sh ./install_pi.sh diff --git a/install_limelight3g.sh b/install_limelight3g.sh index 6836f24..4d54ced 100644 --- a/install_limelight3g.sh +++ b/install_limelight3g.sh @@ -3,6 +3,8 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run the pi install script chmod +x ./install_pi.sh ./install_pi.sh diff --git a/install_limelight4.sh b/install_limelight4.sh index e451133..4644f8c 100644 --- a/install_limelight4.sh +++ b/install_limelight4.sh @@ -3,6 +3,8 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run the pi install script chmod +x ./install_pi.sh ./install_pi.sh diff --git a/install_luma_p1.sh b/install_luma_p1.sh index d4c9961..64cef8a 100644 --- a/install_luma_p1.sh +++ b/install_luma_p1.sh @@ -3,6 +3,8 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run the pi install script chmod +x ./install_pi.sh ./install_pi.sh diff --git a/install_opi5.sh b/install_opi5.sh index aadf6a8..92b0d87 100755 --- a/install_opi5.sh +++ b/install_opi5.sh @@ -3,6 +3,8 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Create pi/raspberry login if id "$1" >/dev/null 2>&1; then echo 'user found' @@ -46,7 +48,7 @@ echo "Freed up $freed KiB" # run Photonvision install script chmod +x ./install.sh -./install.sh --install-nm=yes --arch=aarch64 +./install.sh --install-nm=yes echo "Installing additional things" apt-get install --yes --quiet libc6 libstdc++6 diff --git a/install_pi.sh b/install_pi.sh index 777de03..20c7ea4 100755 --- a/install_pi.sh +++ b/install_pi.sh @@ -3,9 +3,11 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run normal photon installer chmod +x ./install.sh -./install.sh --install-nm=yes --arch=aarch64 +./install.sh --install-nm=yes # and edit boot partition install -m 644 config.txt /boot/ diff --git a/install_rubikpi3.sh b/install_rubikpi3.sh index 1ace4d5..42e37f5 100644 --- a/install_rubikpi3.sh +++ b/install_rubikpi3.sh @@ -32,7 +32,7 @@ wget -qO - https://thundercomm.s3.dualstack.ap-northeast-1.amazonaws.com/uploads # Run normal photon installer chmod +x ./install.sh -./install.sh --install-nm=yes --arch=aarch64 +./install.sh --install-nm=yes # Install packages from the RUBIK Pi PPA, we skip calling apt-get update here because install.sh already does that apt-get -y install libqnn1 libsnpe1 qcom-adreno1 device-tree-compiler @@ -56,11 +56,3 @@ apt-get clean rm -rf /usr/share/doc rm -rf /usr/share/locale/ - -echo '=== Running install_common.sh ===' -chmod +x ./install_common.sh -./install_common.sh -echo '=== Creating version file ===' -mkdir -p /opt/photonvision/ -echo '{$1};rubikpi3' > /opt/photonvision/image-version -echo '=== Installation complete ===' \ No newline at end of file diff --git a/install_snakeyes.sh b/install_snakeyes.sh index f687dec..d54e05f 100755 --- a/install_snakeyes.sh +++ b/install_snakeyes.sh @@ -3,6 +3,8 @@ # Verbose and exit on errors set -ex +cd /tmp/build + # Run the pi install script chmod +x ./install_pi.sh ./install_pi.sh diff --git a/mount.sh b/mount.sh new file mode 100644 index 0000000..381e29c --- /dev/null +++ b/mount.sh @@ -0,0 +1,285 @@ +base_image=$1 +scriptOne=$2 +scriptTwo=$3 +set -exv + +# Install required packages +sudo apt-get update +sudo apt-get install -y wget xz-utils +# If base_image ends with .yaml, treat it as a manifest and skip download +if [[ "$base_image" == *.yaml ]]; then + + # We're building a rubik image + rubik=true + # Download and process manifest + wget -O manifest.yaml "${base_image}" + + echo "=== Manifest contents ===" + cat manifest.yaml + echo "=========================" + + # Process each component using awk to extract URL and SHA256 + awk '/url:/ { + sub(/.*url:[[:space:]]*/,"",$0); + url=$0 + } + /sha256sum:/ { + sub(/.*sha256sum:[[:space:]]*/,"",$0); + print url, $0 + }' manifest.yaml | while read -r url sha; do + filename=$(basename "$url") + echo "Downloading: $filename from $url" + wget -nv -O "$filename" "$url" + echo "$sha $filename" | sha256sum -c - + done + + echo "=== Downloaded files ===" + ls -lh + echo "========================" +elif [[ "$base_image" == *.tar.xz ]]; then + # We're building a rubik image + rubik=true + # Directly download the tar.xz file + wget -nv -O base_image.tar.xz "${base_image}" + tar -I 'xz -T0' -xf base_image.tar.xz +elif [[ "$base_image" == *.img.xz ]]; then + # We're building a standard image + rubik=false + wget -nv -O base_image.img.xz "${base_image}" + xz -T0 -d base_image.img.xz +else + echo "Error: base_image must be a .yaml manifest, .tar.xz, or .img.xz file" + exit 1 +fi +# Find the rootfs image - look for the largest .img.xz or .img file +ROOTFS_IMG="" + +# If not found, use the largest .img.xz file +ROOTFS_IMG="${ROOTFS_IMG:-$(find . -type f \( -name '*.img.xz' -o -name '*.img' \) -exec ls -s {} + 2>/dev/null | sort -rn | head -n1 | awk '{print $2}')}" +[ -n "$ROOTFS_IMG" ] && echo "Using largest .img.xz or .img file as rootfs: $ROOTFS_IMG" + +if [ -z "$ROOTFS_IMG" ] || [ ! -f "$ROOTFS_IMG" ]; then + echo "Error: Could not find a suitable rootfs image file" + echo "Available files:" + ls -la + exit 1 +fi + +# Only extract if ROOTFS_IMG is an .img.xz file +if [[ "$ROOTFS_IMG" == *.img.xz ]]; then + ROOTFS_IMG_XZ="$ROOTFS_IMG" + ROOTFS_IMG="${ROOTFS_IMG_XZ%.xz}" + echo "Extracting rootfs image: $ROOTFS_IMG_XZ" + xz -T0 -d "$ROOTFS_IMG_XZ" +fi + +if [ ! -f "$ROOTFS_IMG" ]; then + echo "Error: Root filesystem image not found: $ROOTFS_IMG" + echo "Available files:" + ls -la + exit 1 +fi + +# Make mount point +mkdir -p ./rootfs + +echo "Using rootfs image: $ROOTFS_IMG" +if [ "$rubik" == true ]; then + echo "Building Rubik image" + + # This uses a fixed offset for Ubuntu preinstalled server images + echo "=== Mounting rootfs with fixed offset (rpiimager method) ===" + + # Calculate offset: 4096 bytes/sector * 139008 sectors = 569,376,768 bytes + OFFSET=$((4096*139008)) + echo "Using offset: $OFFSET bytes (sector 139008)" + + sudo mount -o rw,loop,offset=$OFFSET "$ROOTFS_IMG" ./rootfs + + if [ $? -ne 0 ]; then + echo "Error: Failed to mount image with fixed offset" + exit 1 + fi +else + echo "Building Standard image" + + # Get partition info using parted + PART_INFO=$(parted -s "$ROOTFS_IMG" unit B print) + + # Extract start byte of the root partition (assuming it's the second partition) + START_BYTE=$(echo "$PART_INFO" | awk '/^ 2/ {gsub("B","",$2); print $2}') + + if [ -z "$START_BYTE" ]; then + echo "Error: Could not determine start byte of root partition" + exit 1 + fi + + OFFSET=$START_BYTE + echo "Using offset: $OFFSET bytes" + + sudo mount -o rw,loop,offset=$OFFSET "$ROOTFS_IMG" ./rootfs + + if [ $? -ne 0 ]; then + echo "Error: Failed to mount image with calculated offset" + exit 1 + fi + +fi + +echo "=== Mount successful ===" +ls -la ./rootfs | head -20 + +# Check if this is a Canonical or Modified image (from rpiimager logic) +if [ -f "rootfs/etc/ImgType" ]; then + cp rootfs/etc/ImgType ImgType +else + echo "Canonical" > ImgType +fi +read ImgType < ImgType +echo "Image type: $ImgType" + +# Expand image if it's a Canonical image (first time modification) +if [ "$ImgType" == "Canonical" ]; then + echo "=== Marking image as CustomIDE ===" + sudo chroot rootfs /bin/bash -c " + touch /etc/ImgType + echo 'CustomIDE' > /etc/ImgType + " + + echo "=== Unmounting for expansion ===" + sudo umount ./rootfs + + if [ "$rubik" = true ]; then + # Expand the image by 2GB (reduced from 10GB to fit GitHub Actions disk space) + echo "=== Expanding image by 2GB ===" + dd if=/dev/zero bs=1M count=2048 >> "$ROOTFS_IMG" + else + # Expand the image by 1GB + echo "=== Expanding image by 1GB ===" + dd if=/dev/zero bs=1M count=1024 >> "$ROOTFS_IMG" + fi + + if [ "$rubik" != true ]; then + loopdev=$(sudo losetup --find --show --partscan ${ROOTFS_IMG}) + echo "Created loopback device ${loopdev}" + + if ( (sudo parted --script $loopdev print || false) | grep "Partition Table: gpt" > /dev/null); then + sudo sgdisk -e "${loopdev}" + fi + sudo parted --script "${loopdev}" resizepart 2 100% + sudo e2fsck -p -f "${loopdev}p2" + sudo resize2fs "${loopdev}p2" + echo "Finished resizing disk image." + # Detach loop device + sudo losetup -d "${loopdev}" + + fi + + # Remount after expansion + echo "=== Remounting after expansion ===" + sudo mount -o rw,loop,offset=$OFFSET "$ROOTFS_IMG" ./rootfs + + if [ "$rubik" != true ]; then + # Resize the filesystem to fill the partition + echo "=== Resizing filesystem ===" + sudo resize2fs "$(losetup -j "$ROOTFS_IMG" | cut -d: -f1 | head -n1)" + fi +elif [ "$ImgType" == "CustomIDE" ]; then + echo "Image already customized, no expansion needed" +fi + +rm -f ImgType + +echo "=== Filesystem ready ===" + +# Setup chroot environment +sudo mount -t proc proc rootfs/proc +sudo mount -t sysfs sysfs rootfs/sys +sudo mount -t tmpfs tmpfs rootfs/run +sudo mount --bind /dev rootfs/dev + +# Setup DNS resolution in chroot +echo "=== Setting up DNS in chroot ===" +sudo rm -f rootfs/etc/resolv.conf +sudo cp /etc/resolv.conf rootfs/etc/resolv.conf +sudo cp /etc/hosts rootfs/etc/hosts + +# Mount and bind the current directory into /tmp/build in chroot +sudo mkdir -p rootfs/tmp/build/ +sudo mount --bind "$(pwd)" rootfs/tmp/build/ + +echo "=== Checking for sudo in chroot and running script ===" +sudo chroot rootfs /bin/bash -c " + set -exv + export DEBIAN_FRONTEND=noninteractive + if ! command -v sudo &> /dev/null; then + echo 'sudo not found, installing...' + apt-get update && apt-get install -y sudo + else + echo 'sudo is already installed' + fi + + echo '=== Running installation scripts in chroot ===' + + echo '=== Making script executable ===' + chmod +x /tmp/build/${scriptOne} + echo '=== Running ${scriptOne} ===' + ./tmp/build/${scriptOne} + + if [ -f "/tmp/build/${scriptTwo}" ]; then + echo '=== Making second script executable ===' + chmod +x /tmp/build/${scriptTwo} + echo '=== Running ${scriptTwo} ===' + ./tmp/build/${scriptTwo} $(printf '%q ' "${@:4}") + else + echo 'No second script provided, skipping.' + fi +" + +# Cleanup mounts +sudo umount rootfs/dev || true +sudo umount rootfs/run || true +sudo umount rootfs/sys || true +sudo umount rootfs/proc || true +sudo umount rootfs/tmp/build/ || true +sudo umount rootfs || true + +# Find and detach any remaining loop devices pointing to our image +sudo losetup -j "$ROOTFS_IMG" | cut -d: -f1 | xargs -r sudo losetup -d + +# Ensure all filesystem operations are complete +sync +sleep 3 + +if [ "$rubik" == true ]; then + # Assembly process for remaining files + mkdir -p photonvision_rubikpi3 + # Extract .tar.gz archive(s) directly into photonvision_rubikpi3 if they exist + if ls *.tar.gz 1>/dev/null 2>&1; then + tar -xzf *.tar.gz -C photonvision_rubikpi3 + fi + # Move all files (rawprogram, dtb, img) into photonvision_rubikpi3 + mv rawprogram*.xml photonvision_rubikpi3/ 2>/dev/null || true + mv dtb.bin photonvision_rubikpi3/ 2>/dev/null || true + mv *.img photonvision_rubikpi3/ 2>/dev/null || true + + # Flatten directory structure - move all files from subdirectories to photonvision_rubikpi3 root + find photonvision_rubikpi3 -mindepth 2 -type f -exec mv {} photonvision_rubikpi3/ \; + # Remove empty subdirectories + find photonvision_rubikpi3 -mindepth 1 -type d -empty -delete + + # Export the final directory as an environment variable for GitHub Actions + FINAL_IMAGE="photonvision_rubikpi3" + +else + # Export the final image as an enivronment variable + FINAL_IMAGE="$ROOTFS_IMG" +fi + +if [ -n "$GITHUB_ENV" ]; then + printf '%s\n' "FINAL_IMAGE=${FINAL_IMAGE}" >> "$GITHUB_ENV" + echo "Wrote FINAL_IMAGE to GITHUB_ENV" +else + export FINAL_IMAGE="$FINAL_IMAGE" + echo "FINAL_IMAGE exported in current shell" +fi diff --git a/mount_rubikpi3.sh b/mount_rubikpi3.sh deleted file mode 100644 index 04f432f..0000000 --- a/mount_rubikpi3.sh +++ /dev/null @@ -1,208 +0,0 @@ - -base_image=$1 -script=$2 - -set -exv - -# Install required packages -sudo apt-get update -sudo apt-get install -y qemu-user-static wget xz-utils -# If base_image ends with .yaml, treat it as a manifest and skip download -if [[ "$base_image" == *.yaml ]]; then - - # Download and process manifest - wget -O manifest.yaml "${base_image}" - - echo "=== Manifest contents ===" - cat manifest.yaml - echo "=========================" - - # Process each component using awk to extract URL and SHA256 - awk '/url:/ { - sub(/.*url:[[:space:]]*/,"",$0); - url=$0 - } - /sha256sum:/ { - sub(/.*sha256sum:[[:space:]]*/,"",$0); - print url, $0 - }' manifest.yaml | while read -r url sha; do - filename=$(basename "$url") - echo "Downloading: $filename from $url" - wget -nv -O "$filename" "$url" - echo "$sha $filename" | sha256sum -c - - done - - echo "=== Downloaded files ===" - ls -lh - echo "========================" -elif [[ "$base_image" == *.tar.xz ]]; then - # Directly download the tar.xz file - wget -nv -O base_image.tar.xz "${base_image}" - tar -I 'xz -T0' -xf base_image.tar.xz -else - echo "Error: base_image must be a .yaml manifest or .tar.xz" - exit 1 -fi -# Find the rootfs image - look for the largest .img.xz or .img file -ROOTFS_IMG="" - -# If not found, use the largest .img.xz file -ROOTFS_IMG="${ROOTFS_IMG:-$(find . -type f \( -name '*.img.xz' -o -name '*.img' \) -exec ls -s {} + 2>/dev/null | sort -rn | head -n1 | awk '{print $2}')}" -[ -n "$ROOTFS_IMG" ] && echo "Using largest .img.xz or .img file as rootfs: $ROOTFS_IMG" - -if [ -z "$ROOTFS_IMG" ] || [ ! -f "$ROOTFS_IMG" ]; then - echo "Error: Could not find a suitable rootfs image file" - echo "Available files:" - ls -la - exit 1 -fi - -# Only extract if ROOTFS_IMG is an .img.xz file -if [[ "$ROOTFS_IMG" == *.img.xz ]]; then - ROOTFS_IMG_XZ="$ROOTFS_IMG" - ROOTFS_IMG="${ROOTFS_IMG_XZ%.xz}" - echo "Extracting rootfs image: $ROOTFS_IMG_XZ" - xz -T0 -d "$ROOTFS_IMG_XZ" -fi - -if [ ! -f "$ROOTFS_IMG" ]; then - echo "Error: Root filesystem image not found: $ROOTFS_IMG" - echo "Available files:" - ls -la - exit 1 -fi - -echo "Using rootfs image: $ROOTFS_IMG" - -# This uses a fixed offset for Ubuntu preinstalled server images -echo "=== Mounting rootfs with fixed offset (rpiimager method) ===" -mkdir -p ./rootfs - -# Calculate offset: 4096 bytes/sector * 139008 sectors = 569,376,768 bytes -OFFSET=$((4096*139008)) -echo "Using offset: $OFFSET bytes (sector 139008)" - -sudo mount -o rw,loop,offset=$OFFSET "$ROOTFS_IMG" ./rootfs - -if [ $? -ne 0 ]; then - echo "Error: Failed to mount image with fixed offset" - exit 1 -fi - -echo "=== Mount successful ===" -ls -la ./rootfs | head -20 - -# Check if this is a Canonical or Modified image (from rpiimager logic) -if [ -f "rootfs/etc/ImgType" ]; then - cp rootfs/etc/ImgType ImgType -else - echo "Canonical" > ImgType -fi -read ImgType < ImgType -echo "Image type: $ImgType" - -# Expand image if it's a Canonical image (first time modification) -if [ "$ImgType" == "Canonical" ]; then - echo "=== Marking image as CustomIDE ===" - sudo chroot rootfs /bin/bash -c " - touch /etc/ImgType - echo 'CustomIDE' > /etc/ImgType - " - - echo "=== Unmounting for expansion ===" - sudo umount ./rootfs - - # Expand the image by 2GB (reduced from 10GB to fit GitHub Actions disk space) - echo "=== Expanding image by 2GB ===" - dd if=/dev/zero bs=1M count=2048 >> "$ROOTFS_IMG" - - # Remount after expansion - echo "=== Remounting after expansion ===" - sudo mount -o rw,loop,offset=$OFFSET "$ROOTFS_IMG" ./rootfs -elif [ "$ImgType" == "CustomIDE" ]; then - echo "Image already customized, no expansion needed" -fi - -rm -f ImgType - -echo "=== Filesystem ready ===" - -# Setup chroot environment -sudo mount -t proc proc rootfs/proc -sudo mount -t sysfs sysfs rootfs/sys -sudo mount -t tmpfs tmpfs rootfs/run -sudo mount --bind /dev rootfs/dev - -# Setup DNS resolution in chroot -echo "=== Setting up DNS in chroot ===" -sudo rm -f rootfs/etc/resolv.conf -sudo cp /etc/resolv.conf rootfs/etc/resolv.conf -sudo cp /etc/hosts rootfs/etc/hosts - -# Copy qemu static binaries for ARM emulation -sudo cp /usr/bin/qemu-arm-static rootfs/usr/bin/ || true -sudo cp /usr/bin/qemu-aarch64-static rootfs/usr/bin/ || true - -# DEPRECATED: using bind mount instead -# Copy repository into chroot (excluding mounted directories and problematic files) -# sudo mkdir -p rootfs/tmp/build/ -# sudo rsync -av --exclude=rootfs --exclude=.git --exclude=*.img --exclude=*.xz . rootfs/tmp/build/ - -# Mount and bind the current directory into /tmp/build in chroot -sudo mkdir -p rootfs/tmp/build/ -sudo mount --bind "$(pwd)" rootfs/tmp/build/ - -echo "=== Checking for sudo in chroot and running script ===" -sudo chroot rootfs /usr/bin/qemu-aarch64-static /bin/bash -c " - set -exv - export DEBIAN_FRONTEND=noninteractive - if ! command -v sudo &> /dev/null; then - echo 'sudo not found, installing...' - apt-get update && apt-get install -y sudo - else - echo 'sudo is already installed' - fi - - echo '=== Running installation scripts in chroot ===' - - echo '=== Making script executable ===' - chmod +x ${script} - echo '=== Running ${script} with arguments: ${@:3} ===' - ./${script} ${@:3} -" - -# Cleanup mounts -sudo umount rootfs/dev || true -sudo umount rootfs/run || true -sudo umount rootfs/sys || true -sudo umount rootfs/proc || true -sudo umount rootfs/tmp/build/ || true -sudo umount rootfs || true - -# More aggressive loop device cleanup -if [ -n "$LOOP_DEV" ]; then - sudo losetup -d "$LOOP_DEV" || true -fi - -# Find and detach any remaining loop devices pointing to our image -sudo losetup -j "$ROOTFS_IMG" | cut -d: -f1 | xargs -r sudo losetup -d - -# Ensure all filesystem operations are complete -sync -sleep 3 - -# Assembly process for remaining files -mkdir -p photonvision_rubikpi3 -# Extract .tar.gz archive(s) directly into photonvision_rubikpi3 if they exist -if ls *.tar.gz 1>/dev/null 2>&1; then - tar -xzf *.tar.gz -C photonvision_rubikpi3 -fi -# Move all files (rawprogram, dtb, img) into photonvision_rubikpi3 -mv rawprogram*.xml photonvision_rubikpi3/ 2>/dev/null || true -mv dtb.bin photonvision_rubikpi3/ 2>/dev/null || true -mv *.img photonvision_rubikpi3/ 2>/dev/null || true - -# Flatten directory structure - move all files from subdirectories to photonvision_rubikpi3 root -find photonvision_rubikpi3 -mindepth 2 -type f -exec mv {} photonvision_rubikpi3/ \; -# Remove empty subdirectories -find photonvision_rubikpi3 -mindepth 1 -type d -empty -delete