diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1f8a01d..9a94d22 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,12 +10,17 @@ on: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + env: + # BuildKit mounts each RUN step's rootfs with nosuid, which breaks `sudo` inside + # ev3dev-service-control's Dockerfile (still needed on the newer Docker Engine that ships + # with this runner image, even though that Dockerfile itself is unchanged). The legacy + # builder doesn't impose this restriction. + DOCKER_BUILDKIT: "0" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive - - uses: satackey/action-docker-layer-caching@v0.0.8 - name: install brickstrap dependencies run: | sudo apt-get update @@ -47,7 +52,7 @@ jobs: run: sudo chmod 755 /boot/vmlinuz* - name: build image run: ./build_image.sh - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 if: ${{ github.event_name == 'workflow_dispatch' }} with: name: image diff --git a/brickstrap.sh b/brickstrap.sh index e3dc08a..d0f6e69 100755 --- a/brickstrap.sh +++ b/brickstrap.sh @@ -201,9 +201,25 @@ function brickstrap_create_image() # orphan_file, compat bit 12), which systemd-fsck-root.service treats as fatal and drops the # whole boot into emergency mode. Explicitly excluding the newer features keeps the # filesystem on a feature set the image's own e2fsck actually understands. Harmless on an - # older host (e.g. this project's current ubuntu-20.04 CI runner) whose mke2fs never enabled - # these features anyway - excluding an already-absent feature is a no-op. - ROOTFS_MKE2FS_FEATURES="^orphan_file,^metadata_csum_seed,^fast_commit,^sparse_super2,^stable_inodes" + # older host whose mke2fs never enabled these features anyway - excluding an already-absent + # feature is normally a no-op. + # + # That assumption broke moving to a newer CI runner image: its mke2fs (1.46.5) is old enough + # to not recognize one of these five names at all (added in a later e2fsprogs release), and + # unlike "silently no-op on an absent feature", an unrecognized name makes mke2fs reject the + # entire -O list as invalid, aborting the whole image build. Rather than hardcode which name(s) + # are safe for whichever e2fsprogs happens to be installed, detect it directly: keep only the + # names this host's own mke2fs actually accepts negating, on a real scratch filesystem via the + # same -O parser guestfish's appliance will use (built from this same host's packages). + ROOTFS_MKE2FS_FEATURES="" + for feat in orphan_file metadata_csum_seed fast_commit sparse_super2 stable_inodes; do + feat_test_img="$(mktemp)" + truncate -s 16M "$feat_test_img" + if mke2fs -F -q -O "^$feat" "$feat_test_img" >/dev/null 2>&1; then + ROOTFS_MKE2FS_FEATURES="${ROOTFS_MKE2FS_FEATURES:+$ROOTFS_MKE2FS_FEATURES,}^$feat" + fi + rm -f "$feat_test_img" + done guestfish -N "$BRICKSTRAP_IMAGE_FILE_NAME"=disk:$BRICKSTRAP_IMAGE_FILE_SIZE -- \ part-init /dev/sda mbr : \ diff --git a/build_control_panel.sh b/build_control_panel.sh index 91a43de..6fe30e8 100755 --- a/build_control_panel.sh +++ b/build_control_panel.sh @@ -7,6 +7,24 @@ REPO_DIR="ev3dev-service-control" IMAGE_NAME="sourceacademy/ev3-vala-compiler" cd "$SCRIPT_DIR/$REPO_DIR" +# The ev3dev/debian-stretch-armel-cross base image's own /usr/bin/sudo is missing its setuid bit +# ("effective uid is not 0") - a defect in that specific image, not a runner/host issue: the +# sibling debian-stretch-cross image (Dockerfile.sling) uses the exact same sudo pattern and +# builds fine on the same runner. This image's default user genuinely isn't root either (a plain +# `sed -i` on /etc/apt/sources.list without sudo fails with a real permission error), so strip +# sudo AND force USER root directly - that doesn't depend on sudo's (broken) setuid mechanism at +# all. Patched here rather than in the upstream submodule repo, which we don't own. + +# Debian Stretch has been end-of-life for years and its archive's Release-file signatures have +# since expired, so a plain `apt install -y` refuses to proceed ("unauthenticated packages"). This +# is the standard, narrowly-scoped workaround for an archived/dead release's own expired signing +# keys - it does not affect any live, currently-maintained repository. +sed -i \ + -e 's/^RUN sudo /RUN /' \ + -e 's/"sudo", //' \ + -e '/^FROM /a USER root' \ + -e 's/apt install --yes/apt -o APT::Get::AllowUnauthenticated=true install --yes/' \ + Dockerfile docker build -t "$IMAGE_NAME" . cd "$SCRIPT_DIR"