pguyot / arm-runner-action

Run tests natively and build images directly from GitHub Actions using a chroot-based virtualized Raspberry Pi (raspios/raspbian) environment
BSD 3-Clause "New" or "Revised" License
155 stars 33 forks source link

Rootfs not included in the final image due to error during shrinking #87

Closed dloranc closed 6 months ago

dloranc commented 1 year ago

Hello, I have an issue with building a simple image using this workflow:

name: arm-runner-workflow
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: pguyot/arm-runner-action@main
        id: build_image
        with:
          base_image: "raspios_lite_arm64:2023-05-03"
          commands: |
            echo "#include <iostream>" > main.cpp
            echo "int main() {" >> main.cpp
            echo "  std::cout << \"Hello, World!\" << std::endl;" >> main.cpp
            echo "  return 0;" >> main.cpp
            echo "}" >> main.cpp
            g++ -o main main.cpp
            ./main
            uname -srm
      - name: Compress the release image
        run: |
          mv ${{ steps.build_image.outputs.image }} my-release-image.img
          xz -0 -T 0 -v my-release-image.img
      - name: Upload release image
        uses: actions/upload-artifact@v3
        with:
          name: Release image
          path: my-release-image.img.xz

During the build in the arm-runner-action I'm getting this error:

Resizing root filesystem to minimal size.
rootfs: 41861/111776 files (0.1% non-contiguous), 331116/446464 blocks
resize2fs 1.46.5 (30-Dec-2021)
The filesystem is already 446464 (4k) blocks long.  Nothing to do!

Resizing rootfs partition.
Error: The location 2101346304 is outside of the device /dev/loop3.
Shrinking image from 2101346304 to 272629760 bytes.

The uploaded and compressed artifact is only 19MB, which is too small as it should be over 300MB. It appears that the rootfs partition is not included in the final image. What can I do to fix this issue?

This is the repository I created to test the action: https://github.com/dloranc/arm-runner-test/actions

bvobart commented 6 months ago

Hi, I'm facing the same issue, I too notice that there's no root partition included in the final image, only a boot partition, as shown by fdisk:

$ fdisk -l pi-dj-main.img 
Disk pi-dj-main.img: 129 MiB, 135266304 bytes, 264192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x8908bc0d

Device          Boot Start    End Sectors  Size Id Type
pi-dj-main.img1 *     2048 264191  262144  128M  c W95 FAT32 (LBA)

Here's the relevant part of the logs from my project's CI build (see workflow file here):

Zero-filling unused blocks on boot filesystem...
Zero-filling unused blocks on root filesystem...
Resizing root filesystem to minimal size.
/dev/loop3p2: 42644/81920 files (0.2% non-contiguous), 273930/303369 blocks
resize2fs 1.46.5 (30-Dec-2021)
The filesystem is already 303369 (4k) blocks long.  Nothing to do!

Resizing rootfs partition.
Error: The location 1377865728 is outside of the device /dev/loop3.
Shrinking image from 1377865728 to 135266304 bytes.

@pguyot Do you happen to know what's going on here?

bvobart commented 6 months ago

I've forked this repo and augmented the test for optimize_image to also check whether both the boot and root partitions are included in the final image, see here. That test passes for the unoptimized image, but fails for the optimized image, also showing that it is missing the root partition, see build logs here.

I've added some debug prints too but I'm still none the wiser as to what is going wrong exactly...

pguyot commented 6 months ago

@bvobart thank you for investigating this.

Indeed there are two bugs here:

  1. the cleanup script was not aborting the action if a problem occurred. This yielded the partition being corrupted without failing.

  2. parted expects end to be the offset of the actual end byte but was provided with the offset of the next byte (+1). When optimize_image option is yes, we both zero space (to ease compression) and try to resize fs, but resize2fs doesn't always work and when it doesn't, we called parted with an end byte that was too large.

In your log and @dloranc logs above, we can see that resize2fs failed to shrink the root fs ("Nothing to do!") and parted complains that the provided end offset is beyond the size of the image ("is outside of the device /dev/loop3").

bvobart commented 6 months ago

Perfect, thank you for fixing this so quickly! Happy to help :) I can confirm that the produced final image now indeed has two partitions inside.