From 9769f646363dffea7a4c8b6692124e0a0039b2d4 Mon Sep 17 00:00:00 2001 From: ffrancis Date: Thu, 16 Jul 2026 13:02:08 +0530 Subject: [PATCH 1/5] Mount rootfs on host before Docker copy Mount rootfs on the runner before starting Docker. Bind the mounted rootfs into Docker for file copy. Fall back to guestmount when loop mount fails. Collect libguestfs diagnostics when guestmount fails. Ignore optional missing files, but fail on other copy errors. Clean up the mount on exit. Signed-off-by: ffrancis --- .github/workflows/process_image.yml | 62 ++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/.github/workflows/process_image.yml b/.github/workflows/process_image.yml index 3ec35b7..2739695 100644 --- a/.github/workflows/process_image.yml +++ b/.github/workflows/process_image.yml @@ -119,31 +119,65 @@ jobs: ls -l "$ROOTFS_DIR/rootfs.img" - # Run inside the docker container + # Mount on host runner first (container loop/libguestfs is unreliable on some runners), + # then run only file-copy logic in docker with /tmp/rootfs bind-mounted. + sudo mkdir -p /tmp/rootfs + + cleanup_mount() { + if mountpoint -q /tmp/rootfs; then + sudo umount /tmp/rootfs || sudo guestunmount /tmp/rootfs || true + fi + } + trap cleanup_mount EXIT + + if sudo mount -o loop "$ROOTFS_DIR/rootfs.img" /tmp/rootfs; then + echo "Image mounted successfully with loop mount" + else + echo "Loop mount failed on host, trying guestmount" + sudo env DEBIAN_FRONTEND=noninteractive apt-get update + sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y libguestfs-tools + export LIBGUESTFS_BACKEND=direct + export LIBGUESTFS_BACKEND_SETTINGS=force_tcg + export LIBGUESTFS_DEBUG=1 + export LIBGUESTFS_TRACE=1 + + echo "DEBUG: running guestmount with LIBGUESTFS_DEBUG=1 LIBGUESTFS_TRACE=1" + if ! sudo -E guestmount -a "$ROOTFS_DIR/rootfs.img" -i --rw /tmp/rootfs; then + echo "guestmount failed; collecting libguestfs diagnostics" + sudo -E libguestfs-test-tool || true + exit 1 + fi + echo "Image mounted successfully with guestmount" + fi + docker run \ --rm \ -v $PWD:/workspace \ + -v /tmp/rootfs:/tmp/rootfs \ -w /workspace \ - -e "ROOTFS_DIR=$ROOTFS_DIR" \ -e "FILES_TO_COPY=${{ inputs.files_to_copy }}" \ - --privileged \ ${{ steps.get-docker-image.outputs.image_name }} \ bash -c ' set -xe - cd ${ROOTFS_DIR} - sudo mkdir -p /tmp/rootfs - sudo mount rootfs.img /tmp/rootfs - echo "Image mounted successfully" - - - # Copy the arg build files to the mounted image - sudo bash -c "source /workspace/${FILES_TO_COPY}" + set +e + copy_output="$(sudo bash -c "source /workspace/${FILES_TO_COPY}" 2>&1)" + copy_rc=$? + set -e + echo "$copy_output" + if [ "$copy_rc" -ne 0 ]; then + if echo "$copy_output" | grep -q "cp: cannot stat"; then + echo "Optional files missing in ${FILES_TO_COPY}; continuing" + else + exit "$copy_rc" + fi + fi echo "Build files copied successfully" sync - # Unmount the image - sudo umount /tmp/rootfs - echo "Image unmounted successfully" ' + + cleanup_mount + trap - EXIT + echo "Image unmounted successfully" ls -l "$ROOTFS_DIR/rootfs.img" - name: Create tar image for qcomflash directory From bc3be51b60cf48125082bee03572eaea4ef873d2 Mon Sep 17 00:00:00 2001 From: ffrancis Date: Wed, 22 Jul 2026 16:20:28 +0530 Subject: [PATCH 2/5] Enforce LAVA overlay compatibility and switch test-plan ref Remove lava_test_results_dir from generated job contexts. Force OVERLAY_PATH=/ in flash.settings updates to maintain LAVA overlay compatibility. Apply compatibility adjustments to all generated YAML jobs before selecting the first job for execution. Signed-off-by: ffrancis --- .github/actions/lava-test-plans/action.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/actions/lava-test-plans/action.yml b/.github/actions/lava-test-plans/action.yml index c3fdcc2..86a78e2 100644 --- a/.github/actions/lava-test-plans/action.yml +++ b/.github/actions/lava-test-plans/action.yml @@ -82,7 +82,7 @@ runs: with: repository: qualcomm-linux-stg/lava-test-plans path: lava-test-plans - ref: master + ref: sample - name: Setup Python uses: actions/setup-python@v6 @@ -147,6 +147,7 @@ runs: *) TESTPLAN_DIR="${TESTPLAN_INPUT}" ;; esac + echo "Using lava-test-plans project: ${PROJECT}" echo "Resolved: MACHINE=${INPUT_MACHINE_NAME}, DISTRO_NAME=${DISTRO_NAME}, TESTPLAN_DIR=${TESTPLAN_DIR}" @@ -198,6 +199,16 @@ runs: --device-type "projects/${PROJECT}/devices/${INPUT_MACHINE_NAME}" \ --dry-run-path "${JOBS_SUBDIR}" || true + # LAVA overlay compatibility: + # 1) remove lava_test_results_dir from generated job context + # 2) always force OVERLAY_PATH=/ in flash.settings writes + if [ -d "${JOBS_SUBDIR}" ]; then + while IFS= read -r -d '' yaml_file; do + sed -i '/lava_test_results_dir/d' "${yaml_file}" + sed -i 's#echo "OVERLAY_PATH=.*" >> \\$IMAGE_PATH/flash.settings#echo "OVERLAY_PATH=/" >> \\$IMAGE_PATH/flash.settings#g' "${yaml_file}" + done < <(find "${JOBS_SUBDIR}" -type f -name '*.yaml' -print0) + fi + # Find the first YAML job (NUL-safe listing + stable sort) FIRST_JOB="$(find "${JOBS_SUBDIR}" -type f -name '*.yaml' -print0 | xargs -0 -r ls -1 | sort | head -n 1 || true)" From b2876c8ed6d76dc3a5fac35767b10fccf0a8a592 Mon Sep 17 00:00:00 2001 From: ffrancis Date: Wed, 22 Jul 2026 20:25:06 +0530 Subject: [PATCH 3/5] Normalize rootfs directory name before mounting Add expected rootfs directory validation and rename the extracted directory when required. Update ROOTFS_DIR and ROOTFS_IMG accordingly and remove a trailing blank line. Signed-off-by: ffrancis --- .github/workflows/process_image.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/process_image.yml b/.github/workflows/process_image.yml index 2739695..db75928 100644 --- a/.github/workflows/process_image.yml +++ b/.github/workflows/process_image.yml @@ -111,6 +111,13 @@ jobs: tar -xvf qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz ROOTFS_IMG=$(tar -tf qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz | grep 'rootfs.img$') ROOTFS_DIR=$(dirname "$ROOTFS_IMG") + EXPECTED_ROOTFS_DIR="qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}" + if [ "$ROOTFS_DIR" != "$EXPECTED_ROOTFS_DIR" ] && [ -d "$ROOTFS_DIR" ]; then + rm -rf "$EXPECTED_ROOTFS_DIR" + mv "$ROOTFS_DIR" "$EXPECTED_ROOTFS_DIR" + ROOTFS_DIR="$EXPECTED_ROOTFS_DIR" + ROOTFS_IMG="$ROOTFS_DIR/rootfs.img" + fi # Export as GitHub Actions environment variables echo "ROOTFS_IMG=$ROOTFS_IMG" >> $GITHUB_ENV echo "ROOTFS_DIR=$ROOTFS_DIR" >> $GITHUB_ENV From 5c6304217c3c20e1723a31cd5f92c2d8aa24981a Mon Sep 17 00:00:00 2001 From: ffrancis Date: Thu, 30 Jul 2026 15:41:39 +0530 Subject: [PATCH 4/5] Normalize the S3 location prefix before building artifact paths Append a trailing slash only when the location input is provided. Reuse the normalized prefix for upload, download, and presign operations. Prevent creation of empty S3 path segments when location is unset. Signed-off-by: ffrancis --- .github/actions/aws-s3-exchanger/action.yml | 35 +++++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/.github/actions/aws-s3-exchanger/action.yml b/.github/actions/aws-s3-exchanger/action.yml index 868bf4a..bd96cb3 100644 --- a/.github/actions/aws-s3-exchanger/action.yml +++ b/.github/actions/aws-s3-exchanger/action.yml @@ -36,34 +36,49 @@ runs: shell: bash env: UPLOAD_LOCATION: ${{ inputs.upload_location }} + INPUT_LOCATION: ${{ inputs.location }} + INPUT_MODE: ${{ inputs.mode }} + INPUT_LOCAL_FILE: ${{ inputs.local_file }} + INPUT_S3_BUCKET: ${{ inputs.s3_bucket }} + INPUT_DOWNLOAD_FILENAME: ${{ inputs.download_filename }} + WORKSPACE_DIR: ${{ github.workspace }} + IMAGE_NAME: ${{ env.IMAGE_NAME }} run: | - case "${{ inputs.mode }}" in + set -euo pipefail + + location_prefix="${INPUT_LOCATION}" + if [ -n "$location_prefix" ]; then + location_prefix="${location_prefix%/}/" + fi + + case "${INPUT_MODE}" in upload) echo "::group::$(printf '__________ %-100s' 'Process' | tr ' ' _)" echo "Uploading file to S3 bucket..." - aws s3 cp "${{ inputs.local_file }}" s3://${{ inputs.s3_bucket }}/${{ inputs.location }}/${{ env.UPLOAD_LOCATION }}${{ env.IMAGE_NAME }}/ - echo "Uploaded ${{ inputs.local_file }} to s3://${{ inputs.s3_bucket }}/${{ inputs.location }}/${{ env.UPLOAD_LOCATION }}${{ env.IMAGE_NAME }}/" + aws s3 cp "${INPUT_LOCAL_FILE}" "s3://${INPUT_S3_BUCKET}/${location_prefix}${UPLOAD_LOCATION}${IMAGE_NAME}/" + echo "Uploaded ${INPUT_LOCAL_FILE} to s3://${INPUT_S3_BUCKET}/${location_prefix}${UPLOAD_LOCATION}${IMAGE_NAME}/" echo "::endgroup::" - echo "Creating Pre-signed URL for ${{ inputs.local_file }}..." - filename="$(basename "${{ inputs.local_file }}")" + echo "Creating Pre-signed URL for ${INPUT_LOCAL_FILE}..." + filename="$(basename "${INPUT_LOCAL_FILE}")" echo "Filename: $filename" - presigned_url="$(aws s3 presign s3://${{ inputs.s3_bucket }}/${{ inputs.location }}/${{ env.UPLOAD_LOCATION }}${{ env.IMAGE_NAME }}/$filename --expires-in 3600)" + presigned_url="$(aws s3 presign "s3://${INPUT_S3_BUCKET}/${location_prefix}${UPLOAD_LOCATION}${IMAGE_NAME}/$filename" --expires-in 3600)" echo "Pre-signed URL: $presigned_url" # Make URL available as a step output (fixed key) echo "presigned_url=${presigned_url}" >> "$GITHUB_OUTPUT" # Also write the URL into a uniquely named file for artifact download - echo "${presigned_url}" > "${{ github.workspace }}/presigned_urls/presigned_url_${{ env.IMAGE_NAME }}.txt" + mkdir -p "${WORKSPACE_DIR}/presigned_urls" + echo "${presigned_url}" > "${WORKSPACE_DIR}/presigned_urls/presigned_url_${IMAGE_NAME}.txt" ;; download) #Download The required file from s3 echo "::group::$(printf '__________ %-100s' 'Process' | tr ' ' _)" echo "Downloading files from S3 bucket..." - aws s3 cp s3://${{ inputs.s3_bucket }}/${{ inputs.location }}/${{ inputs.download_filename }} . + aws s3 cp "s3://${INPUT_S3_BUCKET}/${location_prefix}${INPUT_DOWNLOAD_FILENAME}" . echo "::endgroup::" - chmod 777 ${{ inputs.download_filename }} - echo "Downloaded ${{ inputs.download_filename }} from s3://${{ inputs.s3_bucket }}/${{ inputs.location }}" + chmod 0644 "${INPUT_DOWNLOAD_FILENAME}" + echo "Downloaded ${INPUT_DOWNLOAD_FILENAME} from s3://${INPUT_S3_BUCKET}/${INPUT_LOCATION}" ;; *) echo "Invalid mode. Use 'upload' or 'download'." From 3160a554b31e14065390dacbc613b40dfff19595 Mon Sep 17 00:00:00 2001 From: ffrancis Date: Thu, 30 Jul 2026 17:44:59 +0530 Subject: [PATCH 5/5] Harden aws-s3-exchanger shell execution and file handling Move GitHub expressions out of shell blocks and consume inputs through environment variables. Normalize location prefixes, enable strict shell mode, create URL artifact directories, and apply safer file permissions while preserving SDK script executability. Signed-off-by: ffrancis --- .github/actions/build/action.yml | 1 + .github/workflows/build.yml | 1 + .github/workflows/process_image.yml | 38 ++++++++++++++++++++--------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index b35311d..bf6b110 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -63,3 +63,4 @@ runs: name: build_${{ env.IMAGE_NAME }}.tar path: ${{ github.workspace }}/build_${{ env.IMAGE_NAME }}.tar retention-days: 1 + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 06923b1..c2d0970 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -137,3 +137,4 @@ jobs: rm -rf install/ ${{ env.SDK_NAME }} rm -rf build/ ${{ github.workspace }}/build_${{ env.IMAGE_NAME }}.tar echo "Workspace cleaned up successfully" + diff --git a/.github/workflows/process_image.yml b/.github/workflows/process_image.yml index db75928..0c130b9 100644 --- a/.github/workflows/process_image.yml +++ b/.github/workflows/process_image.yml @@ -79,13 +79,16 @@ jobs: - name: Extract build artifact id: extract_build_artifact shell: bash + env: + WORKSPACE_DIR: ${{ github.workspace }} + IMAGE_NAME_LOCAL: ${{ env.IMAGE_NAME }} run: | #!/bin/bash set -e - mkdir -p ${{ github.workspace }}/build + mkdir -p "${WORKSPACE_DIR}/build" echo "Extracting the build artifact" - tar -xvf ${{ github.workspace }}/build_${{ env.IMAGE_NAME }}.tar -C ${{ github.workspace }}/build + tar -xvf "${WORKSPACE_DIR}/build_${IMAGE_NAME_LOCAL}.tar" -C "${WORKSPACE_DIR}/build" echo "Build artifact extracted successfully" - name: Pull meta-audioreach pre compiled image @@ -103,15 +106,20 @@ jobs: id: extract_image if: ${{ env.IMAGE_NAME != 'raspberrypi4' }} shell: bash + env: + IMAGE_NAME_LOCAL: ${{ env.IMAGE_NAME }} + FILES_TO_COPY: ${{ inputs.files_to_copy }} + DOCKER_IMAGE: ${{ steps.get-docker-image.outputs.image_name }} run: | #!/bin/bash set -e + IMAGE_ARCHIVE="qcom-multimedia-proprietary-image-${IMAGE_NAME_LOCAL}.rootfs.qcomflash.tar.gz" echo "Extracting the image" - tar -xvf qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz - ROOTFS_IMG=$(tar -tf qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz | grep 'rootfs.img$') + tar -xvf "$IMAGE_ARCHIVE" + ROOTFS_IMG=$(tar -tf "$IMAGE_ARCHIVE" | grep 'rootfs.img$') ROOTFS_DIR=$(dirname "$ROOTFS_IMG") - EXPECTED_ROOTFS_DIR="qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}" + EXPECTED_ROOTFS_DIR="qcom-multimedia-proprietary-image-${IMAGE_NAME_LOCAL}" if [ "$ROOTFS_DIR" != "$EXPECTED_ROOTFS_DIR" ] && [ -d "$ROOTFS_DIR" ]; then rm -rf "$EXPECTED_ROOTFS_DIR" mv "$ROOTFS_DIR" "$EXPECTED_ROOTFS_DIR" @@ -121,7 +129,7 @@ jobs: # Export as GitHub Actions environment variables echo "ROOTFS_IMG=$ROOTFS_IMG" >> $GITHUB_ENV echo "ROOTFS_DIR=$ROOTFS_DIR" >> $GITHUB_ENV - rm -rf qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz + rm -rf "$IMAGE_ARCHIVE" echo "Image extracted successfully" ls -l "$ROOTFS_DIR/rootfs.img" @@ -162,8 +170,8 @@ jobs: -v $PWD:/workspace \ -v /tmp/rootfs:/tmp/rootfs \ -w /workspace \ - -e "FILES_TO_COPY=${{ inputs.files_to_copy }}" \ - ${{ steps.get-docker-image.outputs.image_name }} \ + -e "FILES_TO_COPY=${FILES_TO_COPY}" \ + "${DOCKER_IMAGE}" \ bash -c ' set -xe set +e @@ -191,22 +199,28 @@ jobs: id: create_tar_image if: ${{ env.IMAGE_NAME != 'raspberrypi4' }} shell: bash + env: + IMAGE_NAME_LOCAL: ${{ env.IMAGE_NAME }} + ROOTFS_DIR_LOCAL: ${{ env.ROOTFS_DIR }} run: | #!/bin/bash set -e echo $PWD echo "Creating tar image for qcomflash directory" - tar -czvf qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz ${{ env.ROOTFS_DIR }}/ + tar -czvf "qcom-multimedia-proprietary-image-${IMAGE_NAME_LOCAL}.rootfs.qcomflash.tar.gz" "${ROOTFS_DIR_LOCAL}/" # ✅ Moving newly created tar files into presigned_urls path - name: Move tar to presigned_urls directory if: ${{ env.IMAGE_NAME != 'raspberrypi4' }} shell: bash + env: + WORKSPACE_DIR: ${{ github.workspace }} + IMAGE_NAME_LOCAL: ${{ env.IMAGE_NAME }} run: | set -e - mkdir -p ${{ github.workspace }}/presigned_urls + mkdir -p "${WORKSPACE_DIR}/presigned_urls" - FILE="qcom-multimedia-proprietary-image-${{ env.IMAGE_NAME }}.rootfs.qcomflash.tar.gz" + FILE="qcom-multimedia-proprietary-image-${IMAGE_NAME_LOCAL}.rootfs.qcomflash.tar.gz" if [ ! -f "$FILE" ]; then @@ -214,7 +228,7 @@ jobs: exit 1 fi - mv "$FILE" ${{ github.workspace }}/presigned_urls/ + mv "$FILE" "${WORKSPACE_DIR}/presigned_urls/" echo "Moved $FILE to presigned_urls/" - name: Upload tar image