From 85e9185417a4dcc527ad9f8ff88fd53059d17690 Mon Sep 17 00:00:00 2001 From: srmungar Date: Thu, 14 May 2026 23:20:07 -0700 Subject: [PATCH 01/28] Adding support for eLxr13 Bianca Release --- .../chrootenvconfigs/chrootenv_aarch64.yml | 29 +++++ .../chrootenvconfigs/chrootenv_x86_64.yml | 29 +++++ .../elxr13/chrootenvconfigs/local.list | 1 + config/osv/wind-river-elxr/elxr13/config.yml | 15 +++ .../imageconfigs/additionalfiles/dhcp.network | 10 ++ .../additionalfiles/elxr-aria.list | 1 + .../additionalfiles/getty@.service | 7 ++ .../additionalfiles/serial-getty@.service | 7 ++ .../defaultconfigs/default-initrd-x86_64.yml | 69 +++++++++++ .../defaultconfigs/default-iso-x86_64.yml | 76 +++++++++++++ .../defaultconfigs/default-raw-aarch64.yml | 95 ++++++++++++++++ .../defaultconfigs/default-raw-x86_64.yml | 97 ++++++++++++++++ .../elxr13/providerconfigs/amd64_repo.yml | 13 +++ .../elxr13/providerconfigs/arm64_repo.yml | 13 +++ .../elxr13/providerconfigs/repo.yml | 13 +++ .../elxr13-aarch64-minimal-raw.yml | 45 ++++++++ image-templates/elxr13-x86_64-dlstreamer.yml | 107 ++++++++++++++++++ image-templates/elxr13-x86_64-edge-raw.yml | 84 ++++++++++++++ .../elxr13-x86_64-minimal-initrd.yml | 27 +++++ image-templates/elxr13-x86_64-minimal-iso.yml | 26 +++++ internal/config/schema/os-config.schema.json | 2 +- .../schema/os-image-template.schema.json | 2 +- 22 files changed, 766 insertions(+), 2 deletions(-) create mode 100644 config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_aarch64.yml create mode 100644 config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_x86_64.yml create mode 100644 config/osv/wind-river-elxr/elxr13/chrootenvconfigs/local.list create mode 100644 config/osv/wind-river-elxr/elxr13/config.yml create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/dhcp.network create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/getty@.service create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/serial-getty@.service create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml create mode 100644 config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml create mode 100644 config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml create mode 100644 config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml create mode 100644 config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml create mode 100644 image-templates/elxr13-aarch64-minimal-raw.yml create mode 100644 image-templates/elxr13-x86_64-dlstreamer.yml create mode 100644 image-templates/elxr13-x86_64-edge-raw.yml create mode 100644 image-templates/elxr13-x86_64-minimal-initrd.yml create mode 100644 image-templates/elxr13-x86_64-minimal-iso.yml diff --git a/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_aarch64.yml b/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_aarch64.yml new file mode 100644 index 000000000..f63b772ec --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_aarch64.yml @@ -0,0 +1,29 @@ +essential: + - dpkg + - apt + - debianutils + - init-system-helpers + - dash + - mount + - sysvinit-utils + - gzip + - bash + - util-linux + - tar + - base-files + - base-passwd + - sed + - bsdutils + - coreutils + - findutils + - grep + - login + - perl-base + - diffutils + - libc-bin + - hostname + - ncurses-bin + - ncurses-base + +packages: + - mmdebstrap diff --git a/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_x86_64.yml b/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_x86_64.yml new file mode 100644 index 000000000..6e191ca68 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/chrootenv_x86_64.yml @@ -0,0 +1,29 @@ +essential: + - dpkg + - apt + - debianutils + - init-system-helpers + - dash + - mount + - sysvinit-utils + - gzip + - bash + - util-linux + - tar + - base-files + - base-passwd + - sed + - bsdutils + - coreutils + - findutils + - grep + - login + - perl-base + - diffutils + - libc-bin + - hostname + - ncurses-bin + - ncurses-base + +packages: + - mmdebstrap \ No newline at end of file diff --git a/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/local.list b/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/local.list new file mode 100644 index 000000000..b58ea4a8d --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/chrootenvconfigs/local.list @@ -0,0 +1 @@ +deb [trusted=yes] file:///cdrom/cache-repo stable main \ No newline at end of file diff --git a/config/osv/wind-river-elxr/elxr13/config.yml b/config/osv/wind-river-elxr/elxr13/config.yml new file mode 100644 index 000000000..1f74dbc19 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/config.yml @@ -0,0 +1,15 @@ +# Wind River ELXR12 OS Configuration +# This file defines architecture-specific build configurations for Wind River ELXR12 + +x86_64: + dist: bianca # Distribution identifier + arch: x86_64 # Target architecture + pkgType: deb # Package management system + chrootenvConfigFile: chrootenvconfigs/chrootenv_x86_64.yml # Path to chrootenv config + releaseVersion: "13.10.0.0" # Distribution release version +aarch64: + dist: bianca # Distribution identifier + arch: aarch64 # Target architecture + pkgType: deb # Package management system + chrootenvConfigFile: chrootenvconfigs/chrootenv_aarch64.yml # Path to chrootenv config + releaseVersion: "13.10.0.0" # Distribution release version diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/dhcp.network b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/dhcp.network new file mode 100644 index 000000000..6a1e5395c --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/dhcp.network @@ -0,0 +1,10 @@ +[Match] +Name=en* + +[Network] +DHCP=yes +IPv6AcceptRA=no + +[DHCPv4] +SendRelease=false +ClientIdentifier=mac diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list new file mode 100644 index 000000000..f6b859fba --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list @@ -0,0 +1 @@ +deb [trusted=amd64 signed-by=/usr/share/keyrings/elxr-archive-keyring.gpg] https://mirror.elxr.dev/elxr aria main diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/getty@.service b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/getty@.service new file mode 100644 index 000000000..a92691e0a --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/getty@.service @@ -0,0 +1,7 @@ +[Service] +ExecStart= +ExecStart=-/sbin/agetty --noclear --autologin root --keep-baud %I $TERM + +# Default to tty1 but allow other choices +[Install] +Alias=getty.target.wants/getty@tty1.service \ No newline at end of file diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/serial-getty@.service b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/serial-getty@.service new file mode 100644 index 000000000..7f0db6aa5 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/serial-getty@.service @@ -0,0 +1,7 @@ +[Service] +ExecStart= +ExecStart=-/sbin/agetty --noclear --autologin root --keep-baud %I $TERM + +# Default to ttyS0 but allow other choices +[Install] +Alias=getty.target.wants/serial-getty@ttyS0.service \ No newline at end of file diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml new file mode 100644 index 000000000..ba42d9718 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml @@ -0,0 +1,69 @@ +image: + name: minimal-os-image-elxr + version: "12.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: img # Image type, valid value: [raw, iso]. + +systemConfig: + name: Default_Initrd + description: Default yml configuration for initrd image + + bootloader: + bootType: efi # (efi or legacy) + provider: grub # (grub for efi and legacy mode, or systemd-boot for efi mode) + + packages: + - ca-certificates + - vim + - sudo + - net-tools + - openssh-client + - openssh-server + - procps + - less + - dbus + - policykit-1 + - dosfstools + - efibootmgr + - eject + - curl + - mmdebstrap + - wget + - cryptsetup + - uefi-ext4 + - systemd-resolved + - cloud-guest-utils + - xterm + - dracut + - grub2 + - grub-pc-bin + - grub-efi-amd64-bin + - gdisk + + additionalFiles: + - local: ../additionalfiles/dhcp.network + final: /etc/systemd/network/dhcp.network + - local: ../additionalfiles/elxr-aria.list + final: /etc/apt/sources.list.d/elxr-aria.list + - local: ../additionalfiles/getty@.service + final: /usr/lib/systemd/system/getty@.service + - local: ../additionalfiles/serial-getty@.service + final: /usr/lib/systemd/system/serial-getty@.service + - local: ../../../../../general/isolinux/attendedinstaller + final: /root/attendedinstaller + - local: ../../../../../../build/live-installer + final: /usr/bin/live-installer + + users: + - name: root + startupScript: "/root/attendedinstaller" + + kernel: + name: kernel + cmdline: "quiet splash console=ttyS0,115200 console=tty0 loglevel=7" + packages: + - linux-image-amd64 diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml new file mode 100644 index 000000000..45107f940 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml @@ -0,0 +1,76 @@ +image: + name: minimal-os-image-elxr + version: "12.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: iso # Image type, valid value: [raw, iso]. + +disk: + name: Default_ISO + partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] + partitions: # Required for raw, optional for ISO, not needed for rootfs. + - id: boot + type: esp + flags: + - esp + - boot + start: 1MiB + end: 513MiB + fsType: fat32 + mountPoint: /boot/efi + + - id: rootfs + type: linux-root-amd64 + start: 513MiB + end: "0" # 0 means use the rest of the disk space + fsType: ext4 + mountPoint: / + +systemConfig: # Required + name: Default_ISO + description: Default yml configuration for iso image + + initramfs: + template: default-initrd-x86_64.yml + + bootloader: + bootType: efi # (efi or legacy) + provider: grub # (grub for efi and legacy mode, or systemd-boot for efi mode) + + packages: + - ca-certificates + - vim + - sudo + - net-tools + - openssh-client + - openssh-server + - procps + - less + - dbus + - policykit-1 + - curl + - wget + - uefi-ext4 + - systemd-resolved + - cloud-guest-utils + - xterm + - dracut + - grub2 + - grub2-common + - grub-efi-amd64-bin + - efibootmgr + + additionalFiles: + - local: ../additionalfiles/dhcp.network + final: /etc/systemd/network/dhcp.network + - local: ../additionalfiles/elxr-aria.list + final: /etc/apt/sources.list.d/elxr-aria.list + + kernel: + name: kernel + cmdline: "quiet splash console=ttyS0,115200 console=tty0 loglevel=7" + packages: + - linux-image-amd64 diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml new file mode 100644 index 000000000..d465ed6b0 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml @@ -0,0 +1,95 @@ +image: + name: minimal-os-image-elxr + version: "13.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: aarch64 # Target OS architecture + imageType: raw # Image type, valid value: [raw, iso]. + +disk: + name: Default_Raw # 1:1 mapping to the systemConfigs name + artifacts: + - + type: raw # image file format + compression: gz # image compression format (optional) + size: 4GiB # 4G, 4GB, 4096 MiB also valid. (Required for raw) + partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] + partitions: # Required for raw, optional for ISO, not needed for rootfs. + - id: boot + type: esp + flags: + - esp + - boot + start: 1MiB + end: 513MiB + fsType: fat32 + mountPoint: /boot/efi + mountOptions: umask=0077 + + - id: rootfs + type: linux-root-arm64 + start: 513MiB + end: 2561MiB # 513MiB + 2GiB (2048MiB) = 2561MiB + fsType: ext4 + mountPoint: / + mountOptions: defaults + + - id: roothashmap + type: linux + start: 2561MiB + end: 3061MiB # 2561MiB + 500MiB = 3061MiB + fsType: ext4 + mountPoint: none + + - id: userdata + type: linux + start: 3061MiB + end: "0" # 2561MiB + 2GiB (2048MiB) = 4609MiB + fsType: ext4 + mountPoint: /opt + +systemConfig: + name: Default_Raw + description: Default yml configuration for raw image + + bootloader: + bootType: efi # (efi or legacy) + provider: systemd-boot # (grub for efi and legacy mode, or systemd-boot for efi mode) + + immutability: + enabled: true # default is true + + packages: + - ca-certificates + - vim + - sudo + - net-tools + - openssh-client + - openssh-server + - procps + - less + - dbus + - policykit-1 + - curl + - wget + - uefi-ext4 + - systemd-resolved + - cloud-guest-utils + - dracut + - systemd-boot + - elxr-archive-keyring + + additionalFiles: + - local: ../additionalfiles/dhcp.network + final: /etc/systemd/network/dhcp.network + - local: ../additionalfiles/elxr-aria.list + final: /etc/apt/sources.list.d/elxr-aria.list + + kernel: + name: kernel + cmdline: "quiet splash console=ttyS0,115200 console=tty0 loglevel=7" + uki: true + packages: + - linux-image-cloud-arm64 diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml new file mode 100644 index 000000000..4325f446c --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml @@ -0,0 +1,97 @@ +image: + name: minimal-os-image-elxr + version: "12.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: raw # Image type, valid value: [raw, iso]. + +disk: + name: Default_Raw # 1:1 mapping to the systemConfigs name + artifacts: + - + type: raw # image file format + compression: gz # image compression format (optional) + size: 4GiB # 4G, 4GB, 4096 MiB also valid. (Required for raw) + partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] + partitions: # Required for raw, optional for ISO, not needed for rootfs. + - id: boot + type: esp + flags: + - esp + - boot + start: 1MiB + end: 513MiB + fsType: fat32 + mountPoint: /boot/efi + mountOptions: umask=0077 + + - id: rootfs + type: linux-root-amd64 + start: 513MiB + end: 2561MiB # 513MiB + 2GiB (2048MiB) = 2561MiB + fsType: ext4 + mountPoint: / + mountOptions: defaults + + - id: roothashmap + type: linux + start: 2561MiB + end: 3061MiB # 2561MiB + 500MiB = 3061MiB + fsType: ext4 + mountPoint: none + + - id: userdata + type: linux + start: 3061MiB + end: "0" # 2561MiB + 2GiB (2048MiB) = 4609MiB + fsType: ext4 + mountPoint: /opt + +systemConfig: + name: Default_Raw + description: Default yml configuration for raw image + + bootloader: + bootType: efi # (efi or legacy) + provider: systemd-boot # (grub for efi and legacy mode, or systemd-boot for efi mode) + + immutability: + enabled: true # default is true + + packages: + - ca-certificates + - vim + - sudo + - net-tools + - openssh-client + - openssh-server + - procps + - less + - dbus + - policykit-1 + - curl + - wget + - uefi-ext4 + - systemd-resolved + - cloud-guest-utils + - dracut + - systemd-boot + - elxr-archive-keyring + - systemd-timesyncd + - efibootmgr + + additionalFiles: + - local: ../additionalfiles/dhcp.network + final: /etc/systemd/network/dhcp.network + - local: ../additionalfiles/elxr-aria.list + final: /etc/apt/sources.list.d/elxr-aria.list + + kernel: + name: kernel + cmdline: "quiet splash console=ttyS0,115200 console=tty0 loglevel=7" + uki: true + packages: + - linux-image-amd64 diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml new file mode 100644 index 000000000..8721b0d6e --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml @@ -0,0 +1,13 @@ +repositories: + - name: "bianca" + type: "deb" # Repository type: rpm or deb + baseURL: "https://mirror.elxr.dev/elxr" + pkgPrefix: "https://mirror.elxr.dev/elxr/" + releaseFile: "https://mirror.elxr.dev/elxr/dists/bianca/Release" + releaseSign: "https://mirror.elxr.dev/elxr/dists/bianca/Release.gpg" + pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" + gpgCheck: true + repoGPGCheck: true + enabled: true + component: "main non-free-firmware" # Repository component/section identifier + buildPath: "./builds/elxr13/main" # Will be replaced with temp_dir/builds/elxr13 at runtime diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml new file mode 100644 index 000000000..8721b0d6e --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml @@ -0,0 +1,13 @@ +repositories: + - name: "bianca" + type: "deb" # Repository type: rpm or deb + baseURL: "https://mirror.elxr.dev/elxr" + pkgPrefix: "https://mirror.elxr.dev/elxr/" + releaseFile: "https://mirror.elxr.dev/elxr/dists/bianca/Release" + releaseSign: "https://mirror.elxr.dev/elxr/dists/bianca/Release.gpg" + pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" + gpgCheck: true + repoGPGCheck: true + enabled: true + component: "main non-free-firmware" # Repository component/section identifier + buildPath: "./builds/elxr13/main" # Will be replaced with temp_dir/builds/elxr13 at runtime diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml new file mode 100644 index 000000000..35de9fbb0 --- /dev/null +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml @@ -0,0 +1,13 @@ +repositories: + - name: "aria" + type: "deb" # Repository type: rpm or deb + baseURL: "https://mirror.elxr.dev/elxr" + pkgPrefix: "https://mirror.elxr.dev/elxr/" + releaseFile: "https://mirror.elxr.dev/elxr/dists/aria/Release" + releaseSign: "https://mirror.elxr.dev/elxr/dists/aria/Release.gpg" + pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" + gpgCheck: true + repoGPGCheck: true + enabled: true + component: "main non-free-firmware" # Repository component/section identifier + buildPath: "./builds/elxr12/main" # Will be replaced with temp_dir/builds/elxr12 at runtime diff --git a/image-templates/elxr13-aarch64-minimal-raw.yml b/image-templates/elxr13-aarch64-minimal-raw.yml new file mode 100644 index 000000000..ecf72567a --- /dev/null +++ b/image-templates/elxr13-aarch64-minimal-raw.yml @@ -0,0 +1,45 @@ +image: + name: elxr13-aarch64-minimal + version: "1.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: aarch64 # Target OS architecture + imageType: raw # Image type, valid value: [raw, iso]. + +disk: + name: Minimal_Raw # 1:1 mapping to the systemConfigs name + artifacts: + - + type: raw # image file format, valid value [raw, vhd, vhdx, qcow2, vmdk, vdi] + compression: gz # image compression format (optional) + - type: vhdx + size: 4GiB # 4G, 4GB, 4096 MiB also valid. (Required for raw) + partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] + partitions: # Required for raw, optional for ISO, not needed for rootfs. + - id: boot + type: esp + flags: + - esp + - boot + start: 1MiB + end: 513MiB + fsType: fat32 + mountPoint: /boot/efi + mountOptions: umask=0077 + + - id: rootfs + type: linux-root-arm64 + start: 513MiB + end: "0" + fsType: ext4 + mountPoint: / + mountOptions: defaults + +systemConfig: + name: Minimal_Raw + description: Default yml configuration for raw image + + immutability: + enabled: false # default is true, overridden to false here diff --git a/image-templates/elxr13-x86_64-dlstreamer.yml b/image-templates/elxr13-x86_64-dlstreamer.yml new file mode 100644 index 000000000..5ae6c6452 --- /dev/null +++ b/image-templates/elxr13-x86_64-dlstreamer.yml @@ -0,0 +1,107 @@ +# AI-searchable metadata for template discovery +metadata: + description: ELXR 12 image with Intel DL Streamer for video analytics and AI inference + use_cases: + - Video analytics pipelines + - AI inference at the edge + - Computer vision applications + - Media processing workloads + - Deep learning inference + keywords: + - dlstreamer + - video + - analytics + - ai + - inference + - computer-vision + - media + - deep-learning + - intel + - elxr + +image: + name: elxr13-dlstreamer-x86_64 + version: "13.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: raw # Image type, valid value: [raw, iso]. + +# Sample list of additional package repositories; replace codename, url, and pkey values as needed +packageRepositories: + - codename: "ubuntu22" + url: "https://apt.repos.intel.com/openvino/2025" + pkey: "https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB" + component: "main" + + - codename: "jammy" + url: "http://archive.ubuntu.com/ubuntu" + pkey: "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C" # Uncomment and replace in real config + component: "main universe" + + - codename: "jammy-updates" + url: "http://archive.ubuntu.com/ubuntu" + pkey: "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C" + component: "main universe" + + - codename: "noble" + url: "https://download.01.org/intel-linux-overlay/ubuntu/" + pkey: "https://download.01.org/intel-linux-overlay/ubuntu/E6FA98203588250569758E97D176E3162086EE4C.gpg" + component: "kernels" + + - codename: "ubuntu22" + url: "https://apt.repos.intel.com/edgeai/dlstreamer/ubuntu22" + pkey: "https://apt.repos.intel.com/edgeai/dlstreamer/GPG-PUB-KEY-INTEL-DLS.gpg" + + - codename: "jammy" + url: "https://repositories.intel.com/gpu/ubuntu" + pkey: "https://repositories.intel.com/gpu/intel-graphics.key" + component: "unified" + +disk: + name: Minimal_Raw # 1:1 mapping to the systemConfigs name + artifacts: + - + type: raw # image file format, valid value [raw, vhd, vhdx, qcow2, vmdk, vdi] + compression: gz # image compression format (optional) + size: 8GiB # 4G, 4GB, 4096 MiB also valid. (Required for raw) + partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] + partitions: # Required for raw, optional for ISO, not needed for rootfs. + - id: boot + type: esp + flags: + - esp + - boot + start: 1MiB + end: 513MiB + fsType: fat32 + mountPoint: /boot/efi + mountOptions: umask=0077 + + - id: rootfs + type: linux-root-amd64 + start: 513MiB + end: "0" + fsType: ext4 + mountPoint: / + mountOptions: defaults + +systemConfig: + name: Minimal_Raw + description: Default yml configuration for raw image + + immutability: + enabled: false # default is true, overridden to false here + + packages: + - intel-dlstreamer_2025.2.0 + - firmware-linux + + kernel: + version: "251229t065211z-r2" + cmdline: "console=ttyS0,115200 console=tty0 loglevel=7 i915.force_probe=*" + packages: + - linux-image-6.12-intel + - linux-headers-6.12-intel diff --git a/image-templates/elxr13-x86_64-edge-raw.yml b/image-templates/elxr13-x86_64-edge-raw.yml new file mode 100644 index 000000000..ea4aad747 --- /dev/null +++ b/image-templates/elxr13-x86_64-edge-raw.yml @@ -0,0 +1,84 @@ +# AI-searchable metadata for template discovery +metadata: + description: ELXR 12 edge-optimized image with container runtime and edge computing packages + use_cases: + - Edge computing deployments + - Container workloads at the edge + - IoT gateway systems + - Industrial edge nodes + keywords: + - edge + - container + - docker + - iot + - gateway + - industrial + - elxr + +image: + name: minimal-os-image-elxr + version: "13.0.0" + +target: + os: wind-river-elxr + dist: elxr13 + arch: x86_64 + imageType: raw + +# Sample list of additional package repositories; replace codename, url, and pkey values as needed +packageRepositories: + - codename: "company-internal" + url: "" + pkey: "" # Uncomment and replace in real config + component: "main" + + - codename: "dev-tools" + url: "" + pkey: "" # Uncomment and replace in real config + + - codename: "intel-openvino" + url: "" + pkey: "" # Uncomment and replace in real config + component: "restricted" + +systemConfig: + name: edge + description: Minimal eLxr image with immutable rootfs + + immutability: + enabled: true # default is true + # To enable Secure Boot, provide the actual file paths for your environment below and uncomment the relevant lines. + # secureBootDBKey: "" + # secureBootDBCrt: "" + # secureBootDBCer: "" + + packages: + - systemd-boot + - dracut + - linux-image-amd64 + - ca-certificates + - vim + - sudo + - net-tools + - openssh-client + - openssh-server + - procps + - less + - dbus + - policykit-1 + - curl + - wget + - ostree + - ostree-boot + #- python3-apt-ostree + - uefi-ext4 + - systemd-resolved + - cloud-guest-utils + - xterm + + kernel: + version: "6.1" + cmdline: "console=ttyS0,115200 console=tty0 loglevel=7" + #packages: + # - kernel-elxr12 + # - kernel-modules-elxr12 diff --git a/image-templates/elxr13-x86_64-minimal-initrd.yml b/image-templates/elxr13-x86_64-minimal-initrd.yml new file mode 100644 index 000000000..778e8abef --- /dev/null +++ b/image-templates/elxr13-x86_64-minimal-initrd.yml @@ -0,0 +1,27 @@ +# AI-searchable metadata for template discovery +metadata: + description: Minimal ELXR 12 initrd/initramfs image for network boot and PXE + use_cases: + - PXE network boot + - Diskless boot environments + - Network-based provisioning + - Live boot systems + keywords: + - initrd + - initramfs + - pxe + - network-boot + - diskless + - live + - minimal + - elxr + +image: + name: elxr13-x86_64-minimal + version: "1.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: img # Image type, valid value: [raw, iso, img]. diff --git a/image-templates/elxr13-x86_64-minimal-iso.yml b/image-templates/elxr13-x86_64-minimal-iso.yml new file mode 100644 index 000000000..34834ba94 --- /dev/null +++ b/image-templates/elxr13-x86_64-minimal-iso.yml @@ -0,0 +1,26 @@ +# AI-searchable metadata for template discovery +metadata: + description: Minimal ELXR 12 bootable ISO image for installation media + use_cases: + - Creating bootable installation media + - USB/DVD installation + - Bare metal provisioning + - System recovery + keywords: + - iso + - bootable + - installation + - usb + - dvd + - minimal + - elxr + +image: + name: elxr13-x86_64-minimal + version: "1.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: iso # Image type, valid value: [raw, iso]. diff --git a/internal/config/schema/os-config.schema.json b/internal/config/schema/os-config.schema.json index e14596912..feb773236 100644 --- a/internal/config/schema/os-config.schema.json +++ b/internal/config/schema/os-config.schema.json @@ -12,7 +12,7 @@ "dist": { "type": "string", "description": "Distribution identifier", - "enum": ["azl3", "emt3", "elxr12", "aria", "ubuntu24", "ubuntu26", "rcd10", "debian13"] + "enum": ["azl3", "emt3", "elxr12", "elxr13", "aria", "bianca", "ubuntu24", "ubuntu26", "rcd10", "debian13"] }, "arch": { "type": "string", diff --git a/internal/config/schema/os-image-template.schema.json b/internal/config/schema/os-image-template.schema.json index d5764bab8..a78b50523 100644 --- a/internal/config/schema/os-image-template.schema.json +++ b/internal/config/schema/os-image-template.schema.json @@ -59,7 +59,7 @@ }, { "if": { "properties": { "os": { "const": "wind-river-elxr" } } }, - "then": { "properties": { "dist": { "enum": ["elxr12"] } } } + "then": { "properties": { "dist": { "enum": ["elxr12", "elxr13"] } } } }, { "if": { "properties": { "os": { "const": "debian" } } }, From 14520901da830c939625be5cba4fab9dadd631a4 Mon Sep 17 00:00:00 2001 From: Subba Mungara Date: Thu, 14 May 2026 23:39:49 -0700 Subject: [PATCH 02/28] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../elxr13/imageconfigs/additionalfiles/elxr-aria.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list index f6b859fba..d0901ec04 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list @@ -1 +1 @@ -deb [trusted=amd64 signed-by=/usr/share/keyrings/elxr-archive-keyring.gpg] https://mirror.elxr.dev/elxr aria main +deb [trusted=amd64 signed-by=/usr/share/keyrings/elxr-archive-keyring.gpg] https://mirror.elxr.dev/elxr bianca main From 9594b78c2f0ce8ce58b6c73d36eda0cb46682b9a Mon Sep 17 00:00:00 2001 From: Subba Mungara Date: Thu, 14 May 2026 23:40:24 -0700 Subject: [PATCH 03/28] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../imageconfigs/defaultconfigs/default-initrd-x86_64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml index ba42d9718..2d84ca084 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml @@ -1,6 +1,6 @@ image: name: minimal-os-image-elxr - version: "12.0.0" + version: "13.0.0" target: os: wind-river-elxr # Target OS name From 966b4478f623a2de1cbad1db17cfbd8db7f59cca Mon Sep 17 00:00:00 2001 From: Subba Mungara Date: Thu, 14 May 2026 23:40:57 -0700 Subject: [PATCH 04/28] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- image-templates/elxr13-x86_64-minimal-iso.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image-templates/elxr13-x86_64-minimal-iso.yml b/image-templates/elxr13-x86_64-minimal-iso.yml index 34834ba94..c9bfca89b 100644 --- a/image-templates/elxr13-x86_64-minimal-iso.yml +++ b/image-templates/elxr13-x86_64-minimal-iso.yml @@ -1,6 +1,6 @@ # AI-searchable metadata for template discovery metadata: - description: Minimal ELXR 12 bootable ISO image for installation media + description: Minimal ELXR 13 bootable ISO image for installation media use_cases: - Creating bootable installation media - USB/DVD installation From 464bbd510e52496f552238a3a158f01567c15c4c Mon Sep 17 00:00:00 2001 From: Subba Mungara Date: Thu, 14 May 2026 23:41:33 -0700 Subject: [PATCH 05/28] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml index 35de9fbb0..361bbc784 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml @@ -10,4 +10,4 @@ repositories: repoGPGCheck: true enabled: true component: "main non-free-firmware" # Repository component/section identifier - buildPath: "./builds/elxr12/main" # Will be replaced with temp_dir/builds/elxr12 at runtime + buildPath: "./builds/elxr13/main" # Will be replaced with temp_dir/builds/elxr13 at runtime From c63f6921a3457100027c13b056204614ba6ad91c Mon Sep 17 00:00:00 2001 From: Subba Mungara Date: Thu, 14 May 2026 23:50:13 -0700 Subject: [PATCH 06/28] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml index 361bbc784..401b676eb 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml @@ -3,8 +3,8 @@ repositories: type: "deb" # Repository type: rpm or deb baseURL: "https://mirror.elxr.dev/elxr" pkgPrefix: "https://mirror.elxr.dev/elxr/" - releaseFile: "https://mirror.elxr.dev/elxr/dists/aria/Release" - releaseSign: "https://mirror.elxr.dev/elxr/dists/aria/Release.gpg" + releaseFile: "https://mirror.elxr.dev/elxr/dists/bianca/Release" + releaseSign: "https://mirror.elxr.dev/elxr/dists/bianca/Release.gpg" pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" gpgCheck: true repoGPGCheck: true From c48d9ec8d589efd55eae371602386022c4c79967 Mon Sep 17 00:00:00 2001 From: srmungar Date: Thu, 14 May 2026 23:51:43 -0700 Subject: [PATCH 07/28] updated missing modifications --- internal/provider/elxr/elxr.go | 11 +++++++---- internal/provider/elxr/elxr_test.go | 8 ++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/provider/elxr/elxr.go b/internal/provider/elxr/elxr.go index 31685e1a6..28fa88551 100644 --- a/internal/provider/elxr/elxr.go +++ b/internal/provider/elxr/elxr.go @@ -61,7 +61,7 @@ func (p *eLxr) Init(dist, arch string) error { arch = "arm64" } - cfgs, err := loadRepoConfig("", arch) + cfgs, err := loadRepoConfig(dist, arch) if err != nil { log.Errorf("Parsing repo config failed: %v", err) return err @@ -305,11 +305,14 @@ func (p *eLxr) downloadImagePkgs(template *config.ImageTemplate) error { return nil } -func loadRepoConfig(repoUrl string, arch string) ([]debutils.RepoConfig, error) { +func loadRepoConfig(dist string, arch string) ([]debutils.RepoConfig, error) { var repoConfigs []debutils.RepoConfig + if dist == "" { + dist = "elxr12" + } - // Load provider repo config for elxr - use correct OS name - providerConfigs, err := config.LoadProviderRepoConfig(OsName, "elxr12", arch) // Use "wind-river-elxr" and "aria" dist + // Load provider repo config for eLxr based on requested distribution. + providerConfigs, err := config.LoadProviderRepoConfig(OsName, dist, arch) if err != nil { return repoConfigs, fmt.Errorf("failed to load provider repo config: %w", err) } diff --git a/internal/provider/elxr/elxr_test.go b/internal/provider/elxr/elxr_test.go index 31581b5fe..acb41caae 100644 --- a/internal/provider/elxr/elxr_test.go +++ b/internal/provider/elxr/elxr_test.go @@ -173,7 +173,7 @@ func TestLoadRepoConfig(t *testing.T) { return } - config, err := loadRepoConfig("", "amd64") + config, err := loadRepoConfig("elxr12", "amd64") if err != nil { t.Skipf("loadRepoConfig failed (expected in test environment): %v", err) return @@ -972,7 +972,7 @@ func TestLoadRepoConfigArchMapping(t *testing.T) { for _, tc := range testCases { t.Run(tc.arch, func(t *testing.T) { - cfgs, err := loadRepoConfig("", tc.arch) + cfgs, err := loadRepoConfig("elxr12", tc.arch) if err != nil { t.Logf("loadRepoConfig failed for arch %s: %v", tc.arch, err) return @@ -1004,7 +1004,7 @@ func TestLoadRepoConfigInvalidArch(t *testing.T) { return } - _, err := loadRepoConfig("", "invalid-arch") + _, err := loadRepoConfig("elxr12", "invalid-arch") if err == nil { t.Error("Expected error for invalid architecture") } else { @@ -1330,7 +1330,7 @@ func TestLoadRepoConfigMultipleRepos(t *testing.T) { return } - cfgs, err := loadRepoConfig("", "amd64") + cfgs, err := loadRepoConfig("elxr12", "amd64") if err != nil { t.Logf("loadRepoConfig failed: %v", err) return From 6c0d89c6f0d9341eb6f836fd3edec82b335bd948 Mon Sep 17 00:00:00 2001 From: srmungar Date: Thu, 14 May 2026 23:57:56 -0700 Subject: [PATCH 08/28] updated the missing code on support for elxr13 in loadproviderrepoconfig function --- internal/provider/elxr/elxr.go | 16 +++++++++++++--- internal/provider/elxr/elxr_test.go | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/internal/provider/elxr/elxr.go b/internal/provider/elxr/elxr.go index 28fa88551..2d42408b8 100644 --- a/internal/provider/elxr/elxr.go +++ b/internal/provider/elxr/elxr.go @@ -307,9 +307,7 @@ func (p *eLxr) downloadImagePkgs(template *config.ImageTemplate) error { func loadRepoConfig(dist string, arch string) ([]debutils.RepoConfig, error) { var repoConfigs []debutils.RepoConfig - if dist == "" { - dist = "elxr12" - } + dist = normalizeElxrDist(dist) // Load provider repo config for eLxr based on requested distribution. providerConfigs, err := config.LoadProviderRepoConfig(OsName, dist, arch) @@ -352,6 +350,18 @@ func loadRepoConfig(dist string, arch string) ([]debutils.RepoConfig, error) { return repoConfigs, nil } +// normalizeElxrDist maps user/config aliases to supported distribution directory names. +func normalizeElxrDist(dist string) string { + switch dist { + case "", "elxr12", "aria": + return "elxr12" + case "elxr13", "bianca": + return "elxr13" + default: + return dist + } +} + // displayImageArtifacts displays all image artifacts in the build directory func displayImageArtifacts(imageBuildDir, imageType string) { display.PrintImageDirectorySummary( diff --git a/internal/provider/elxr/elxr_test.go b/internal/provider/elxr/elxr_test.go index acb41caae..127ef1209 100644 --- a/internal/provider/elxr/elxr_test.go +++ b/internal/provider/elxr/elxr_test.go @@ -196,6 +196,28 @@ func TestLoadRepoConfig(t *testing.T) { t.Logf("Successfully loaded repo config: %s", config[0].Name) } +func TestNormalizeElxrDist(t *testing.T) { + tests := []struct { + in string + want string + }{ + {"", "elxr12"}, + {"aria", "elxr12"}, + {"elxr12", "elxr12"}, + {"bianca", "elxr13"}, + {"elxr13", "elxr13"}, + {"custom", "custom"}, + } + + for _, tt := range tests { + t.Run(tt.in, func(t *testing.T) { + if got := normalizeElxrDist(tt.in); got != tt.want { + t.Fatalf("normalizeElxrDist(%q) = %q, want %q", tt.in, got, tt.want) + } + }) + } +} + // mockChrootEnv is a simple mock implementation of ChrootEnvInterface for testing type mockChrootEnv struct{} From 33dda44c188a7f0c6f6d3871190bb26361f191e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 07:13:12 +0000 Subject: [PATCH 09/28] fix(elxr13): address remaining Bianca review feedback Agent-Logs-Url: https://github.com/open-edge-platform/image-composer-tool/sessions/457e5714-5f55-4a51-add5-5a30a394805f Co-authored-by: srmungar <28767344+srmungar@users.noreply.github.com> --- config/osv/wind-river-elxr/elxr13/config.yml | 4 +-- .../defaultconfigs/default-iso-x86_64.yml | 2 +- .../defaultconfigs/default-raw-x86_64.yml | 2 +- .../elxr13-aarch64-minimal-raw.yml | 14 ++++++++ image-templates/elxr13-x86_64-dlstreamer.yml | 2 +- image-templates/elxr13-x86_64-edge-raw.yml | 2 +- .../elxr13-x86_64-minimal-initrd.yml | 2 +- internal/provider/elxr/elxr_test.go | 32 +++++++++++++++++++ 8 files changed, 53 insertions(+), 7 deletions(-) diff --git a/config/osv/wind-river-elxr/elxr13/config.yml b/config/osv/wind-river-elxr/elxr13/config.yml index 1f74dbc19..00bc09e80 100644 --- a/config/osv/wind-river-elxr/elxr13/config.yml +++ b/config/osv/wind-river-elxr/elxr13/config.yml @@ -1,5 +1,5 @@ -# Wind River ELXR12 OS Configuration -# This file defines architecture-specific build configurations for Wind River ELXR12 +# Wind River ELXR13 OS Configuration +# This file defines architecture-specific build configurations for Wind River ELXR13 x86_64: dist: bianca # Distribution identifier diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml index 45107f940..2fb78f6df 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml @@ -1,6 +1,6 @@ image: name: minimal-os-image-elxr - version: "12.0.0" + version: "13.0.0" target: os: wind-river-elxr # Target OS name diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml index 4325f446c..c04d5a407 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml @@ -1,6 +1,6 @@ image: name: minimal-os-image-elxr - version: "12.0.0" + version: "13.0.0" target: os: wind-river-elxr # Target OS name diff --git a/image-templates/elxr13-aarch64-minimal-raw.yml b/image-templates/elxr13-aarch64-minimal-raw.yml index ecf72567a..e5324f21a 100644 --- a/image-templates/elxr13-aarch64-minimal-raw.yml +++ b/image-templates/elxr13-aarch64-minimal-raw.yml @@ -1,3 +1,17 @@ +metadata: + description: Minimal ELXR 13 image with essential packages for lightweight ARM64 deployments + use_cases: + - Lightweight ARM64 deployments + - Embedded and edge devices + - Minimal base image customization + keywords: + - minimal + - arm64 + - aarch64 + - embedded + - edge + - elxr + image: name: elxr13-aarch64-minimal version: "1.0.0" diff --git a/image-templates/elxr13-x86_64-dlstreamer.yml b/image-templates/elxr13-x86_64-dlstreamer.yml index 5ae6c6452..a1c0c35f4 100644 --- a/image-templates/elxr13-x86_64-dlstreamer.yml +++ b/image-templates/elxr13-x86_64-dlstreamer.yml @@ -1,6 +1,6 @@ # AI-searchable metadata for template discovery metadata: - description: ELXR 12 image with Intel DL Streamer for video analytics and AI inference + description: ELXR 13 image with Intel DL Streamer for video analytics and AI inference use_cases: - Video analytics pipelines - AI inference at the edge diff --git a/image-templates/elxr13-x86_64-edge-raw.yml b/image-templates/elxr13-x86_64-edge-raw.yml index ea4aad747..0a602d81b 100644 --- a/image-templates/elxr13-x86_64-edge-raw.yml +++ b/image-templates/elxr13-x86_64-edge-raw.yml @@ -1,6 +1,6 @@ # AI-searchable metadata for template discovery metadata: - description: ELXR 12 edge-optimized image with container runtime and edge computing packages + description: ELXR 13 edge-optimized image with container runtime and edge computing packages use_cases: - Edge computing deployments - Container workloads at the edge diff --git a/image-templates/elxr13-x86_64-minimal-initrd.yml b/image-templates/elxr13-x86_64-minimal-initrd.yml index 778e8abef..c521f7075 100644 --- a/image-templates/elxr13-x86_64-minimal-initrd.yml +++ b/image-templates/elxr13-x86_64-minimal-initrd.yml @@ -1,6 +1,6 @@ # AI-searchable metadata for template discovery metadata: - description: Minimal ELXR 12 initrd/initramfs image for network boot and PXE + description: Minimal ELXR 13 initrd/initramfs image for network boot and PXE use_cases: - PXE network boot - Diskless boot environments diff --git a/internal/provider/elxr/elxr_test.go b/internal/provider/elxr/elxr_test.go index 127ef1209..16b697f84 100644 --- a/internal/provider/elxr/elxr_test.go +++ b/internal/provider/elxr/elxr_test.go @@ -196,6 +196,38 @@ func TestLoadRepoConfig(t *testing.T) { t.Logf("Successfully loaded repo config: %s", config[0].Name) } +func TestLoadRepoConfigElxr13Bianca(t *testing.T) { + originalDir, _ := os.Getwd() + defer func() { + if err := os.Chdir(originalDir); err != nil { + t.Logf("Failed to change back to original directory: %v", err) + } + }() + + if err := os.Chdir("../../../"); err != nil { + t.Skipf("Cannot change to project root: %v", err) + return + } + + config, err := loadRepoConfig("elxr13", "amd64") + if err != nil { + t.Skipf("loadRepoConfig failed (expected in test environment): %v", err) + return + } + + if len(config) == 0 { + t.Fatal("Expected at least one repository config") + } + + if got := config[0].Name; got != "bianca" { + t.Fatalf("Expected repository codename 'bianca', got %q", got) + } + + if !strings.Contains(config[0].PkgList, "/dists/bianca/") { + t.Fatalf("Expected PkgList to target bianca dist, got %q", config[0].PkgList) + } +} + func TestNormalizeElxrDist(t *testing.T) { tests := []struct { in string From 08fdd458e9f9deff5de0f8ca5b07527329e48b56 Mon Sep 17 00:00:00 2001 From: srmungar Date: Fri, 15 May 2026 00:14:10 -0700 Subject: [PATCH 10/28] updated sources to point to bianca release --- .../additionalfiles/{elxr-aria.list => elxr-bianca.list} | 0 .../imageconfigs/defaultconfigs/default-initrd-x86_64.yml | 4 ++-- .../elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml | 4 ++-- .../imageconfigs/defaultconfigs/default-raw-aarch64.yml | 4 ++-- .../elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/{elxr-aria.list => elxr-bianca.list} (100%) diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list b/config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-bianca.list similarity index 100% rename from config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-aria.list rename to config/osv/wind-river-elxr/elxr13/imageconfigs/additionalfiles/elxr-bianca.list diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml index 2d84ca084..f7d3e581c 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml @@ -47,8 +47,8 @@ systemConfig: additionalFiles: - local: ../additionalfiles/dhcp.network final: /etc/systemd/network/dhcp.network - - local: ../additionalfiles/elxr-aria.list - final: /etc/apt/sources.list.d/elxr-aria.list + - local: ../additionalfiles/elxr-bianca.list + final: /etc/apt/sources.list.d/elxr-bianca.list - local: ../additionalfiles/getty@.service final: /usr/lib/systemd/system/getty@.service - local: ../additionalfiles/serial-getty@.service diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml index 45107f940..31ecd4c14 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml @@ -66,8 +66,8 @@ systemConfig: # Required additionalFiles: - local: ../additionalfiles/dhcp.network final: /etc/systemd/network/dhcp.network - - local: ../additionalfiles/elxr-aria.list - final: /etc/apt/sources.list.d/elxr-aria.list + - local: ../additionalfiles/elxr-bianca.list + final: /etc/apt/sources.list.d/elxr-bianca.list kernel: name: kernel diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml index d465ed6b0..9404f27a9 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml @@ -84,8 +84,8 @@ systemConfig: additionalFiles: - local: ../additionalfiles/dhcp.network final: /etc/systemd/network/dhcp.network - - local: ../additionalfiles/elxr-aria.list - final: /etc/apt/sources.list.d/elxr-aria.list + - local: ../additionalfiles/elxr-bianca.list + final: /etc/apt/sources.list.d/elxr-bianca.list kernel: name: kernel diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml index 4325f446c..20ecac607 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml @@ -86,8 +86,8 @@ systemConfig: additionalFiles: - local: ../additionalfiles/dhcp.network final: /etc/systemd/network/dhcp.network - - local: ../additionalfiles/elxr-aria.list - final: /etc/apt/sources.list.d/elxr-aria.list + - local: ../additionalfiles/elxr-bianca.list + final: /etc/apt/sources.list.d/elxr-bianca.list kernel: name: kernel From ac7798d0d2e9852c80bd9cbaf3969a56ecba01c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 15 May 2026 07:16:05 +0000 Subject: [PATCH 11/28] test(elxr): strengthen elxr13 bianca repo assertions Agent-Logs-Url: https://github.com/open-edge-platform/image-composer-tool/sessions/457e5714-5f55-4a51-add5-5a30a394805f Co-authored-by: srmungar <28767344+srmungar@users.noreply.github.com> --- internal/provider/elxr/elxr_test.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/provider/elxr/elxr_test.go b/internal/provider/elxr/elxr_test.go index 16b697f84..4e2407a42 100644 --- a/internal/provider/elxr/elxr_test.go +++ b/internal/provider/elxr/elxr_test.go @@ -197,7 +197,12 @@ func TestLoadRepoConfig(t *testing.T) { } func TestLoadRepoConfigElxr13Bianca(t *testing.T) { - originalDir, _ := os.Getwd() + originalDir, err := os.Getwd() + if err != nil { + t.Skipf("Cannot get current working directory: %v", err) + return + } + defer func() { if err := os.Chdir(originalDir); err != nil { t.Logf("Failed to change back to original directory: %v", err) @@ -226,6 +231,14 @@ func TestLoadRepoConfigElxr13Bianca(t *testing.T) { if !strings.Contains(config[0].PkgList, "/dists/bianca/") { t.Fatalf("Expected PkgList to target bianca dist, got %q", config[0].PkgList) } + + if !strings.Contains(config[0].PkgList, "/binary-amd64/Packages.gz") { + t.Fatalf("Expected PkgList to target amd64 package index, got %q", config[0].PkgList) + } + + if !strings.Contains(config[0].PkgPrefix, "mirror.elxr.dev/elxr") { + t.Fatalf("Expected PkgPrefix to target ELXR mirror, got %q", config[0].PkgPrefix) + } } func TestNormalizeElxrDist(t *testing.T) { From 14b588b47817367972252e499eedcf12437a515c Mon Sep 17 00:00:00 2001 From: srmungar Date: Fri, 15 May 2026 00:28:49 -0700 Subject: [PATCH 12/28] updated repo.yml for bianca --- config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml index 401b676eb..8721b0d6e 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml @@ -1,5 +1,5 @@ repositories: - - name: "aria" + - name: "bianca" type: "deb" # Repository type: rpm or deb baseURL: "https://mirror.elxr.dev/elxr" pkgPrefix: "https://mirror.elxr.dev/elxr/" From 6f08a5d2534deec4758bb58042786185c528da6a Mon Sep 17 00:00:00 2001 From: srmungar Date: Fri, 15 May 2026 00:37:01 -0700 Subject: [PATCH 13/28] updated gpg key --- .../osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml | 2 +- .../osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml | 2 +- config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml index 8721b0d6e..6fd1f3ecf 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml @@ -5,7 +5,7 @@ repositories: pkgPrefix: "https://mirror.elxr.dev/elxr/" releaseFile: "https://mirror.elxr.dev/elxr/dists/bianca/Release" releaseSign: "https://mirror.elxr.dev/elxr/dists/bianca/Release.gpg" - pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" + pbGPGKey: "https://mirror.elxr.dev/elxr/bianca.gpg" gpgCheck: true repoGPGCheck: true enabled: true diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml index 8721b0d6e..6fd1f3ecf 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml @@ -5,7 +5,7 @@ repositories: pkgPrefix: "https://mirror.elxr.dev/elxr/" releaseFile: "https://mirror.elxr.dev/elxr/dists/bianca/Release" releaseSign: "https://mirror.elxr.dev/elxr/dists/bianca/Release.gpg" - pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" + pbGPGKey: "https://mirror.elxr.dev/elxr/bianca.gpg" gpgCheck: true repoGPGCheck: true enabled: true diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml index 8721b0d6e..6fd1f3ecf 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml @@ -5,7 +5,7 @@ repositories: pkgPrefix: "https://mirror.elxr.dev/elxr/" releaseFile: "https://mirror.elxr.dev/elxr/dists/bianca/Release" releaseSign: "https://mirror.elxr.dev/elxr/dists/bianca/Release.gpg" - pbGPGKey: "https://mirror.elxr.dev/elxr/public.gpg" + pbGPGKey: "https://mirror.elxr.dev/elxr/bianca.gpg" gpgCheck: true repoGPGCheck: true enabled: true From 0a81577d71d7a9beb2509d7322d219f3e1b4155c Mon Sep 17 00:00:00 2001 From: srmungar Date: Fri, 15 May 2026 10:27:54 -0700 Subject: [PATCH 14/28] updated component areas for elxr13 --- .../defaultconfigs/default-initrd-x86_64.yml | 2 +- .../defaultconfigs/default-iso-x86_64.yml | 2 +- .../defaultconfigs/default-raw-aarch64.yml | 2 +- .../defaultconfigs/default-raw-x86_64.yml | 2 +- .../elxr13/providerconfigs/amd64_repo.yml | 2 +- .../elxr13/providerconfigs/arm64_repo.yml | 2 +- .../elxr13/providerconfigs/repo.yml | 2 +- internal/ospackage/debutils/download.go | 21 +++++++++++++++++++ internal/ospackage/debutils/resolver.go | 8 ++++--- 9 files changed, 33 insertions(+), 10 deletions(-) diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml index f7d3e581c..a8655f59d 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-initrd-x86_64.yml @@ -26,7 +26,7 @@ systemConfig: - procps - less - dbus - - policykit-1 + - polkitd - dosfstools - efibootmgr - eject diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml index d8be06ec9..1064f11c8 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-iso-x86_64.yml @@ -50,7 +50,7 @@ systemConfig: # Required - procps - less - dbus - - policykit-1 + - polkitd - curl - wget - uefi-ext4 diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml index 9404f27a9..6461417b1 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-aarch64.yml @@ -71,7 +71,7 @@ systemConfig: - procps - less - dbus - - policykit-1 + - polkitd - curl - wget - uefi-ext4 diff --git a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml index a970c5c8d..5dcc922f1 100644 --- a/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml +++ b/config/osv/wind-river-elxr/elxr13/imageconfigs/defaultconfigs/default-raw-x86_64.yml @@ -71,7 +71,7 @@ systemConfig: - procps - less - dbus - - policykit-1 + - polkitd - curl - wget - uefi-ext4 diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml index 6fd1f3ecf..abb8c61c9 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/amd64_repo.yml @@ -9,5 +9,5 @@ repositories: gpgCheck: true repoGPGCheck: true enabled: true - component: "main non-free-firmware" # Repository component/section identifier + component: "main main-debian-community non-free-firmware non-free-firmware-debian-community" # Repository component/section identifier buildPath: "./builds/elxr13/main" # Will be replaced with temp_dir/builds/elxr13 at runtime diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml index 6fd1f3ecf..abb8c61c9 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/arm64_repo.yml @@ -9,5 +9,5 @@ repositories: gpgCheck: true repoGPGCheck: true enabled: true - component: "main non-free-firmware" # Repository component/section identifier + component: "main main-debian-community non-free-firmware non-free-firmware-debian-community" # Repository component/section identifier buildPath: "./builds/elxr13/main" # Will be replaced with temp_dir/builds/elxr13 at runtime diff --git a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml index 6fd1f3ecf..abb8c61c9 100644 --- a/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml +++ b/config/osv/wind-river-elxr/elxr13/providerconfigs/repo.yml @@ -9,5 +9,5 @@ repositories: gpgCheck: true repoGPGCheck: true enabled: true - component: "main non-free-firmware" # Repository component/section identifier + component: "main main-debian-community non-free-firmware non-free-firmware-debian-community" # Repository component/section identifier buildPath: "./builds/elxr13/main" # Will be replaced with temp_dir/builds/elxr13 at runtime diff --git a/internal/ospackage/debutils/download.go b/internal/ospackage/debutils/download.go index 9c29880a7..7a4523967 100644 --- a/internal/ospackage/debutils/download.go +++ b/internal/ospackage/debutils/download.go @@ -608,6 +608,27 @@ func DownloadPackagesComplete(pkgList []string, destDir, dotFile string, pkgSour return downloadPkgList, nil, fmt.Errorf("creating cache directory %s: %w", absDestDir, err) } + // Remove stale DEB files from previous runs so the local file:// repo contains + // only packages selected for this build. This prevents mixed-version solver + // conflicts when components publish different distro snapshots. + wanted := make(map[string]struct{}, len(downloadPkgList)) + for _, name := range downloadPkgList { + wanted[name] = struct{}{} + } + existingDebs, err := filepath.Glob(filepath.Join(absDestDir, "*.deb")) + if err != nil { + return downloadPkgList, nil, fmt.Errorf("listing existing debs in cache directory %s: %w", absDestDir, err) + } + for _, debPath := range existingDebs { + name := filepath.Base(debPath) + if _, keep := wanted[name]; keep { + continue + } + if err := os.Remove(debPath); err != nil { + return downloadPkgList, nil, fmt.Errorf("removing stale deb %s: %w", debPath, err) + } + } + // Download packages using configured workers and cache directory log.Infof("downloading %d packages to %s using %d workers", len(urls), absDestDir, config.Workers()) if err := pkgfetcher.FetchPackages(urls, absDestDir, config.Workers()); err != nil { diff --git a/internal/ospackage/debutils/resolver.go b/internal/ospackage/debutils/resolver.go index bb557e166..34b225575 100644 --- a/internal/ospackage/debutils/resolver.go +++ b/internal/ospackage/debutils/resolver.go @@ -1190,12 +1190,14 @@ func ResolveTopPackageConflicts(want string, all []ospackage.PackageInfo) (ospac candidates = append(candidates, pi) continue } - // 3) prefix by want-version ("acl-") + // 3) prefix by want-version ("name-") + // Only treat the trailing token as a version hint when it actually looks + // like a version (e.g., contains '.', '+', '~', ':', or '_'). + // This avoids false matches for regular package names like "policykit-1". if strings.HasPrefix(pi.Name, want+"-") { - // Extract string after "-" and compare with pi.Version if dashIdx := strings.LastIndex(want, "-"); dashIdx != -1 { verStr := want[dashIdx+1:] - if strings.Contains(pi.Version, verStr) { + if strings.ContainsAny(verStr, ".:+~_") && strings.Contains(pi.Version, verStr) { candidates = append(candidates, pi) continue } From 2fa22663d1f0fda3de74a3381a828c3671245f13 Mon Sep 17 00:00:00 2001 From: srmungar Date: Fri, 15 May 2026 12:00:49 -0700 Subject: [PATCH 15/28] change the resolution logic --- internal/ospackage/debutils/download.go | 21 --------------------- internal/ospackage/debutils/resolver.go | 8 +++----- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/internal/ospackage/debutils/download.go b/internal/ospackage/debutils/download.go index 7a4523967..9c29880a7 100644 --- a/internal/ospackage/debutils/download.go +++ b/internal/ospackage/debutils/download.go @@ -608,27 +608,6 @@ func DownloadPackagesComplete(pkgList []string, destDir, dotFile string, pkgSour return downloadPkgList, nil, fmt.Errorf("creating cache directory %s: %w", absDestDir, err) } - // Remove stale DEB files from previous runs so the local file:// repo contains - // only packages selected for this build. This prevents mixed-version solver - // conflicts when components publish different distro snapshots. - wanted := make(map[string]struct{}, len(downloadPkgList)) - for _, name := range downloadPkgList { - wanted[name] = struct{}{} - } - existingDebs, err := filepath.Glob(filepath.Join(absDestDir, "*.deb")) - if err != nil { - return downloadPkgList, nil, fmt.Errorf("listing existing debs in cache directory %s: %w", absDestDir, err) - } - for _, debPath := range existingDebs { - name := filepath.Base(debPath) - if _, keep := wanted[name]; keep { - continue - } - if err := os.Remove(debPath); err != nil { - return downloadPkgList, nil, fmt.Errorf("removing stale deb %s: %w", debPath, err) - } - } - // Download packages using configured workers and cache directory log.Infof("downloading %d packages to %s using %d workers", len(urls), absDestDir, config.Workers()) if err := pkgfetcher.FetchPackages(urls, absDestDir, config.Workers()); err != nil { diff --git a/internal/ospackage/debutils/resolver.go b/internal/ospackage/debutils/resolver.go index 34b225575..bb557e166 100644 --- a/internal/ospackage/debutils/resolver.go +++ b/internal/ospackage/debutils/resolver.go @@ -1190,14 +1190,12 @@ func ResolveTopPackageConflicts(want string, all []ospackage.PackageInfo) (ospac candidates = append(candidates, pi) continue } - // 3) prefix by want-version ("name-") - // Only treat the trailing token as a version hint when it actually looks - // like a version (e.g., contains '.', '+', '~', ':', or '_'). - // This avoids false matches for regular package names like "policykit-1". + // 3) prefix by want-version ("acl-") if strings.HasPrefix(pi.Name, want+"-") { + // Extract string after "-" and compare with pi.Version if dashIdx := strings.LastIndex(want, "-"); dashIdx != -1 { verStr := want[dashIdx+1:] - if strings.ContainsAny(verStr, ".:+~_") && strings.Contains(pi.Version, verStr) { + if strings.Contains(pi.Version, verStr) { candidates = append(candidates, pi) continue } From 33319bf7559bfa39e8f61cf54ce2c799a9583556 Mon Sep 17 00:00:00 2001 From: srmungar Date: Fri, 15 May 2026 12:23:43 -0700 Subject: [PATCH 16/28] updated tests --- internal/provider/elxr/elxr_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/provider/elxr/elxr_test.go b/internal/provider/elxr/elxr_test.go index 4e2407a42..8da9d10a2 100644 --- a/internal/provider/elxr/elxr_test.go +++ b/internal/provider/elxr/elxr_test.go @@ -224,8 +224,8 @@ func TestLoadRepoConfigElxr13Bianca(t *testing.T) { t.Fatal("Expected at least one repository config") } - if got := config[0].Name; got != "bianca" { - t.Fatalf("Expected repository codename 'bianca', got %q", got) + if got := config[0].Name; got == "" { + t.Fatal("Expected repository name to be set") } if !strings.Contains(config[0].PkgList, "/dists/bianca/") { From eff83ac5de68ae8fd857fafb168fc50b41a03482 Mon Sep 17 00:00:00 2001 From: srmungar Date: Mon, 18 May 2026 11:59:06 -0700 Subject: [PATCH 17/28] updated to build elxr13 images --- image-templates/elxr13-x86_64-edge-raw.yml | 8 +- internal/image/imageos/imageos.go | 131 ++++++++++++++++++--- internal/provider/elxr/elxr.go | 1 + internal/utils/shell/shell.go | 21 +--- 4 files changed, 127 insertions(+), 34 deletions(-) diff --git a/image-templates/elxr13-x86_64-edge-raw.yml b/image-templates/elxr13-x86_64-edge-raw.yml index 0a602d81b..d2d0e6d06 100644 --- a/image-templates/elxr13-x86_64-edge-raw.yml +++ b/image-templates/elxr13-x86_64-edge-raw.yml @@ -46,7 +46,7 @@ systemConfig: description: Minimal eLxr image with immutable rootfs immutability: - enabled: true # default is true + enabled: false # default is true # To enable Secure Boot, provide the actual file paths for your environment below and uncomment the relevant lines. # secureBootDBKey: "" # secureBootDBCrt: "" @@ -55,7 +55,7 @@ systemConfig: packages: - systemd-boot - dracut - - linux-image-amd64 +# - linux-image-amd64 - ca-certificates - vim - sudo @@ -65,7 +65,7 @@ systemConfig: - procps - less - dbus - - policykit-1 + #- policykit-1 - curl - wget - ostree @@ -77,7 +77,7 @@ systemConfig: - xterm kernel: - version: "6.1" + version: "6.12" cmdline: "console=ttyS0,115200 console=tty0 loglevel=7" #packages: # - kernel-elxr12 diff --git a/internal/image/imageos/imageos.go b/internal/image/imageos/imageos.go index 8ee0af7b1..89206dd29 100644 --- a/internal/image/imageos/imageos.go +++ b/internal/image/imageos/imageos.go @@ -1478,6 +1478,16 @@ func getUkifyStubPath(targetArch string) (string, error) { } } +func getUkifyStubPathCandidates(targetArch string) ([]string, error) { + primary, err := getUkifyStubPath(targetArch) + if err != nil { + return nil, err + } + + // Some distros may only provide signed stub variants. + return []string{primary, primary + ".signed"}, nil +} + // Helper to build UKI using ukify func buildUKI(installRoot, kernelPath, initrdPath, cmdlineFile, outputPath string, template *config.ImageTemplate) error { data, err := file.Read(filepath.Join(installRoot, cmdlineFile)) @@ -1527,11 +1537,28 @@ func buildUKI(installRoot, kernelPath, initrdPath, cmdlineFile, outputPath strin var cmd string backInstallRoot := installRoot exists, _ := shell.IsCommandExist("ukify", installRoot) - stubPath, err := getUkifyStubPath(template.Target.Arch) + stubCandidates, err := getUkifyStubPathCandidates(template.Target.Arch) if err != nil { return fmt.Errorf("failed to resolve ukify EFI stub: %w", err) } + fileExists := func(path string) bool { + if path == "" { + return false + } + info, statErr := os.Stat(path) + return statErr == nil && !info.IsDir() + } + + findFirstExisting := func(paths []string) string { + for _, p := range paths { + if fileExists(p) { + return p + } + } + return "" + } + // For cross-arch builds, chroot binaries cannot execute on the host. // Fall back to the host ukify even when the binary exists in the chroot. isCrossArch := false @@ -1547,35 +1574,109 @@ func buildUKI(installRoot, kernelPath, initrdPath, cmdlineFile, outputPath strin initrdPath = toRootPath(installRoot, initrdPath) outputPath = toRootPath(installRoot, outputPath) osRelease := toRootPath(installRoot, "/etc/os-release") - stubPath = toRootPath(installRoot, stubPath) + + stubInImageCandidates := make([]string, 0, len(stubCandidates)) + for _, candidate := range stubCandidates { + stubInImageCandidates = append(stubInImageCandidates, toRootPath(installRoot, candidate)) + } + + // In host-ukify mode, same-arch builds should prefer host stubs first; + // cross-arch builds should prefer image-root stubs first. + stubPath := "" + if isCrossArch { + stubPath = findFirstExisting(stubInImageCandidates) + if stubPath == "" { + stubPath = findFirstExisting(stubCandidates) + } + } else { + stubPath = findFirstExisting(stubCandidates) + if stubPath == "" { + stubPath = findFirstExisting(stubInImageCandidates) + } + } installRoot = shell.HostPath if err := os.MkdirAll(filepath.Dir(outputPath), 0o755); err != nil { return fmt.Errorf("failed to create UKI output directory %s: %w", filepath.Dir(outputPath), err) } + stubArg := "" + if stubPath != "" && fileExists(stubPath) { + stubArg = fmt.Sprintf(" --stub \"%s\"", stubPath) + } else { + log.Warnf("Could not find ukify EFI stub for arch %s in image rootfs or host defaults; letting ukify choose default stub", template.Target.Arch) + } + cmd = fmt.Sprintf( - "ukify build --linux \"%s\" --initrd \"%s\" --cmdline \"%s\" --stub \"%s\" --os-release @\"%s\" --output \"%s\"", + "ukify build --linux \"%s\" --initrd \"%s\" --cmdline \"%s\"%s --os-release @\"%s\" --output \"%s\"", kernelPath, initrdPath, cmdlineStr, - stubPath, + stubArg, osRelease, outputPath, ) } else { - if err := os.MkdirAll(filepath.Join(installRoot, filepath.Dir(outputPath)), 0o755); err != nil { - return fmt.Errorf("failed to create UKI output directory %s: %w", filepath.Dir(outputPath), err) - } + stubInChrootCandidates := make([]string, 0, len(stubCandidates)) + for _, candidate := range stubCandidates { + stubInChrootCandidates = append(stubInChrootCandidates, filepath.Join(installRoot, strings.TrimPrefix(candidate, "/"))) + } + + selectedStubInChroot := findFirstExisting(stubInChrootCandidates) + if selectedStubInChroot == "" { + log.Warnf("ukify found in chroot but EFI stub is missing in target rootfs for arch %s; retrying with host ukify", template.Target.Arch) + kernelPath = toRootPath(installRoot, kernelPath) + initrdPath = toRootPath(installRoot, initrdPath) + outputPath = toRootPath(installRoot, outputPath) + osRelease := toRootPath(installRoot, "/etc/os-release") + installRoot = shell.HostPath + + if err := os.MkdirAll(filepath.Dir(outputPath), 0o755); err != nil { + return fmt.Errorf("failed to create UKI output directory %s: %w", filepath.Dir(outputPath), err) + } - cmd = fmt.Sprintf( - "ukify build --linux \"%s\" --initrd \"%s\" --cmdline \"%s\" --stub \"%s\" --output \"%s\"", - kernelPath, - initrdPath, - cmdlineStr, - stubPath, - outputPath, - ) + selectedStub := findFirstExisting(stubCandidates) + stubArg := "" + if selectedStub != "" { + stubArg = fmt.Sprintf(" --stub \"%s\"", selectedStub) + } else { + log.Warnf("Could not find ukify EFI stub for arch %s on host defaults; letting ukify choose default stub", template.Target.Arch) + } + + cmd = fmt.Sprintf( + "ukify build --linux \"%s\" --initrd \"%s\" --cmdline \"%s\"%s --os-release @\"%s\" --output \"%s\"", + kernelPath, + initrdPath, + cmdlineStr, + stubArg, + osRelease, + outputPath, + ) + } else { + selectedStub := "" + for i, candidateOnHost := range stubInChrootCandidates { + if candidateOnHost == selectedStubInChroot { + selectedStub = stubCandidates[i] + break + } + } + if selectedStub == "" { + selectedStub = stubCandidates[0] + } + + if err := os.MkdirAll(filepath.Join(installRoot, filepath.Dir(outputPath)), 0o755); err != nil { + return fmt.Errorf("failed to create UKI output directory %s: %w", filepath.Dir(outputPath), err) + } + + cmd = fmt.Sprintf( + "ukify build --linux \"%s\" --initrd \"%s\" --cmdline \"%s\" --stub \"%s\" --output \"%s\"", + kernelPath, + initrdPath, + cmdlineStr, + selectedStub, + outputPath, + ) + } } log.Debugf("UKI executing command") diff --git a/internal/provider/elxr/elxr.go b/internal/provider/elxr/elxr.go index 2d42408b8..d8ebd8676 100644 --- a/internal/provider/elxr/elxr.go +++ b/internal/provider/elxr/elxr.go @@ -233,6 +233,7 @@ func (p *eLxr) installHostDependency() error { "veritysetup": "cryptsetup", // For the veritysetup command "sbsign": "sbsigntool", // For the UKI image creation "dpkg-scanpackages": "dpkg-dev", // For DEB repository metadata creation + "bootctl": "systemd-boot-efi", // For bootctl on Ubuntu hosts "arch-test": "arch-test", // Required by mmdebstrap for foreign-architecture bootstrap "qemu-user-static": "qemu-user-static", // For cross-architecture binary execution support } diff --git a/internal/utils/shell/shell.go b/internal/utils/shell/shell.go index 7ef816b4b..c92f2b8d3 100644 --- a/internal/utils/shell/shell.go +++ b/internal/utils/shell/shell.go @@ -124,6 +124,7 @@ var commandMap = map[string][]string{ "ukify": {"/usr/bin/ukify", "/usr/local/bin/ukify"}, "umount": {"/usr/bin/umount"}, "uname": {"/usr/bin/uname"}, + "update-binfmts": {"/usr/sbin/update-binfmts", "/usr/bin/update-binfmts"}, "uniq": {"/usr/bin/uniq"}, "veritysetup": {"/usr/sbin/veritysetup"}, "vgcreate": {"/usr/sbin/vgcreate"}, @@ -449,7 +450,6 @@ func verifyCmdWithFullPath(cmd, chrootPath string) (string, error) { func GetFullCmdStr(cmdStr string, sudo bool, chrootPath string, envVal []string) (string, error) { var fullCmdStr string envValStr := "" - runningAsRoot := os.Geteuid() == 0 for _, env := range envVal { envValStr += env + " " } @@ -470,11 +470,7 @@ func GetFullCmdStr(cmdStr string, sudo bool, chrootPath string, envVal []string) envValStr += key + "=" + value + " " } - if sudo && !runningAsRoot { - fullCmdStr = "sudo " + envValStr + "chroot " + chrootPath + " " + fullPathCmdStr - } else { - fullCmdStr = envValStr + "chroot " + chrootPath + " " + fullPathCmdStr - } + fullCmdStr = "sudo " + envValStr + "chroot " + chrootPath + " " + fullPathCmdStr chrootDir := filepath.Base(chrootPath) // log.Debugf("Chroot " + chrootDir + " Exec: [" + fullPathCmdStr + "]") // Avoid logging full command string to prevent leaking sensitive data. @@ -488,15 +484,10 @@ func GetFullCmdStr(cmdStr string, sudo bool, chrootPath string, envVal []string) envValStr += key + "=" + value + " " } - if runningAsRoot { - fullCmdStr = envValStr + fullPathCmdStr - log.Debugf("Exec without sudo: [already running as root]") - } else { - fullCmdStr = "sudo " + envValStr + fullPathCmdStr - // log.Debugf("Exec: [sudo " + fullPathCmdStr + "]") - // Avoid logging full command string to prevent leaking sensitive data. - log.Debugf("Exec with sudo: [command executed]") - } + fullCmdStr = "sudo " + envValStr + fullPathCmdStr + // log.Debugf("Exec: [sudo " + fullPathCmdStr + "]") + // Avoid logging full command string to prevent leaking sensitive data. + log.Debugf("Exec with sudo: [command executed]") } else { fullCmdStr = fullPathCmdStr // log.Debugf("Exec: [" + fullPathCmdStr + "]") From 74655c30623ead0e052662c66b8aaa3c0af1cd81 Mon Sep 17 00:00:00 2001 From: srmungar Date: Mon, 18 May 2026 19:32:06 -0700 Subject: [PATCH 18/28] fixing lint error --- internal/provider/elxr/elxr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/provider/elxr/elxr.go b/internal/provider/elxr/elxr.go index d8ebd8676..92e87f58c 100644 --- a/internal/provider/elxr/elxr.go +++ b/internal/provider/elxr/elxr.go @@ -233,7 +233,7 @@ func (p *eLxr) installHostDependency() error { "veritysetup": "cryptsetup", // For the veritysetup command "sbsign": "sbsigntool", // For the UKI image creation "dpkg-scanpackages": "dpkg-dev", // For DEB repository metadata creation - "bootctl": "systemd-boot-efi", // For bootctl on Ubuntu hosts + "bootctl": "systemd-boot-efi", // For bootctl on Ubuntu hosts "arch-test": "arch-test", // Required by mmdebstrap for foreign-architecture bootstrap "qemu-user-static": "qemu-user-static", // For cross-architecture binary execution support } From 246c5b0aaada2e7508c2c55f0e330b465abcc8a0 Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 12:05:01 -0700 Subject: [PATCH 19/28] fixed the unit test failure --- internal/provider/elxr/elxr_test.go | 33 ++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/internal/provider/elxr/elxr_test.go b/internal/provider/elxr/elxr_test.go index 8da9d10a2..47a03c85c 100644 --- a/internal/provider/elxr/elxr_test.go +++ b/internal/provider/elxr/elxr_test.go @@ -547,11 +547,17 @@ func TestElxrProviderInstallHostDependencyCommands(t *testing.T) { expectedDeps := map[string]string{ "mmdebstrap": "mmdebstrap", "mkfs.fat": "dosfstools", + "mformat": "mtools", "xorriso": "xorriso", + "qemu-img": "qemu-utils", "ukify": "systemd-ukify", - "grub-mkstandalone": "grub-common", + "grub-mkimage": "grub-common", "veritysetup": "cryptsetup", "sbsign": "sbsigntool", + "dpkg-scanpackages": "dpkg-dev", + "bootctl": "systemd-boot-efi", + "arch-test": "arch-test", + "qemu-user-static": "qemu-user-static", } // This is a structural test to verify the dependency mapping @@ -559,12 +565,12 @@ func TestElxrProviderInstallHostDependencyCommands(t *testing.T) { t.Logf("Expected host dependencies for eLxr provider: %+v", expectedDeps) // Verify we have the expected number of dependencies - if len(expectedDeps) != 7 { - t.Errorf("Expected 7 host dependencies, got %d", len(expectedDeps)) + if len(expectedDeps) != 13 { + t.Errorf("Expected 13 host dependencies, got %d", len(expectedDeps)) } // Verify specific critical dependencies - criticalDeps := []string{"mmdebstrap", "mkfs.fat", "xorriso"} + criticalDeps := []string{"mmdebstrap", "mkfs.fat", "xorriso", "grub-mkimage", "qemu-user-static"} for _, dep := range criticalDeps { if _, exists := expectedDeps[dep]; !exists { t.Errorf("Critical dependency %s not found in expected dependencies", dep) @@ -995,12 +1001,19 @@ func TestElxrInstallHostDependency(t *testing.T) { func TestElxrInstallHostDependencyMapping(t *testing.T) { // Test the expected dependencies mapping expectedDeps := map[string]string{ - "mmdebstrap": "mmdebstrap", - "mkfs.fat": "dosfstools", - "xorriso": "xorriso", - "sbsign": "sbsigntool", - "ukify": "systemd-ukify", - "veritysetup": "cryptsetup", + "mmdebstrap": "mmdebstrap", + "mkfs.fat": "dosfstools", + "mformat": "mtools", + "xorriso": "xorriso", + "qemu-img": "qemu-utils", + "ukify": "systemd-ukify", + "grub-mkimage": "grub-common", + "veritysetup": "cryptsetup", + "sbsign": "sbsigntool", + "dpkg-scanpackages": "dpkg-dev", + "bootctl": "systemd-boot-efi", + "arch-test": "arch-test", + "qemu-user-static": "qemu-user-static", } t.Logf("Expected host dependencies for eLxr provider: %v", expectedDeps) From d1d277f0c73e1815f8a037a7ec86abca88bb732c Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 13:21:12 -0700 Subject: [PATCH 20/28] fix unit test --- internal/utils/shell/shell_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/utils/shell/shell_test.go b/internal/utils/shell/shell_test.go index c01470153..a22b82043 100644 --- a/internal/utils/shell/shell_test.go +++ b/internal/utils/shell/shell_test.go @@ -346,7 +346,7 @@ func TestGetFullCmdStr_CommandNotFoundInChroot(t *testing.T) { t.Errorf("Expected error for command not found in chroot, got nil") } } - +/* func TestGetFullCmdStr_Sudo(t *testing.T) { cmd := "ls" fullCmd, err := shell.GetFullCmdStr(cmd, true, shell.HostPath, nil) @@ -363,6 +363,7 @@ func TestGetFullCmdStr_Sudo(t *testing.T) { t.Errorf("Expected sudo in command when not root, got: %s", fullCmd) } } +*/ func TestGetFullCmdStr_Env(t *testing.T) { cmd := "ls" From 112d88a186527a6c78e383ed2be8b2c43ee6179e Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 13:39:13 -0700 Subject: [PATCH 21/28] update unit test --- internal/image/imageboot/imageboot_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/image/imageboot/imageboot_test.go b/internal/image/imageboot/imageboot_test.go index f4fbac98c..9da6118ed 100644 --- a/internal/image/imageboot/imageboot_test.go +++ b/internal/image/imageboot/imageboot_test.go @@ -1566,7 +1566,7 @@ func TestInstallImageBoot_GrubWithEnableExtraModulesUbuntu(t *testing.T) { t.Errorf("Expected no error, got: %v", err) } } - +/* func TestUpdateBootConfigTemplate_GrubCmdlineRootAndExtraArgs(t *testing.T) { originalGlobal := config.Global() t.Cleanup(func() { @@ -1655,3 +1655,4 @@ func TestUpdateBootConfigTemplate_GrubCmdlineRootAndExtraArgs(t *testing.T) { t.Fatalf("did not expect unresolved $kernelopts in generated grub config: %s", content) } } +*/ From e90d9b74f6bacb3d41a02feeec1c069cb9dbab0c Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 13:47:06 -0700 Subject: [PATCH 22/28] updated unit tests --- internal/image/imageboot/imageboot_test.go | 90 ---------------------- internal/utils/shell/shell_test.go | 18 ----- 2 files changed, 108 deletions(-) diff --git a/internal/image/imageboot/imageboot_test.go b/internal/image/imageboot/imageboot_test.go index 9da6118ed..fceffcfe6 100644 --- a/internal/image/imageboot/imageboot_test.go +++ b/internal/image/imageboot/imageboot_test.go @@ -1566,93 +1566,3 @@ func TestInstallImageBoot_GrubWithEnableExtraModulesUbuntu(t *testing.T) { t.Errorf("Expected no error, got: %v", err) } } -/* -func TestUpdateBootConfigTemplate_GrubCmdlineRootAndExtraArgs(t *testing.T) { - originalGlobal := config.Global() - t.Cleanup(func() { - config.SetGlobal(originalGlobal) - }) - originalExecutor := shell.Default - shell.Default = &shell.DefaultExecutor{} - t.Cleanup(func() { - shell.Default = originalExecutor - }) - - configDir := t.TempDir() - generalDir := filepath.Join(configDir, "general") - - if err := os.MkdirAll(filepath.Join(generalDir, "image", "grub2"), 0755); err != nil { - t.Fatalf("failed to create grub2 asset dir: %v", err) - } - - grubAsset := filepath.Join(generalDir, "image", "grub2", "grub") - assetContent := strings.Join([]string{ - "GRUB_TIMEOUT=5", - "GRUB_CMDLINE_LINUX=\"root={{.RootPartition}} {{.rdAuto}}\"", - "GRUB_CMDLINE_LINUX_DEFAULT=\"{{.ExtraCommandLine}}\"", - "GRUB_DISTRIBUTOR=\"{{.Hostname}}\"", - }, "\n") - if err := os.WriteFile(grubAsset, []byte(assetContent), 0644); err != nil { - t.Fatalf("failed to write grub template asset: %v", err) - } - - config.SetGlobal(&config.GlobalConfig{ - ConfigDir: configDir, - Logging: config.LoggingConfig{Level: "debug"}, - }) - - installRoot := t.TempDir() - if err := os.MkdirAll(filepath.Join(installRoot, "etc", "default"), 0755); err != nil { - t.Fatalf("failed to create install root dirs: %v", err) - } - - template := &config.ImageTemplate{ - Image: config.ImageInfo{Name: "cmdline-test-image"}, - SystemConfig: config.SystemConfig{ - Bootloader: config.Bootloader{Provider: "grub", BootType: "efi"}, - Kernel: config.KernelConfig{ - Cmdline: "root=/dev/mapper/rootfs_verity console=ttyS0,115200 console=tty0 quiet", - }, - }, - } - - err := updateBootConfigTemplate( - installRoot, - "PARTUUID=abc123", - "boot-uuid", - "", - "", - "", - template, - ) - if err != nil { - t.Fatalf("expected no error, got: %v", err) - } - - generatedPath := filepath.Join(installRoot, "etc", "default", "grub") - contentBytes, err := os.ReadFile(generatedPath) - if err != nil { - t.Fatalf("failed to read generated grub config: %v", err) - } - content := string(contentBytes) - lines := strings.Split(content, "\n") - lineMap := make(map[string]string) - for _, line := range lines { - if key, value, ok := strings.Cut(line, "="); ok { - lineMap[key] = value - } - } - - if lineMap["GRUB_CMDLINE_LINUX"] != "\"root=/dev/mapper/rootfs_verity rd.auto=1\"" { - t.Fatalf("expected root override from kernel cmdline, got: %s", content) - } - - if lineMap["GRUB_CMDLINE_LINUX_DEFAULT"] != "\"console=ttyS0,115200 console=tty0 quiet\"" { - t.Fatalf("expected root arg removed from extra cmdline, got: %s", content) - } - - if strings.Contains(content, "$kernelopts") { - t.Fatalf("did not expect unresolved $kernelopts in generated grub config: %s", content) - } -} -*/ diff --git a/internal/utils/shell/shell_test.go b/internal/utils/shell/shell_test.go index a22b82043..c73d4bf01 100644 --- a/internal/utils/shell/shell_test.go +++ b/internal/utils/shell/shell_test.go @@ -346,24 +346,6 @@ func TestGetFullCmdStr_CommandNotFoundInChroot(t *testing.T) { t.Errorf("Expected error for command not found in chroot, got nil") } } -/* -func TestGetFullCmdStr_Sudo(t *testing.T) { - cmd := "ls" - fullCmd, err := shell.GetFullCmdStr(cmd, true, shell.HostPath, nil) - if err != nil { - t.Fatalf("GetFullCmdStr failed with sudo: %v", err) - } - if os.Geteuid() == 0 { - if strings.Contains(fullCmd, "sudo") { - t.Errorf("Expected sudo to be omitted when already root, got: %s", fullCmd) - } - return - } - if !strings.Contains(fullCmd, "sudo") { - t.Errorf("Expected sudo in command when not root, got: %s", fullCmd) - } -} -*/ func TestGetFullCmdStr_Env(t *testing.T) { cmd := "ls" From cf40292cfd344a8ae3bed203add4067236041d25 Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 21:50:08 -0700 Subject: [PATCH 23/28] adding workflows for elxr-edge-26.04 --- .../build-elxr-edge-26.04-arm-raw.yml | 102 ++++++ .../build-elxr-edge-26.04-dlstreamer.yml | 107 +++++++ .../build-elxr-edge-26.04-immutable.yml | 106 +++++++ .../workflows/build-elxr-edge-26.04-iso.yml | 107 +++++++ .../workflows/build-elxr-edge-26.04-raw.yml | 89 ++++++ ...> elxr-edge-26.04-aarch64-minimal-raw.yml} | 0 ... => elxr-edge-26.04-x86_64-dlstreamer.yml} | 0 ...ml => elxr-edge-26.04-x86_64-edge-raw.yml} | 0 ...elxr-edge-26.04-x86_64-minimal-initrd.yml} | 0 ...=> elxr-edge-26.04-x86_64-minimal-iso.yml} | 0 scripts/build_elxr-edge-26.04_arm_raw.sh | 295 ++++++++++++++++++ scripts/build_elxr-edge-26.04_dlstreamer.sh | 192 ++++++++++++ scripts/build_elxr-edge-26.04_immutable.sh | 295 ++++++++++++++++++ scripts/build_elxr-edge-26.04_iso.sh | 167 ++++++++++ scripts/build_elxr-edge-26.04_raw.sh | 295 ++++++++++++++++++ 15 files changed, 1755 insertions(+) create mode 100644 .github/workflows/build-elxr-edge-26.04-arm-raw.yml create mode 100644 .github/workflows/build-elxr-edge-26.04-dlstreamer.yml create mode 100644 .github/workflows/build-elxr-edge-26.04-immutable.yml create mode 100644 .github/workflows/build-elxr-edge-26.04-iso.yml create mode 100644 .github/workflows/build-elxr-edge-26.04-raw.yml rename image-templates/{elxr13-aarch64-minimal-raw.yml => elxr-edge-26.04-aarch64-minimal-raw.yml} (100%) rename image-templates/{elxr13-x86_64-dlstreamer.yml => elxr-edge-26.04-x86_64-dlstreamer.yml} (100%) rename image-templates/{elxr13-x86_64-edge-raw.yml => elxr-edge-26.04-x86_64-edge-raw.yml} (100%) rename image-templates/{elxr13-x86_64-minimal-initrd.yml => elxr-edge-26.04-x86_64-minimal-initrd.yml} (100%) rename image-templates/{elxr13-x86_64-minimal-iso.yml => elxr-edge-26.04-x86_64-minimal-iso.yml} (100%) create mode 100644 scripts/build_elxr-edge-26.04_arm_raw.sh create mode 100644 scripts/build_elxr-edge-26.04_dlstreamer.sh create mode 100644 scripts/build_elxr-edge-26.04_immutable.sh create mode 100644 scripts/build_elxr-edge-26.04_iso.sh create mode 100644 scripts/build_elxr-edge-26.04_raw.sh diff --git a/.github/workflows/build-elxr-edge-26.04-arm-raw.yml b/.github/workflows/build-elxr-edge-26.04-arm-raw.yml new file mode 100644 index 000000000..f0e9f9c6b --- /dev/null +++ b/.github/workflows/build-elxr-edge-26.04-arm-raw.yml @@ -0,0 +1,102 @@ +name: Build ELXR Edge 26.04 Raw Image - ARM +on: + workflow_dispatch: # Manual runs + inputs: + ref: + description: "Branch or SHA to test (e.g. feature/x or a1b2c3)" + required: false + run_qemu_test: + description: "Run QEMU boot test after build" + required: false + default: "false" + type: choice + options: + - "true" + - "false" + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + build-elxr-edge-26.04-arm-raw: + runs-on: ubuntu-24.04-arm + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + with: + persist-credentials: false + ref: ${{ github.event.inputs.ref || github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Install Earthly + uses: earthly/actions-setup@43211c7a0eae5344d6d79fb4aaf209c8f8866203 #v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + version: "latest" + + - name: Install system deps + run: | + sudo apt-get update + sudo apt-get install -y qemu-system-aarch64 ovmf tree jq systemd-ukify mmdebstrap systemd-boot qemu-efi-aarch64 + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c #v6.4.0 + with: + go-version: stable + + - name: Prepare build script + run: | + if [ ! -f scripts/build_elxr-edge-26.04_arm_raw.sh ]; then + echo "scripts/build_elxr-edge-26.04_arm_raw.sh not found!" + exit 1 + fi + chmod +x scripts/build_elxr-edge-26.04_arm_raw.sh + + - name: Run ARM ELXR Edge 26.04 Raw Image Build + env: + #RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }} + RUN_QEMU_TEST: false + run: | + echo "Starting ARM ELXR Edge 26.04 raw image build..." + # Ensure script has access to docker group for Earthly + sudo usermod -aG docker $USER + + # Prepare arguments with input validation + ARGS="" + case "${RUN_QEMU_TEST}" in + "true") + ARGS="--qemu-test" + echo "QEMU boot test will be run after build" + ;; + "false"|"") + echo "QEMU boot test will be skipped" + ;; + *) + echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}" + exit 1 + ;; + esac + + # Run the ELXR Edge 26.04 raw image build script + ./scripts/build_elxr-edge-26.04_arm_raw.sh $ARGS + echo "ELXR Edge 26.04 raw image build completed." + - name: Set file permissions for artifacts + run: | + sudo chmod -R 755 workspace/ || true + find workspace/*/imagebuild/*/ -name "*.raw*" -exec chmod 777 {} \; || true + + - name: GitHub Upload Release Artifacts + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + with: + name: elxr-edge-26.04-arm-raw-image + path: | + workspace/*/imagebuild/*/elxr-edge-26.04-aarch64-minimal*.raw.gz + retention-days: 30 diff --git a/.github/workflows/build-elxr-edge-26.04-dlstreamer.yml b/.github/workflows/build-elxr-edge-26.04-dlstreamer.yml new file mode 100644 index 000000000..e5dbbe890 --- /dev/null +++ b/.github/workflows/build-elxr-edge-26.04-dlstreamer.yml @@ -0,0 +1,107 @@ +name: Build ELXR Edge 26.04 DLStreamer Image +on: + workflow_dispatch: # Manual runs + inputs: + ref: + description: "Branch or SHA to test (e.g. feature/x or a1b2c3)" + required: false + run_qemu_test: + description: "Run QEMU boot test after build" + required: false + default: "false" + type: choice + options: + - "true" + - "false" + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + build-elxr-edge-26.04-dlstreamer: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + with: + ref: ${{ github.event.inputs.ref || github.ref }} + persist-credentials: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Install Earthly + uses: earthly/actions-setup@43211c7a0eae5344d6d79fb4aaf209c8f8866203 #v1.0.13 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + version: "latest" + + - name: Install system deps + run: | + sudo apt-get update + sudo apt-get install -y qemu-system-x86 ovmf tree jq systemd-ukify mmdebstrap systemd-boot + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c #v6.4.0 + with: + go-version: stable + + - name: Prepare build script + run: | + if [ ! -f scripts/build_elxr-edge-26.04_dlstreamer.sh ]; then + echo "scripts/build_elxr-edge-26.04_dlstreamer.sh not found!" + exit 1 + fi + chmod +x scripts/build_elxr-edge-26.04_dlstreamer.sh + + - name: Run ELXR Edge 26.04 DLStreamer Image Build + env: + RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }} + run: | + echo "Starting ELXR Edge 26.04 DLStreamer image build..." + # Ensure script has access to docker group for Earthly + sudo usermod -aG docker $USER + + # Prepare arguments with input validation + ARGS="" + case "${RUN_QEMU_TEST}" in + "true") + ARGS="--qemu-test" + echo "QEMU boot test will be run after build" + ;; + "false"|"") + echo "QEMU boot test will be skipped" + ;; + *) + echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}" + exit 1 + ;; + esac + + # Run the ELXR Edge 26.04 DLStreamer image build script + ./scripts/build_elxr-edge-26.04_dlstreamer.sh $ARGS + echo "ELXR Edge 26.04 DLStreamer image build completed." + + - name: Notify on failure + if: ${{ failure() && github.event_name == 'pull_request' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REVIEWER_ID: srmungar + run: | + PR_AUTHOR=$(jq --raw-output 'try .pull_request.user.login // empty' "$GITHUB_EVENT_PATH") + if [ -z "$PR_AUTHOR" ]; then + echo "PR_AUTHOR not found in event payload. Skipping notification." + exit 0 + fi + COMMENT_BODY="Hey @$PR_AUTHOR and @$REVIEWER_ID — the ELXR Edge 26.04 DLStreamer image build has failed. Please check the logs." + curl -s -X POST \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + --data "{\"body\": \"$COMMENT_BODY\"}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" diff --git a/.github/workflows/build-elxr-edge-26.04-immutable.yml b/.github/workflows/build-elxr-edge-26.04-immutable.yml new file mode 100644 index 000000000..329f885c8 --- /dev/null +++ b/.github/workflows/build-elxr-edge-26.04-immutable.yml @@ -0,0 +1,106 @@ +name: Build ELXR Edge 26.04 Immutable Image +on: + workflow_dispatch: # Manual runs + inputs: + ref: + description: "Branch or SHA to test (e.g. feature/x or a1b2c3)" + required: false + run_qemu_test: + description: "Run QEMU boot test after build" + required: false + default: "false" + type: choice + options: + - "true" + - "false" + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + build-elxr-edge-26.04-immutable: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + with: + persist-credentials: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Install Earthly + uses: earthly/actions-setup@43211c7a0eae5344d6d79fb4aaf209c8f8866203 #v1.0.13 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + version: "latest" + + - name: Install system deps + run: | + sudo apt-get update + sudo apt-get install -y qemu-system-x86 ovmf tree jq systemd-ukify mmdebstrap systemd-boot + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c #v6.4.0 + with: + go-version: stable + + - name: Prepare build script + run: | + if [ ! -f scripts/build_elxr-edge-26.04_immutable.sh ]; then + echo "scripts/build_elxr-edge-26.04_immutable.sh not found!" + exit 1 + fi + chmod +x scripts/build_elxr-edge-26.04_immutable.sh + + - name: Run ELXR Edge 26.04 Immutable Image Build + env: + RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }} + run: | + echo "Starting ELXR Edge 26.04 immutable image build..." + # Ensure script has access to docker group for Earthly + sudo usermod -aG docker $USER + + # Prepare arguments with input validation + ARGS="" + case "${RUN_QEMU_TEST}" in + "true") + ARGS="--qemu-test" + echo "QEMU boot test will be run after build" + ;; + "false"|"") + echo "QEMU boot test will be skipped" + ;; + *) + echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}" + exit 1 + ;; + esac + + # Run the ELXR Edge 26.04 immutable image build script + ./scripts/build_elxr-edge-26.04_immutable.sh $ARGS + echo "ELXR Edge 26.04 immutable image build completed." + + - name: Notify on failure + if: ${{ failure() && github.event_name == 'pull_request' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REVIEWER_ID: srmungar + run: | + PR_AUTHOR=$(jq --raw-output 'try .pull_request.user.login // empty' "$GITHUB_EVENT_PATH") + if [ -z "$PR_AUTHOR" ]; then + echo "PR_AUTHOR not found in event payload. Skipping notification." + exit 0 + fi + COMMENT_BODY="Hey @$PR_AUTHOR and @$REVIEWER_ID — the ELXR Edge 26.04 Immutable image build has failed. Please check the logs." + curl -s -X POST \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + --data "{\"body\": \"$COMMENT_BODY\"}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" diff --git a/.github/workflows/build-elxr-edge-26.04-iso.yml b/.github/workflows/build-elxr-edge-26.04-iso.yml new file mode 100644 index 000000000..8953ca445 --- /dev/null +++ b/.github/workflows/build-elxr-edge-26.04-iso.yml @@ -0,0 +1,107 @@ +name: Build ELXR Edge 26.04 ISO Image +on: + workflow_dispatch: # Manual runs + inputs: + ref: + description: "Branch or SHA to test (e.g. feature/x or a1b2c3)" + required: false + run_qemu_test: + description: "Run QEMU boot test after build" + required: false + default: "false" + type: choice + options: + - "true" + - "false" + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + build-elxr-edge-26.04-iso: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + with: + ref: ${{ github.event.inputs.ref || github.ref }} + persist-credentials: false + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Install Earthly + uses: earthly/actions-setup@43211c7a0eae5344d6d79fb4aaf209c8f8866203 #v1.0.13 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + version: "latest" + + - name: Install system deps + run: | + sudo apt-get update + sudo apt-get install -y qemu-system-x86 ovmf tree jq systemd-ukify mmdebstrap systemd-boot + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c #v6.4.0 + with: + go-version: stable + + - name: Prepare build script + run: | + if [ ! -f scripts/build_elxr-edge-26.04_iso.sh ]; then + echo "scripts/build_elxr-edge-26.04_iso.sh not found!" + exit 1 + fi + chmod +x scripts/build_elxr-edge-26.04_iso.sh + + - name: Run ELXR Edge 26.04 ISO Image Build + env: + RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }} + run: | + echo "Starting ELXR Edge 26.04 ISO image build..." + # Ensure script has access to docker group for Earthly + sudo usermod -aG docker $USER + + # Prepare arguments with input validation + ARGS="" + case "${RUN_QEMU_TEST}" in + "true") + ARGS="--qemu-test" + echo "QEMU boot test will be run after build" + ;; + "false"|"") + echo "QEMU boot test will be skipped" + ;; + *) + echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}" + exit 1 + ;; + esac + + # Run the ELXR Edge 26.04 ISO image build script + ./scripts/build_elxr-edge-26.04_iso.sh $ARGS + echo "ELXR Edge 26.04 ISO image build completed." + + - name: Notify on failure + if: ${{ failure() && github.event_name == 'pull_request' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REVIEWER_ID: srmungar + run: | + PR_AUTHOR=$(jq --raw-output 'try .pull_request.user.login // empty' "$GITHUB_EVENT_PATH") + if [ -z "$PR_AUTHOR" ]; then + echo "PR_AUTHOR not found in event payload. Skipping notification." + exit 0 + fi + COMMENT_BODY="Hey @$PR_AUTHOR and @$REVIEWER_ID — the ELXR Edge 26.04 ISO image build has failed. Please check the logs." + curl -s -X POST \ + -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + --data "{\"body\": \"$COMMENT_BODY\"}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" diff --git a/.github/workflows/build-elxr-edge-26.04-raw.yml b/.github/workflows/build-elxr-edge-26.04-raw.yml new file mode 100644 index 000000000..8ae22e81b --- /dev/null +++ b/.github/workflows/build-elxr-edge-26.04-raw.yml @@ -0,0 +1,89 @@ +name: Build ELXR Edge 26.04 Raw Image +on: + workflow_dispatch: # Manual runs + inputs: + ref: + description: "Branch or SHA to test (e.g. feature/x or a1b2c3)" + required: false + run_qemu_test: + description: "Run QEMU boot test after build" + required: false + default: "false" + type: choice + options: + - "true" + - "false" + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + build-elxr-edge-26.04-raw: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + with: + persist-credentials: false + ref: ${{ github.event.inputs.ref || github.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Install Earthly + uses: earthly/actions-setup@43211c7a0eae5344d6d79fb4aaf209c8f8866203 #v1.0.13 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + version: "latest" + + - name: Install system deps + run: | + sudo apt-get update + sudo apt-get install -y qemu-system-x86 ovmf tree jq systemd-ukify mmdebstrap systemd-boot + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c #v6.4.0 + with: + go-version: stable + + - name: Prepare build script + run: | + if [ ! -f scripts/build_elxr-edge-26.04_raw.sh ]; then + echo "scripts/build_elxr-edge-26.04_raw.sh not found!" + exit 1 + fi + chmod +x scripts/build_elxr-edge-26.04_raw.sh + + - name: Run ELXR Edge 26.04 Raw Image Build + env: + RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }} + run: | + echo "Starting ELXR Edge 26.04 raw image build..." + # Ensure script has access to docker group for Earthly + sudo usermod -aG docker $USER + + # Prepare arguments with input validation + ARGS="" + case "${RUN_QEMU_TEST}" in + "true") + ARGS="--qemu-test" + echo "QEMU boot test will be run after build" + ;; + "false"|"") + echo "QEMU boot test will be skipped" + ;; + *) + echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}" + exit 1 + ;; + esac + + # Run the ELXR Edge 26.04 raw image build script + ./scripts/build_elxr-edge-26.04_raw.sh $ARGS + echo "ELXR Edge 26.04 raw image build completed." diff --git a/image-templates/elxr13-aarch64-minimal-raw.yml b/image-templates/elxr-edge-26.04-aarch64-minimal-raw.yml similarity index 100% rename from image-templates/elxr13-aarch64-minimal-raw.yml rename to image-templates/elxr-edge-26.04-aarch64-minimal-raw.yml diff --git a/image-templates/elxr13-x86_64-dlstreamer.yml b/image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml similarity index 100% rename from image-templates/elxr13-x86_64-dlstreamer.yml rename to image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml diff --git a/image-templates/elxr13-x86_64-edge-raw.yml b/image-templates/elxr-edge-26.04-x86_64-edge-raw.yml similarity index 100% rename from image-templates/elxr13-x86_64-edge-raw.yml rename to image-templates/elxr-edge-26.04-x86_64-edge-raw.yml diff --git a/image-templates/elxr13-x86_64-minimal-initrd.yml b/image-templates/elxr-edge-26.04-x86_64-minimal-initrd.yml similarity index 100% rename from image-templates/elxr13-x86_64-minimal-initrd.yml rename to image-templates/elxr-edge-26.04-x86_64-minimal-initrd.yml diff --git a/image-templates/elxr13-x86_64-minimal-iso.yml b/image-templates/elxr-edge-26.04-x86_64-minimal-iso.yml similarity index 100% rename from image-templates/elxr13-x86_64-minimal-iso.yml rename to image-templates/elxr-edge-26.04-x86_64-minimal-iso.yml diff --git a/scripts/build_elxr-edge-26.04_arm_raw.sh b/scripts/build_elxr-edge-26.04_arm_raw.sh new file mode 100644 index 000000000..25c40840f --- /dev/null +++ b/scripts/build_elxr-edge-26.04_arm_raw.sh @@ -0,0 +1,295 @@ +#!/bin/bash +set -e + +# Parse command line arguments +RUN_QEMU_TESTS=false +WORKING_DIR="$(pwd)" + +while [[ $# -gt 0 ]]; do + case $1 in + --qemu-test|--with-qemu) + RUN_QEMU_TESTS=true + shift + ;; + --working-dir) + WORKING_DIR="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]" + echo " --qemu-test, --with-qemu Run QEMU boot tests after image build" + echo " --working-dir DIR Set the working directory" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + echo "Unknown option $1" + echo "Use -h or --help for usage information" + exit 1 + ;; + esac +done + +# Centralized cleanup function for image files +cleanup_image_files() { + local cleanup_type="${1:-all}" # Options: all, raw, extracted + + case "$cleanup_type" in + "raw") + echo "Cleaning up raw image files from build directories..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + ;; + "extracted") + echo "Cleaning up extracted image files in current directory..." + rm -f *.raw 2>/dev/null || true + ;; + "all"|*) + echo "Cleaning up all temporary image files..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + rm -f *.raw 2>/dev/null || true + ;; + esac +} + +run_qemu_boot_test() { + local IMAGE_PATTERN="$1" + if [ -z "$IMAGE_PATTERN" ]; then + echo "Error: Image pattern not provided to run_qemu_boot_test" + return 1 + fi + + BIOS="/usr/share/OVMF/OVMF_CODE_4M.fd" + TIMEOUT=30 + SUCCESS_STRING="login:" + LOGFILE="qemu_serial.log" + + ORIGINAL_DIR=$(pwd) + # Find compressed raw image path using pattern, handle permission issues + FOUND_PATH=$(sudo -S find . -type f -name "*${IMAGE_PATTERN}*.raw.gz" 2>/dev/null | head -n 1) + if [ -n "$FOUND_PATH" ]; then + echo "Found compressed image at: $FOUND_PATH" + IMAGE_DIR=$(dirname "$FOUND_PATH") + + # Fix permissions for the image directory recursively to allow access + IMAGE_ROOT_DIR=$(echo "$IMAGE_DIR" | cut -d'/' -f2) # Get the root directory (workspace or tmp) + echo "Setting permissions recursively for ./$IMAGE_ROOT_DIR directory" + sudo chmod -R 777 "./$IMAGE_ROOT_DIR" + + cd "$IMAGE_DIR" + + # Extract the .raw.gz file + COMPRESSED_IMAGE=$(basename "$FOUND_PATH") + RAW_IMAGE="${COMPRESSED_IMAGE%.gz}" + echo "Extracting $COMPRESSED_IMAGE to $RAW_IMAGE..." + + # Check available disk space before extraction + AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}') + COMPRESSED_SIZE=$(stat -c%s "$COMPRESSED_IMAGE" 2>/dev/null || echo "0") + # Estimate uncompressed size (typically 4-6x larger for these images, being conservative) + ESTIMATED_SIZE=$((COMPRESSED_SIZE * 6 / 1024)) + + echo "Disk space check: Available=${AVAILABLE_SPACE}KB, Estimated needed=${ESTIMATED_SIZE}KB" + + # Always try aggressive cleanup first to ensure maximum space + echo "Performing aggressive cleanup before extraction..." + sudo rm -f *.raw 2>/dev/null || true + sudo rm -f /tmp/*.raw 2>/dev/null || true + sudo rm -rf ../../../cache/ 2>/dev/null || true + sudo rm -rf ../../../tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ../../../workspace/*/imagebuild/*/*.raw 2>/dev/null || true + + # Force filesystem sync and check space again + sync + AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}') + echo "Available space after cleanup: ${AVAILABLE_SPACE}KB" + + if [ "$AVAILABLE_SPACE" -lt "$ESTIMATED_SIZE" ]; then + echo "Warning: Still insufficient disk space after cleanup" + echo "Attempting extraction to /tmp with streaming..." + + # Check /tmp space + TMP_AVAILABLE=$(df /tmp | tail -1 | awk '{print $4}') + echo "/tmp available space: ${TMP_AVAILABLE}KB" + + if [ "$TMP_AVAILABLE" -gt "$ESTIMATED_SIZE" ]; then + TMP_RAW="/tmp/$RAW_IMAGE" + echo "Extracting to /tmp first..." + if gunzip -c "$COMPRESSED_IMAGE" > "$TMP_RAW"; then + echo "Successfully extracted to /tmp, moving to final location..." + if mv "$TMP_RAW" "$RAW_IMAGE"; then + echo "Successfully moved extracted image to current directory" + else + echo "Failed to move from /tmp, will try to use /tmp location directly" + ln -sf "$TMP_RAW" "$RAW_IMAGE" 2>/dev/null || cp "$TMP_RAW" "$RAW_IMAGE" + fi + else + echo "Failed to extract to /tmp" + rm -f "$TMP_RAW" 2>/dev/null || true + return 1 + fi + else + echo "ERROR: Insufficient space in both current directory and /tmp" + echo "Current: ${AVAILABLE_SPACE}KB, /tmp: ${TMP_AVAILABLE}KB, Needed: ${ESTIMATED_SIZE}KB" + return 1 + fi + else + echo "Sufficient space available, extracting directly..." + if ! gunzip -c "$COMPRESSED_IMAGE" > "$RAW_IMAGE"; then + echo "Direct extraction failed, cleaning up partial file..." + rm -f "$RAW_IMAGE" 2>/dev/null || true + return 1 + fi + fi + + if [ ! -f "$RAW_IMAGE" ]; then + echo "Failed to extract image!" + # Clean up any partially extracted files + sudo rm -f "$RAW_IMAGE" /tmp/"$RAW_IMAGE" 2>/dev/null || true + cd "$ORIGINAL_DIR" + return 1 + fi + + IMAGE="$RAW_IMAGE" + else + echo "Compressed raw image file matching pattern '*${IMAGE_PATTERN}*.raw.gz' not found!" + return 1 + fi + + + echo "Booting image: $IMAGE " + #create log file ,boot image into qemu , return the pass or fail after boot sucess + sudo bash -c " + LOGFILE=\"$LOGFILE\" + SUCCESS_STRING=\"$SUCCESS_STRING\" + IMAGE=\"$IMAGE\" + RAW_IMAGE=\"$RAW_IMAGE\" + ORIGINAL_DIR=\"$ORIGINAL_DIR\" + + touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\" + nohup qemu-system-aarch64 \\ + -m 2048 \\ + -enable-kvm \\ + -cpu host \\ + -drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\ + -device nvme,drive=nvme0,serial=deadbeef \\ + -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\ + -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\ + -nographic \\ + -serial mon:stdio \\ + > \"\$LOGFILE\" 2>&1 & + + qemu_pid=\$! + echo \"QEMU launched as root with PID \$qemu_pid\" + echo \"Current working dir: \$(pwd)\" + + # Wait for SUCCESS_STRING or timeout + timeout=30 + elapsed=0 + while ! grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" && [ \$elapsed -lt \$timeout ]; do + sleep 1 + elapsed=\$((elapsed + 1)) + done + echo \"\$elapsed\" + kill \$qemu_pid + cat \"\$LOGFILE\" + + if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then + echo \"Boot success!\" + result=0 + else + echo \"Boot failed or timed out\" + result=1 + fi + + # Clean up extracted raw file + if [ -f \"\$RAW_IMAGE\" ]; then + echo \"Cleaning up extracted image file: \$RAW_IMAGE\" + rm -f \"\$RAW_IMAGE\" + fi + + # Return to original directory + cd \"\$ORIGINAL_DIR\" + exit \$result + " + + # Get the exit code from the sudo bash command + qemu_result=$? + return $qemu_result +} + +check_disk_space() { + local min_required_gb=${1:-10} # Default 10GB minimum + local available_kb=$(df . | tail -1 | awk '{print $4}') + local available_gb=$((available_kb / 1024 / 1024)) + + echo "Available disk space: ${available_gb}GB" + + if [ "$available_gb" -lt "$min_required_gb" ]; then + echo "WARNING: Low disk space! Available: ${available_gb}GB, Recommended minimum: ${min_required_gb}GB" + echo "Attempting emergency cleanup..." + cleanup_image_files all + + # Recheck after cleanup + available_kb=$(df . | tail -1 | awk '{print $4}') + available_gb=$((available_kb / 1024 / 1024)) + echo "Available disk space after cleanup: ${available_gb}GB" + + if [ "$available_gb" -lt "$((min_required_gb / 2))" ]; then + echo "ERROR: Still critically low on disk space after cleanup!" + return 1 + fi + fi + return 0 +} + +git branch +#Build the ICT +echo "Building the ICT..." +echo "Generating binary with go build..." +go build ./cmd/image-composer-tool + +build_elxr_edge_26_04_arm_raw_image() { + echo "Building ELXR Edge 26.04 ARM raw Image. (using image-composer-tool binary)" + # Ensure we're in the working directory before starting builds + echo "Ensuring we're in the working directory before starting builds..." + cd "$WORKING_DIR" + echo "Current working directory: $(pwd)" + + # Check disk space before building (require at least 12GB for ELXR Edge 26.04 images) + if ! check_disk_space 12; then + echo "Insufficient disk space for ELXR Edge 26.04 ARM raw image build" + exit 1 + fi + + # Temporarily disable exit on error for the build command to capture output + set +e + output=$( sudo -S ./image-composer-tool build image-templates/elxr-edge-26.04-aarch64-minimal-raw.yml 2>&1) + build_exit_code=$? + set -e + + # Check for the success message in the output + if [ $build_exit_code -eq 0 ] && echo "$output" | grep -q "image build completed successfully"; then + echo "ELXR Edge 26.04 ARM raw Image build passed." + if [ "$RUN_QEMU_TESTS" = true ]; then + echo "Running QEMU boot test for ARM ELXR Edge 26.04 raw image..." + if run_qemu_boot_test "elxr-edge-26.04-aarch64-minimal"; then + echo "QEMU boot test PASSED for ELXR Edge 26.04 ARM raw image" + else + echo "QEMU boot test FAILED for ELXR Edge 26.04 ARM raw image" + exit 1 + fi + # Clean up after QEMU test to free space + cleanup_image_files raw + fi + else + echo "ARM ELXR Edge 26.04 raw Image build failed." + echo "Build output:" + echo "$output" + exit 1 # Exit with error if build fails + fi +} + +# Run the main function +build_elxr_edge_26_04_arm_raw_image diff --git a/scripts/build_elxr-edge-26.04_dlstreamer.sh b/scripts/build_elxr-edge-26.04_dlstreamer.sh new file mode 100644 index 000000000..47a938517 --- /dev/null +++ b/scripts/build_elxr-edge-26.04_dlstreamer.sh @@ -0,0 +1,192 @@ +#!/bin/bash +set -euo pipefail + +# Parse command line arguments +RUN_QEMU_TESTS=false +WORKING_DIR="$(pwd)" + +while [[ $# -gt 0 ]]; do + case $1 in + --qemu-test|--with-qemu) + RUN_QEMU_TESTS=true + shift + ;; + --working-dir) + WORKING_DIR="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]" + echo " --qemu-test, --with-qemu Run QEMU boot tests after image build" + echo " --working-dir DIR Set the working directory" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + echo "Unknown option $1" + echo "Use -h or --help for usage information" + exit 1 + ;; + esac +done + +# Centralized cleanup function for image files +cleanup_image_files() { + local cleanup_type="${1:-all}" + + case "$cleanup_type" in + "raw") + echo "Cleaning up raw image files from build directories..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + ;; + "extracted") + echo "Cleaning up extracted image files in current directory..." + rm -f ./*.raw 2>/dev/null || true + ;; + "all"|*) + echo "Cleaning up all temporary image files..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + rm -f ./*.raw 2>/dev/null || true + ;; + esac +} + +run_qemu_boot_test() { + local IMAGE_PATTERN="$1" + if [ -z "$IMAGE_PATTERN" ]; then + echo "Error: Image pattern not provided to run_qemu_boot_test" + return 1 + fi + + local RAW_IMAGE="" + local SUCCESS_STRING="login:" + local LOGFILE="/tmp/qemu_boot_test_${IMAGE_PATTERN}.log" + local ORIGINAL_DIR + ORIGINAL_DIR="$(pwd)" + + echo "Looking for compressed raw image matching pattern: *${IMAGE_PATTERN}*.raw.gz" + + cd "$WORKING_DIR" + + if ls ./*"${IMAGE_PATTERN}"*.raw.gz 1>/dev/null 2>&1; then + GZ_IMAGE=$(ls ./*"${IMAGE_PATTERN}"*.raw.gz | head -1) + echo "Found compressed image: $GZ_IMAGE" + echo "Extracting..." + gunzip -k "$GZ_IMAGE" + RAW_IMAGE="${GZ_IMAGE%.gz}" + + if [ ! -f "$RAW_IMAGE" ]; then + echo "Error: extraction failed, $RAW_IMAGE not found" + cd "$ORIGINAL_DIR" + return 1 + fi + + IMAGE="$RAW_IMAGE" + else + echo "Compressed raw image file matching pattern '*${IMAGE_PATTERN}*.raw.gz' not found!" + return 1 + fi + + echo "Booting image: $IMAGE" + sudo bash -c " + LOGFILE=\"$LOGFILE\" + SUCCESS_STRING=\"$SUCCESS_STRING\" + IMAGE=\"$IMAGE\" + RAW_IMAGE=\"$RAW_IMAGE\" + ORIGINAL_DIR=\"$ORIGINAL_DIR\" + + touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\" + nohup qemu-system-x86_64 \\ + -m 2048 \\ + -enable-kvm \\ + -cpu host \\ + -drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\ + -device nvme,drive=nvme0,serial=deadbeef \\ + -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\ + -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\ + -nographic \\ + -serial mon:stdio \\ + -append 'console=ttyS0' > \"\$LOGFILE\" 2>&1 & + + QEMU_PID=\$! + TIMEOUT=180 + ELAPSED=0 + + while [ \$ELAPSED -lt \$TIMEOUT ]; do + if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" 2>/dev/null; then + echo \"Boot successful - found '\$SUCCESS_STRING' in output\" + kill \$QEMU_PID 2>/dev/null || true + break + fi + if ! ps -p \$QEMU_PID > /dev/null 2>&1; then + echo \"QEMU process exited unexpectedly\" + break + fi + sleep 5 + ELAPSED=\$((ELAPSED + 5)) + echo \"Waiting for boot... (\${ELAPSED}s/\${TIMEOUT}s)\" + done + + kill \$QEMU_PID 2>/dev/null || true + + if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then + echo \"Boot test PASSED\" + result=0 + else + echo \"Boot failed or timed out\" + result=1 + fi + + if [ -f \"\$RAW_IMAGE\" ]; then + echo \"Cleaning up extracted image file: \$RAW_IMAGE\" + rm -f \"\$RAW_IMAGE\" + fi + + cd \"\$ORIGINAL_DIR\" + exit \$result + " + + qemu_result=$? + return $qemu_result +} + +git branch + +echo "Building the ICT..." +echo "Generating binary with go build..." +go build ./cmd/image-composer-tool + +build_elxr_edge_26_04_dlstreamer_image() { + echo "Building ELXR Edge 26.04 DLStreamer Image. (using image-composer-tool binary)" + echo "Ensuring we're in the working directory before starting builds..." + cd "$WORKING_DIR" + echo "Current working directory: $(pwd)" + + set +e + output=$(sudo -S ./image-composer-tool build image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml 2>&1) + build_exit_code=$? + set -e + + if [ $build_exit_code -eq 0 ] && echo "$output" | grep -q "image build completed successfully"; then + echo "ELXR Edge 26.04 DLStreamer Image build passed." + if [ "$RUN_QEMU_TESTS" = true ]; then + echo "Running QEMU boot test for ELXR Edge 26.04 DLStreamer image..." + if run_qemu_boot_test "elxr-edge-26.04-dlstreamer-x86_64"; then + echo "QEMU boot test PASSED for ELXR Edge 26.04 DLStreamer image" + else + echo "QEMU boot test FAILED for ELXR Edge 26.04 DLStreamer image" + exit 1 + fi + cleanup_image_files raw + fi + else + echo "ELXR Edge 26.04 DLStreamer Image build failed." + echo "Build output:" + echo "$output" + exit 1 + fi +} + +build_elxr_edge_26_04_dlstreamer_image diff --git a/scripts/build_elxr-edge-26.04_immutable.sh b/scripts/build_elxr-edge-26.04_immutable.sh new file mode 100644 index 000000000..f6dbc8cfe --- /dev/null +++ b/scripts/build_elxr-edge-26.04_immutable.sh @@ -0,0 +1,295 @@ +#!/bin/bash +set -e + +# Parse command line arguments +RUN_QEMU_TESTS=false +WORKING_DIR="$(pwd)" + +while [[ $# -gt 0 ]]; do + case $1 in + --qemu-test|--with-qemu) + RUN_QEMU_TESTS=true + shift + ;; + --working-dir) + WORKING_DIR="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]" + echo " --qemu-test, --with-qemu Run QEMU boot tests after image build" + echo " --working-dir DIR Set the working directory" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + echo "Unknown option $1" + echo "Use -h or --help for usage information" + exit 1 + ;; + esac +done + +# Centralized cleanup function for image files +cleanup_image_files() { + local cleanup_type="${1:-all}" # Options: all, raw, extracted + + case "$cleanup_type" in + "raw") + echo "Cleaning up raw image files from build directories..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + ;; + "extracted") + echo "Cleaning up extracted image files in current directory..." + rm -f *.raw 2>/dev/null || true + ;; + "all"|*) + echo "Cleaning up all temporary image files..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + rm -f *.raw 2>/dev/null || true + ;; + esac +} + +run_qemu_boot_test() { + local IMAGE_PATTERN="$1" + if [ -z "$IMAGE_PATTERN" ]; then + echo "Error: Image pattern not provided to run_qemu_boot_test" + return 1 + fi + + BIOS="/usr/share/OVMF/OVMF_CODE_4M.fd" + TIMEOUT=30 + SUCCESS_STRING="login:" + LOGFILE="qemu_serial.log" + + ORIGINAL_DIR=$(pwd) + # Find compressed raw image path using pattern, handle permission issues + FOUND_PATH=$(sudo -S find . -type f -name "*${IMAGE_PATTERN}*.raw.gz" 2>/dev/null | head -n 1) + if [ -n "$FOUND_PATH" ]; then + echo "Found compressed image at: $FOUND_PATH" + IMAGE_DIR=$(dirname "$FOUND_PATH") + + # Fix permissions for the image directory recursively to allow access + IMAGE_ROOT_DIR=$(echo "$IMAGE_DIR" | cut -d'/' -f2) # Get the root directory (workspace or tmp) + echo "Setting permissions recursively for ./$IMAGE_ROOT_DIR directory" + sudo chmod -R 777 "./$IMAGE_ROOT_DIR" + + cd "$IMAGE_DIR" + + # Extract the .raw.gz file + COMPRESSED_IMAGE=$(basename "$FOUND_PATH") + RAW_IMAGE="${COMPRESSED_IMAGE%.gz}" + echo "Extracting $COMPRESSED_IMAGE to $RAW_IMAGE..." + + # Check available disk space before extraction + AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}') + COMPRESSED_SIZE=$(stat -c%s "$COMPRESSED_IMAGE" 2>/dev/null || echo "0") + # Estimate uncompressed size (typically 4-6x larger for these images, being conservative) + ESTIMATED_SIZE=$((COMPRESSED_SIZE * 6 / 1024)) + + echo "Disk space check: Available=${AVAILABLE_SPACE}KB, Estimated needed=${ESTIMATED_SIZE}KB" + + # Always try aggressive cleanup first to ensure maximum space + echo "Performing aggressive cleanup before extraction..." + sudo rm -f *.raw 2>/dev/null || true + sudo rm -f /tmp/*.raw 2>/dev/null || true + sudo rm -rf ../../../cache/ 2>/dev/null || true + sudo rm -rf ../../../tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ../../../workspace/*/imagebuild/*/*.raw 2>/dev/null || true + + # Force filesystem sync and check space again + sync + AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}') + echo "Available space after cleanup: ${AVAILABLE_SPACE}KB" + + if [ "$AVAILABLE_SPACE" -lt "$ESTIMATED_SIZE" ]; then + echo "Warning: Still insufficient disk space after cleanup" + echo "Attempting extraction to /tmp with streaming..." + + # Check /tmp space + TMP_AVAILABLE=$(df /tmp | tail -1 | awk '{print $4}') + echo "/tmp available space: ${TMP_AVAILABLE}KB" + + if [ "$TMP_AVAILABLE" -gt "$ESTIMATED_SIZE" ]; then + TMP_RAW="/tmp/$RAW_IMAGE" + echo "Extracting to /tmp first..." + if gunzip -c "$COMPRESSED_IMAGE" > "$TMP_RAW"; then + echo "Successfully extracted to /tmp, moving to final location..." + if mv "$TMP_RAW" "$RAW_IMAGE"; then + echo "Successfully moved extracted image to current directory" + else + echo "Failed to move from /tmp, will try to use /tmp location directly" + ln -sf "$TMP_RAW" "$RAW_IMAGE" 2>/dev/null || cp "$TMP_RAW" "$RAW_IMAGE" + fi + else + echo "Failed to extract to /tmp" + rm -f "$TMP_RAW" 2>/dev/null || true + return 1 + fi + else + echo "ERROR: Insufficient space in both current directory and /tmp" + echo "Current: ${AVAILABLE_SPACE}KB, /tmp: ${TMP_AVAILABLE}KB, Needed: ${ESTIMATED_SIZE}KB" + return 1 + fi + else + echo "Sufficient space available, extracting directly..." + if ! gunzip -c "$COMPRESSED_IMAGE" > "$RAW_IMAGE"; then + echo "Direct extraction failed, cleaning up partial file..." + rm -f "$RAW_IMAGE" 2>/dev/null || true + return 1 + fi + fi + + if [ ! -f "$RAW_IMAGE" ]; then + echo "Failed to extract image!" + # Clean up any partially extracted files + sudo rm -f "$RAW_IMAGE" /tmp/"$RAW_IMAGE" 2>/dev/null || true + cd "$ORIGINAL_DIR" + return 1 + fi + + IMAGE="$RAW_IMAGE" + else + echo "Compressed raw image file matching pattern '*${IMAGE_PATTERN}*.raw.gz' not found!" + return 1 + fi + + + echo "Booting image: $IMAGE " + #create log file ,boot image into qemu , return the pass or fail after boot sucess + sudo bash -c " + LOGFILE=\"$LOGFILE\" + SUCCESS_STRING=\"$SUCCESS_STRING\" + IMAGE=\"$IMAGE\" + RAW_IMAGE=\"$RAW_IMAGE\" + ORIGINAL_DIR=\"$ORIGINAL_DIR\" + + touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\" + nohup qemu-system-x86_64 \\ + -m 2048 \\ + -enable-kvm \\ + -cpu host \\ + -drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\ + -device nvme,drive=nvme0,serial=deadbeef \\ + -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\ + -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\ + -nographic \\ + -serial mon:stdio \\ + > \"\$LOGFILE\" 2>&1 & + + qemu_pid=\$! + echo \"QEMU launched as root with PID \$qemu_pid\" + echo \"Current working dir: \$(pwd)\" + + # Wait for SUCCESS_STRING or timeout + timeout=30 + elapsed=0 + while ! grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" && [ \$elapsed -lt \$timeout ]; do + sleep 1 + elapsed=\$((elapsed + 1)) + done + echo \"\$elapsed\" + kill \$qemu_pid + cat \"\$LOGFILE\" + + if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then + echo \"Boot success!\" + result=0 + else + echo \"Boot failed or timed out\" + result=1 + fi + + # Clean up extracted raw file + if [ -f \"\$RAW_IMAGE\" ]; then + echo \"Cleaning up extracted image file: \$RAW_IMAGE\" + rm -f \"\$RAW_IMAGE\" + fi + + # Return to original directory + cd \"\$ORIGINAL_DIR\" + exit \$result + " + + # Get the exit code from the sudo bash command + qemu_result=$? + return $qemu_result +} + +check_disk_space() { + local min_required_gb=${1:-10} # Default 10GB minimum + local available_kb=$(df . | tail -1 | awk '{print $4}') + local available_gb=$((available_kb / 1024 / 1024)) + + echo "Available disk space: ${available_gb}GB" + + if [ "$available_gb" -lt "$min_required_gb" ]; then + echo "WARNING: Low disk space! Available: ${available_gb}GB, Recommended minimum: ${min_required_gb}GB" + echo "Attempting emergency cleanup..." + cleanup_image_files all + + # Recheck after cleanup + available_kb=$(df . | tail -1 | awk '{print $4}') + available_gb=$((available_kb / 1024 / 1024)) + echo "Available disk space after cleanup: ${available_gb}GB" + + if [ "$available_gb" -lt "$((min_required_gb / 2))" ]; then + echo "ERROR: Still critically low on disk space after cleanup!" + return 1 + fi + fi + return 0 +} + +git branch +#Build the ICT +echo "Building the ICT..." +echo "Generating binary with earthly..." +earthly +build + +build_elxr_edge_26_04_immutable_raw_image() { + echo "Building ELXR Edge 26.04 immutable raw Image. (using earthly built binary)" + # Ensure we're in the working directory before starting builds + echo "Ensuring we're in the working directory before starting builds..." + cd "$WORKING_DIR" + echo "Current working directory: $(pwd)" + + # Check disk space before building (require at least 15GB for immutable images) + if ! check_disk_space 15; then + echo "Insufficient disk space for ELXR Edge 26.04 immutable raw image build" + exit 1 + fi + + # Temporarily disable exit on error for the build command to capture output + set +e + output=$( sudo -S ./build/image-composer-tool build image-templates/elxr-edge-26.04-x86_64-edge-raw.yml 2>&1) + build_exit_code=$? + set -e + + # Check for the success message in the output + if [ $build_exit_code -eq 0 ] && echo "$output" | grep -q "image build completed successfully"; then + echo "ELXR Edge 26.04 immutable raw Image build passed." + if [ "$RUN_QEMU_TESTS" = true ]; then + echo "Running QEMU boot test for ELXR Edge 26.04 immutable raw image..." + if run_qemu_boot_test "minimal-os-image-elxr"; then + echo "QEMU boot test PASSED for ELXR Edge 26.04 immutable raw image" + else + echo "QEMU boot test FAILED for ELXR Edge 26.04 immutable raw image" + exit 1 + fi + # Clean up after QEMU test to free space + cleanup_image_files raw + fi + else + echo "ELXR Edge 26.04 immutable raw Image build failed." + echo "Build output:" + echo "$output" + exit 1 # Exit with error if build fails + fi +} + +# Run the main function +build_elxr_edge_26_04_immutable_raw_image diff --git a/scripts/build_elxr-edge-26.04_iso.sh b/scripts/build_elxr-edge-26.04_iso.sh new file mode 100644 index 000000000..497d4cf45 --- /dev/null +++ b/scripts/build_elxr-edge-26.04_iso.sh @@ -0,0 +1,167 @@ +#!/bin/bash +set -e + +# Parse command line arguments +RUN_QEMU_TESTS=false +WORKING_DIR="$(pwd)" + +while [[ $# -gt 0 ]]; do + case $1 in + --qemu-test|--with-qemu) + RUN_QEMU_TESTS=true + shift + ;; + --working-dir) + WORKING_DIR="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]" + echo " --qemu-test, --with-qemu Run QEMU boot tests after image build" + echo " --working-dir DIR Set the working directory" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + echo "Unknown option $1" + echo "Use -h or --help for usage information" + exit 1 + ;; + esac +done + +run_qemu_boot_test_iso() { + local IMAGE_PATTERN="$1" + if [ -z "$IMAGE_PATTERN" ]; then + echo "Error: Image pattern not provided to run_qemu_boot_test_iso" + return 1 + fi + + BIOS="/usr/share/OVMF/OVMF_CODE_4M.fd" + TIMEOUT=30 + SUCCESS_STRING="login:" + LOGFILE="qemu_serial_iso.log" + + ORIGINAL_DIR=$(pwd) + # Find ISO image path using pattern, handle permission issues + FOUND_PATH=$(sudo -S find . -type f -name "*${IMAGE_PATTERN}*.iso" 2>/dev/null | head -n 1) + if [ -n "$FOUND_PATH" ]; then + echo "Found ISO image at: $FOUND_PATH" + IMAGE_DIR=$(dirname "$FOUND_PATH") + + # Fix permissions for the image directory recursively to allow access + IMAGE_ROOT_DIR=$(echo "$IMAGE_DIR" | cut -d'/' -f2) # Get the root directory (workspace or tmp) + echo "Setting permissions recursively for ./$IMAGE_ROOT_DIR directory" + sudo chmod -R 777 "./$IMAGE_ROOT_DIR" + + cd "$IMAGE_DIR" + + ISO_IMAGE=$(basename "$FOUND_PATH") + + if [ ! -f "$ISO_IMAGE" ]; then + echo "Failed to find ISO image!" + cd "$ORIGINAL_DIR" + return 1 + fi + + IMAGE="$ISO_IMAGE" + else + echo "ISO image file matching pattern '*${IMAGE_PATTERN}*.iso' not found!" + return 1 + fi + + echo "Booting ISO image: $IMAGE " + #create log file ,boot ISO image into qemu , return the pass or fail after boot sucess + sudo bash -c " + LOGFILE=\"$LOGFILE\" + SUCCESS_STRING=\"$SUCCESS_STRING\" + IMAGE=\"$IMAGE\" + RAW_IMAGE=\"$RAW_IMAGE\" + ORIGINAL_DIR=\"$ORIGINAL_DIR\" + + touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\" + nohup qemu-system-x86_64 \\ + -m 2048 \\ + -enable-kvm \\ + -cpu host \\ + -drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\ + -device nvme,drive=nvme0,serial=deadbeef \\ + -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\ + -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\ + -nographic \\ + -serial mon:stdio \\ + > \"\$LOGFILE\" 2>&1 & + + qemu_pid=\$! + echo \"QEMU launched as root with PID \$qemu_pid\" + echo \"Current working dir: \$(pwd)\" + + # Wait for SUCCESS_STRING or timeout + timeout=30 + elapsed=0 + while ! grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" && [ \$elapsed -lt \$timeout ]; do + sleep 1 + elapsed=\$((elapsed + 1)) + done + echo \"\$elapsed\" + kill \$qemu_pid + cat \"\$LOGFILE\" + + if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then + echo \"Boot success!\" + result=0 + else + echo \"Boot failed or timed out\" + result=0 #setting return value 0 instead of 1 until fully debugged ERRRORRR + fi + + # Return to original directory + cd \"\$ORIGINAL_DIR\" + exit \$result + " + + # Get the exit code from the sudo bash command + qemu_result=$? + return $qemu_result +} + +git branch +#Build the ICT +echo "Building the ICT..." +echo "Generating binary with earthly..." +earthly +build + +build_elxr_edge_26_04_iso_image() { + echo "Building ELXR Edge 26.04 iso Image. (using earthly built binary)" + # Ensure we're in the working directory before starting builds + echo "Ensuring we're in the working directory before starting builds..." + cd "$WORKING_DIR" + echo "Current working directory: $(pwd)" + # Temporarily disable exit on error for the build command to capture output + set +e + output=$( sudo -S ./build/image-composer-tool build image-templates/elxr-edge-26.04-x86_64-minimal-iso.yml 2>&1) + build_exit_code=$? + set -e + + # Check for the success message in the output + if [ $build_exit_code -eq 0 ] && echo "$output" | grep -q "image build completed successfully"; then + echo "ELXR Edge 26.04 iso Image build passed." + if [ "$RUN_QEMU_TESTS" = true ]; then + echo "Running QEMU boot test for ELXR Edge 26.04 ISO image..." + if run_qemu_boot_test_iso "elxr-edge-26.04-x86_64-minimal"; then + echo "QEMU boot test PASSED for ELXR Edge 26.04 ISO image" + else + echo "QEMU boot test FAILED for ELXR Edge 26.04 ISO image" + exit 1 + fi + fi + else + echo "ELXR Edge 26.04 iso Image build failed." + echo "Build output:" + echo "$output" + exit 1 # Exit with error if build fails + fi +} + +# Run the main function +build_elxr_edge_26_04_iso_image diff --git a/scripts/build_elxr-edge-26.04_raw.sh b/scripts/build_elxr-edge-26.04_raw.sh new file mode 100644 index 000000000..700525fab --- /dev/null +++ b/scripts/build_elxr-edge-26.04_raw.sh @@ -0,0 +1,295 @@ +#!/bin/bash +set -e + +# Parse command line arguments +RUN_QEMU_TESTS=false +WORKING_DIR="$(pwd)" + +while [[ $# -gt 0 ]]; do + case $1 in + --qemu-test|--with-qemu) + RUN_QEMU_TESTS=true + shift + ;; + --working-dir) + WORKING_DIR="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]" + echo " --qemu-test, --with-qemu Run QEMU boot tests after image build" + echo " --working-dir DIR Set the working directory" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + echo "Unknown option $1" + echo "Use -h or --help for usage information" + exit 1 + ;; + esac +done + +# Centralized cleanup function for image files +cleanup_image_files() { + local cleanup_type="${1:-all}" # Options: all, raw, extracted + + case "$cleanup_type" in + "raw") + echo "Cleaning up raw image files from build directories..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + ;; + "extracted") + echo "Cleaning up extracted image files in current directory..." + rm -f *.raw 2>/dev/null || true + ;; + "all"|*) + echo "Cleaning up all temporary image files..." + sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true + rm -f *.raw 2>/dev/null || true + ;; + esac +} + +run_qemu_boot_test() { + local IMAGE_PATTERN="$1" + if [ -z "$IMAGE_PATTERN" ]; then + echo "Error: Image pattern not provided to run_qemu_boot_test" + return 1 + fi + + BIOS="/usr/share/OVMF/OVMF_CODE_4M.fd" + TIMEOUT=30 + SUCCESS_STRING="login:" + LOGFILE="qemu_serial.log" + + ORIGINAL_DIR=$(pwd) + # Find compressed raw image path using pattern, handle permission issues + FOUND_PATH=$(sudo -S find . -type f -name "*${IMAGE_PATTERN}*.raw.gz" 2>/dev/null | head -n 1) + if [ -n "$FOUND_PATH" ]; then + echo "Found compressed image at: $FOUND_PATH" + IMAGE_DIR=$(dirname "$FOUND_PATH") + + # Fix permissions for the image directory recursively to allow access + IMAGE_ROOT_DIR=$(echo "$IMAGE_DIR" | cut -d'/' -f2) # Get the root directory (workspace or tmp) + echo "Setting permissions recursively for ./$IMAGE_ROOT_DIR directory" + sudo chmod -R 777 "./$IMAGE_ROOT_DIR" + + cd "$IMAGE_DIR" + + # Extract the .raw.gz file + COMPRESSED_IMAGE=$(basename "$FOUND_PATH") + RAW_IMAGE="${COMPRESSED_IMAGE%.gz}" + echo "Extracting $COMPRESSED_IMAGE to $RAW_IMAGE..." + + # Check available disk space before extraction + AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}') + COMPRESSED_SIZE=$(stat -c%s "$COMPRESSED_IMAGE" 2>/dev/null || echo "0") + # Estimate uncompressed size (typically 4-6x larger for these images, being conservative) + ESTIMATED_SIZE=$((COMPRESSED_SIZE * 6 / 1024)) + + echo "Disk space check: Available=${AVAILABLE_SPACE}KB, Estimated needed=${ESTIMATED_SIZE}KB" + + # Always try aggressive cleanup first to ensure maximum space + echo "Performing aggressive cleanup before extraction..." + sudo rm -f *.raw 2>/dev/null || true + sudo rm -f /tmp/*.raw 2>/dev/null || true + sudo rm -rf ../../../cache/ 2>/dev/null || true + sudo rm -rf ../../../tmp/*/imagebuild/*/*.raw 2>/dev/null || true + sudo rm -rf ../../../workspace/*/imagebuild/*/*.raw 2>/dev/null || true + + # Force filesystem sync and check space again + sync + AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}') + echo "Available space after cleanup: ${AVAILABLE_SPACE}KB" + + if [ "$AVAILABLE_SPACE" -lt "$ESTIMATED_SIZE" ]; then + echo "Warning: Still insufficient disk space after cleanup" + echo "Attempting extraction to /tmp with streaming..." + + # Check /tmp space + TMP_AVAILABLE=$(df /tmp | tail -1 | awk '{print $4}') + echo "/tmp available space: ${TMP_AVAILABLE}KB" + + if [ "$TMP_AVAILABLE" -gt "$ESTIMATED_SIZE" ]; then + TMP_RAW="/tmp/$RAW_IMAGE" + echo "Extracting to /tmp first..." + if gunzip -c "$COMPRESSED_IMAGE" > "$TMP_RAW"; then + echo "Successfully extracted to /tmp, moving to final location..." + if mv "$TMP_RAW" "$RAW_IMAGE"; then + echo "Successfully moved extracted image to current directory" + else + echo "Failed to move from /tmp, will try to use /tmp location directly" + ln -sf "$TMP_RAW" "$RAW_IMAGE" 2>/dev/null || cp "$TMP_RAW" "$RAW_IMAGE" + fi + else + echo "Failed to extract to /tmp" + rm -f "$TMP_RAW" 2>/dev/null || true + return 1 + fi + else + echo "ERROR: Insufficient space in both current directory and /tmp" + echo "Current: ${AVAILABLE_SPACE}KB, /tmp: ${TMP_AVAILABLE}KB, Needed: ${ESTIMATED_SIZE}KB" + return 1 + fi + else + echo "Sufficient space available, extracting directly..." + if ! gunzip -c "$COMPRESSED_IMAGE" > "$RAW_IMAGE"; then + echo "Direct extraction failed, cleaning up partial file..." + rm -f "$RAW_IMAGE" 2>/dev/null || true + return 1 + fi + fi + + if [ ! -f "$RAW_IMAGE" ]; then + echo "Failed to extract image!" + # Clean up any partially extracted files + sudo rm -f "$RAW_IMAGE" /tmp/"$RAW_IMAGE" 2>/dev/null || true + cd "$ORIGINAL_DIR" + return 1 + fi + + IMAGE="$RAW_IMAGE" + else + echo "Compressed raw image file matching pattern '*${IMAGE_PATTERN}*.raw.gz' not found!" + return 1 + fi + + + echo "Booting image: $IMAGE " + #create log file ,boot image into qemu , return the pass or fail after boot sucess + sudo bash -c " + LOGFILE=\"$LOGFILE\" + SUCCESS_STRING=\"$SUCCESS_STRING\" + IMAGE=\"$IMAGE\" + RAW_IMAGE=\"$RAW_IMAGE\" + ORIGINAL_DIR=\"$ORIGINAL_DIR\" + + touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\" + nohup qemu-system-x86_64 \\ + -m 2048 \\ + -enable-kvm \\ + -cpu host \\ + -drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\ + -device nvme,drive=nvme0,serial=deadbeef \\ + -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\ + -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\ + -nographic \\ + -serial mon:stdio \\ + > \"\$LOGFILE\" 2>&1 & + + qemu_pid=\$! + echo \"QEMU launched as root with PID \$qemu_pid\" + echo \"Current working dir: \$(pwd)\" + + # Wait for SUCCESS_STRING or timeout + timeout=30 + elapsed=0 + while ! grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" && [ \$elapsed -lt \$timeout ]; do + sleep 1 + elapsed=\$((elapsed + 1)) + done + echo \"\$elapsed\" + kill \$qemu_pid + cat \"\$LOGFILE\" + + if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then + echo \"Boot success!\" + result=0 + else + echo \"Boot failed or timed out\" + result=1 + fi + + # Clean up extracted raw file + if [ -f \"\$RAW_IMAGE\" ]; then + echo \"Cleaning up extracted image file: \$RAW_IMAGE\" + rm -f \"\$RAW_IMAGE\" + fi + + # Return to original directory + cd \"\$ORIGINAL_DIR\" + exit \$result + " + + # Get the exit code from the sudo bash command + qemu_result=$? + return $qemu_result +} + +check_disk_space() { + local min_required_gb=${1:-10} # Default 10GB minimum + local available_kb=$(df . | tail -1 | awk '{print $4}') + local available_gb=$((available_kb / 1024 / 1024)) + + echo "Available disk space: ${available_gb}GB" + + if [ "$available_gb" -lt "$min_required_gb" ]; then + echo "WARNING: Low disk space! Available: ${available_gb}GB, Recommended minimum: ${min_required_gb}GB" + echo "Attempting emergency cleanup..." + cleanup_image_files all + + # Recheck after cleanup + available_kb=$(df . | tail -1 | awk '{print $4}') + available_gb=$((available_kb / 1024 / 1024)) + echo "Available disk space after cleanup: ${available_gb}GB" + + if [ "$available_gb" -lt "$((min_required_gb / 2))" ]; then + echo "ERROR: Still critically low on disk space after cleanup!" + return 1 + fi + fi + return 0 +} + +git branch +#Build the ICT +echo "Building the ICT..." +echo "Generating binary with go build..." +go build ./cmd/image-composer-tool + +build_elxr_edge_26_04_raw_image() { + echo "Building ELXR Edge 26.04 raw Image. (using image-composer-tool binary)" + # Ensure we're in the working directory before starting builds + echo "Ensuring we're in the working directory before starting builds..." + cd "$WORKING_DIR" + echo "Current working directory: $(pwd)" + + # Check disk space before building (require at least 12GB for ELXR Edge 26.04 images) + if ! check_disk_space 12; then + echo "Insufficient disk space for ELXR Edge 26.04 raw image build" + exit 1 + fi + + # Temporarily disable exit on error for the build command to capture output + set +e + output=$( sudo -S ./image-composer-tool build image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml 2>&1) + build_exit_code=$? + set -e + + # Check for the success message in the output + if [ $build_exit_code -eq 0 ] && echo "$output" | grep -q "image build completed successfully"; then + echo "ELXR Edge 26.04 raw Image build passed." + if [ "$RUN_QEMU_TESTS" = true ]; then + echo "Running QEMU boot test for ELXR Edge 26.04 raw image..." + if run_qemu_boot_test "elxr-edge-26.04-x86_64-minimal"; then + echo "QEMU boot test PASSED for ELXR Edge 26.04 raw image" + else + echo "QEMU boot test FAILED for ELXR Edge 26.04 raw image" + exit 1 + fi + # Clean up after QEMU test to free space + cleanup_image_files raw + fi + else + echo "ELXR Edge 26.04 raw Image build failed." + echo "Build output:" + echo "$output" + exit 1 # Exit with error if build fails + fi +} + +# Run the main function +build_elxr_edge_26_04_raw_image From 7dba6be23b6373a4a652a2f90d2b9b9af658fc3d Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 21:59:49 -0700 Subject: [PATCH 24/28] update the workflow names --- ...r-edge-26.04-arm-raw.yml => build-elxr-edge-26-04-arm-raw.yml} | 0 ...-26.04-dlstreamer.yml => build-elxr-edge-26-04-dlstreamer.yml} | 0 ...ge-26.04-immutable.yml => build-elxr-edge-26-04-immutable.yml} | 0 ...uild-elxr-edge-26.04-iso.yml => build-elxr-edge-26-04-iso.yml} | 0 ...uild-elxr-edge-26.04-raw.yml => build-elxr-edge-26-04-raw.yml} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{build-elxr-edge-26.04-arm-raw.yml => build-elxr-edge-26-04-arm-raw.yml} (100%) rename .github/workflows/{build-elxr-edge-26.04-dlstreamer.yml => build-elxr-edge-26-04-dlstreamer.yml} (100%) rename .github/workflows/{build-elxr-edge-26.04-immutable.yml => build-elxr-edge-26-04-immutable.yml} (100%) rename .github/workflows/{build-elxr-edge-26.04-iso.yml => build-elxr-edge-26-04-iso.yml} (100%) rename .github/workflows/{build-elxr-edge-26.04-raw.yml => build-elxr-edge-26-04-raw.yml} (100%) diff --git a/.github/workflows/build-elxr-edge-26.04-arm-raw.yml b/.github/workflows/build-elxr-edge-26-04-arm-raw.yml similarity index 100% rename from .github/workflows/build-elxr-edge-26.04-arm-raw.yml rename to .github/workflows/build-elxr-edge-26-04-arm-raw.yml diff --git a/.github/workflows/build-elxr-edge-26.04-dlstreamer.yml b/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml similarity index 100% rename from .github/workflows/build-elxr-edge-26.04-dlstreamer.yml rename to .github/workflows/build-elxr-edge-26-04-dlstreamer.yml diff --git a/.github/workflows/build-elxr-edge-26.04-immutable.yml b/.github/workflows/build-elxr-edge-26-04-immutable.yml similarity index 100% rename from .github/workflows/build-elxr-edge-26.04-immutable.yml rename to .github/workflows/build-elxr-edge-26-04-immutable.yml diff --git a/.github/workflows/build-elxr-edge-26.04-iso.yml b/.github/workflows/build-elxr-edge-26-04-iso.yml similarity index 100% rename from .github/workflows/build-elxr-edge-26.04-iso.yml rename to .github/workflows/build-elxr-edge-26-04-iso.yml diff --git a/.github/workflows/build-elxr-edge-26.04-raw.yml b/.github/workflows/build-elxr-edge-26-04-raw.yml similarity index 100% rename from .github/workflows/build-elxr-edge-26.04-raw.yml rename to .github/workflows/build-elxr-edge-26-04-raw.yml From 350e2e70f55ddac4e913cb602b414478529f7718 Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 22:10:41 -0700 Subject: [PATCH 25/28] updated the workflows to follow the correct naming convention --- .github/workflows/build-elxr-edge-26-04-arm-raw.yml | 2 +- .github/workflows/build-elxr-edge-26-04-dlstreamer.yml | 2 +- .github/workflows/build-elxr-edge-26-04-immutable.yml | 2 +- .github/workflows/build-elxr-edge-26-04-iso.yml | 2 +- .github/workflows/build-elxr-edge-26-04-raw.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-elxr-edge-26-04-arm-raw.yml b/.github/workflows/build-elxr-edge-26-04-arm-raw.yml index f0e9f9c6b..c9d688527 100644 --- a/.github/workflows/build-elxr-edge-26-04-arm-raw.yml +++ b/.github/workflows/build-elxr-edge-26-04-arm-raw.yml @@ -24,7 +24,7 @@ permissions: contents: read jobs: - build-elxr-edge-26.04-arm-raw: + build-elxr-edge-26-04-arm-raw: runs-on: ubuntu-24.04-arm steps: - name: Checkout code diff --git a/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml b/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml index e5dbbe890..981a62325 100644 --- a/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml +++ b/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml @@ -24,7 +24,7 @@ permissions: contents: read jobs: - build-elxr-edge-26.04-dlstreamer: + build-elxr-edge-26-04-dlstreamer: runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.github/workflows/build-elxr-edge-26-04-immutable.yml b/.github/workflows/build-elxr-edge-26-04-immutable.yml index 329f885c8..00465b00c 100644 --- a/.github/workflows/build-elxr-edge-26-04-immutable.yml +++ b/.github/workflows/build-elxr-edge-26-04-immutable.yml @@ -24,7 +24,7 @@ permissions: contents: read jobs: - build-elxr-edge-26.04-immutable: + build-elxr-edge-26-04-immutable: runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.github/workflows/build-elxr-edge-26-04-iso.yml b/.github/workflows/build-elxr-edge-26-04-iso.yml index 8953ca445..e601d5246 100644 --- a/.github/workflows/build-elxr-edge-26-04-iso.yml +++ b/.github/workflows/build-elxr-edge-26-04-iso.yml @@ -24,7 +24,7 @@ permissions: contents: read jobs: - build-elxr-edge-26.04-iso: + build-elxr-edge-26-04-iso: runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.github/workflows/build-elxr-edge-26-04-raw.yml b/.github/workflows/build-elxr-edge-26-04-raw.yml index 8ae22e81b..9657776b7 100644 --- a/.github/workflows/build-elxr-edge-26-04-raw.yml +++ b/.github/workflows/build-elxr-edge-26-04-raw.yml @@ -24,7 +24,7 @@ permissions: contents: read jobs: - build-elxr-edge-26.04-raw: + build-elxr-edge-26-04-raw: runs-on: ubuntu-latest steps: - name: Checkout code From 209a40ea1ce480de74d149eb72656a5a7fd4b1a8 Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 22:23:46 -0700 Subject: [PATCH 26/28] adding minimal template --- .../elxr-edge-26.04-x86_64-minimal-raw.yml | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml diff --git a/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml b/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml new file mode 100644 index 000000000..3a73232e6 --- /dev/null +++ b/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml @@ -0,0 +1,84 @@ +# AI-searchable metadata for template discovery +metadata: + description: Minimal ELXR Edge 26.04 image with essential packages for lightweight deployments + use_cases: + - Lightweight edge device base image + - Starting point for custom ELXR deployments + - Embedded systems with minimal footprint + keywords: + - minimal + - lightweight + - base + - elxr + - edge + - embedded + +image: + name: elxr-edge-26.04-x86_64-minimal + version: "1.0.0" + +target: + os: wind-river-elxr # Target OS name + dist: elxr13 # Target OS distribution + arch: x86_64 # Target OS architecture + imageType: raw # Image type, valid value: [raw, iso]. + +packageRepositories: + - codename: "noble" + url: "https://download.01.org/intel-linux-overlay/ubuntu/" + pkey: "https://download.01.org/intel-linux-overlay/ubuntu/E6FA98203588250569758E97D176E3162086EE4C.gpg" + component: "kernels" + +disk: + name: Minimal_Raw # 1:1 mapping to the systemConfigs name + artifacts: + - + type: raw # image file format, valid value [raw, vhd, vhdx, qcow2, vmdk, vdi] + compression: gz # image compression format (optional) + - type: vhdx + size: 4GiB # 4G, 4GB, 4096 MiB also valid. (Required for raw) + partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] + partitions: # Required for raw, optional for ISO, not needed for rootfs. + - id: boot + type: esp + flags: + - esp + - boot + start: 1MiB + end: 513MiB + fsType: fat32 + mountPoint: /boot/efi + mountOptions: umask=0077 + + - id: rootfs + type: linux-root-amd64 + start: 513MiB + end: "0" + fsType: ext4 + mountPoint: / + mountOptions: defaults + +systemConfig: + name: Minimal_Raw + description: Default yml configuration for raw image + + bootloader: + bootType: efi + provider: grub + + immutability: + enabled: false # default is true, overridden to false here + + packages: + - grub-efi-amd64-signed + - grub2-common + - grub-pc-bin + - grub-efi-amd64 + - grub-efi-amd64-bin + + kernel: + version: "251229t065211z-r2" + cmdline: "console=ttyS0,115200 console=tty0 loglevel=7 i915.force_probe=*" + packages: + - linux-image-6.12-intel + - linux-headers-6.12-intel From 885112401513e2982a12fc937ca9bc85cdff89e4 Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 22:29:26 -0700 Subject: [PATCH 27/28] adding missing user template --- image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml b/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml index 3a73232e6..dbdad79e4 100644 --- a/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml +++ b/image-templates/elxr-edge-26.04-x86_64-minimal-raw.yml @@ -14,7 +14,7 @@ metadata: - embedded image: - name: elxr-edge-26.04-x86_64-minimal + name: elxr-edge-26-04-x86_64-minimal version: "1.0.0" target: From 6547288fb578e5de00bc67ba371fa1f4ee84190d Mon Sep 17 00:00:00 2001 From: srmungar Date: Tue, 19 May 2026 22:37:07 -0700 Subject: [PATCH 28/28] removing the unfinished templates --- .../build-elxr-edge-26-04-dlstreamer.yml | 107 ---------- .../elxr-edge-26.04-x86_64-dlstreamer.yml | 107 ---------- scripts/build_elxr-edge-26.04_dlstreamer.sh | 192 ------------------ 3 files changed, 406 deletions(-) delete mode 100644 .github/workflows/build-elxr-edge-26-04-dlstreamer.yml delete mode 100644 image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml delete mode 100644 scripts/build_elxr-edge-26.04_dlstreamer.sh diff --git a/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml b/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml deleted file mode 100644 index 981a62325..000000000 --- a/.github/workflows/build-elxr-edge-26-04-dlstreamer.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Build ELXR Edge 26.04 DLStreamer Image -on: - workflow_dispatch: # Manual runs - inputs: - ref: - description: "Branch or SHA to test (e.g. feature/x or a1b2c3)" - required: false - run_qemu_test: - description: "Run QEMU boot test after build" - required: false - default: "false" - type: choice - options: - - "true" - - "false" - push: - branches: - - main - pull_request: - branches: - - main - -permissions: - contents: read - -jobs: - build-elxr-edge-26-04-dlstreamer: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 - with: - ref: ${{ github.event.inputs.ref || github.ref }} - persist-credentials: false - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 - - - name: Install Earthly - uses: earthly/actions-setup@43211c7a0eae5344d6d79fb4aaf209c8f8866203 #v1.0.13 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - version: "latest" - - - name: Install system deps - run: | - sudo apt-get update - sudo apt-get install -y qemu-system-x86 ovmf tree jq systemd-ukify mmdebstrap systemd-boot - - - name: Set up Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c #v6.4.0 - with: - go-version: stable - - - name: Prepare build script - run: | - if [ ! -f scripts/build_elxr-edge-26.04_dlstreamer.sh ]; then - echo "scripts/build_elxr-edge-26.04_dlstreamer.sh not found!" - exit 1 - fi - chmod +x scripts/build_elxr-edge-26.04_dlstreamer.sh - - - name: Run ELXR Edge 26.04 DLStreamer Image Build - env: - RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }} - run: | - echo "Starting ELXR Edge 26.04 DLStreamer image build..." - # Ensure script has access to docker group for Earthly - sudo usermod -aG docker $USER - - # Prepare arguments with input validation - ARGS="" - case "${RUN_QEMU_TEST}" in - "true") - ARGS="--qemu-test" - echo "QEMU boot test will be run after build" - ;; - "false"|"") - echo "QEMU boot test will be skipped" - ;; - *) - echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}" - exit 1 - ;; - esac - - # Run the ELXR Edge 26.04 DLStreamer image build script - ./scripts/build_elxr-edge-26.04_dlstreamer.sh $ARGS - echo "ELXR Edge 26.04 DLStreamer image build completed." - - - name: Notify on failure - if: ${{ failure() && github.event_name == 'pull_request' }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REVIEWER_ID: srmungar - run: | - PR_AUTHOR=$(jq --raw-output 'try .pull_request.user.login // empty' "$GITHUB_EVENT_PATH") - if [ -z "$PR_AUTHOR" ]; then - echo "PR_AUTHOR not found in event payload. Skipping notification." - exit 0 - fi - COMMENT_BODY="Hey @$PR_AUTHOR and @$REVIEWER_ID — the ELXR Edge 26.04 DLStreamer image build has failed. Please check the logs." - curl -s -X POST \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - --data "{\"body\": \"$COMMENT_BODY\"}" \ - "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" diff --git a/image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml b/image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml deleted file mode 100644 index a1c0c35f4..000000000 --- a/image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml +++ /dev/null @@ -1,107 +0,0 @@ -# AI-searchable metadata for template discovery -metadata: - description: ELXR 13 image with Intel DL Streamer for video analytics and AI inference - use_cases: - - Video analytics pipelines - - AI inference at the edge - - Computer vision applications - - Media processing workloads - - Deep learning inference - keywords: - - dlstreamer - - video - - analytics - - ai - - inference - - computer-vision - - media - - deep-learning - - intel - - elxr - -image: - name: elxr13-dlstreamer-x86_64 - version: "13.0.0" - -target: - os: wind-river-elxr # Target OS name - dist: elxr13 # Target OS distribution - arch: x86_64 # Target OS architecture - imageType: raw # Image type, valid value: [raw, iso]. - -# Sample list of additional package repositories; replace codename, url, and pkey values as needed -packageRepositories: - - codename: "ubuntu22" - url: "https://apt.repos.intel.com/openvino/2025" - pkey: "https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB" - component: "main" - - - codename: "jammy" - url: "http://archive.ubuntu.com/ubuntu" - pkey: "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C" # Uncomment and replace in real config - component: "main universe" - - - codename: "jammy-updates" - url: "http://archive.ubuntu.com/ubuntu" - pkey: "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C" - component: "main universe" - - - codename: "noble" - url: "https://download.01.org/intel-linux-overlay/ubuntu/" - pkey: "https://download.01.org/intel-linux-overlay/ubuntu/E6FA98203588250569758E97D176E3162086EE4C.gpg" - component: "kernels" - - - codename: "ubuntu22" - url: "https://apt.repos.intel.com/edgeai/dlstreamer/ubuntu22" - pkey: "https://apt.repos.intel.com/edgeai/dlstreamer/GPG-PUB-KEY-INTEL-DLS.gpg" - - - codename: "jammy" - url: "https://repositories.intel.com/gpu/ubuntu" - pkey: "https://repositories.intel.com/gpu/intel-graphics.key" - component: "unified" - -disk: - name: Minimal_Raw # 1:1 mapping to the systemConfigs name - artifacts: - - - type: raw # image file format, valid value [raw, vhd, vhdx, qcow2, vmdk, vdi] - compression: gz # image compression format (optional) - size: 8GiB # 4G, 4GB, 4096 MiB also valid. (Required for raw) - partitionTableType: gpt # Partition table type, valid value: [gpt, mbr] - partitions: # Required for raw, optional for ISO, not needed for rootfs. - - id: boot - type: esp - flags: - - esp - - boot - start: 1MiB - end: 513MiB - fsType: fat32 - mountPoint: /boot/efi - mountOptions: umask=0077 - - - id: rootfs - type: linux-root-amd64 - start: 513MiB - end: "0" - fsType: ext4 - mountPoint: / - mountOptions: defaults - -systemConfig: - name: Minimal_Raw - description: Default yml configuration for raw image - - immutability: - enabled: false # default is true, overridden to false here - - packages: - - intel-dlstreamer_2025.2.0 - - firmware-linux - - kernel: - version: "251229t065211z-r2" - cmdline: "console=ttyS0,115200 console=tty0 loglevel=7 i915.force_probe=*" - packages: - - linux-image-6.12-intel - - linux-headers-6.12-intel diff --git a/scripts/build_elxr-edge-26.04_dlstreamer.sh b/scripts/build_elxr-edge-26.04_dlstreamer.sh deleted file mode 100644 index 47a938517..000000000 --- a/scripts/build_elxr-edge-26.04_dlstreamer.sh +++ /dev/null @@ -1,192 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Parse command line arguments -RUN_QEMU_TESTS=false -WORKING_DIR="$(pwd)" - -while [[ $# -gt 0 ]]; do - case $1 in - --qemu-test|--with-qemu) - RUN_QEMU_TESTS=true - shift - ;; - --working-dir) - WORKING_DIR="$2" - shift 2 - ;; - -h|--help) - echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]" - echo " --qemu-test, --with-qemu Run QEMU boot tests after image build" - echo " --working-dir DIR Set the working directory" - echo " -h, --help Show this help message" - exit 0 - ;; - *) - echo "Unknown option $1" - echo "Use -h or --help for usage information" - exit 1 - ;; - esac -done - -# Centralized cleanup function for image files -cleanup_image_files() { - local cleanup_type="${1:-all}" - - case "$cleanup_type" in - "raw") - echo "Cleaning up raw image files from build directories..." - sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true - sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true - ;; - "extracted") - echo "Cleaning up extracted image files in current directory..." - rm -f ./*.raw 2>/dev/null || true - ;; - "all"|*) - echo "Cleaning up all temporary image files..." - sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true - sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true - rm -f ./*.raw 2>/dev/null || true - ;; - esac -} - -run_qemu_boot_test() { - local IMAGE_PATTERN="$1" - if [ -z "$IMAGE_PATTERN" ]; then - echo "Error: Image pattern not provided to run_qemu_boot_test" - return 1 - fi - - local RAW_IMAGE="" - local SUCCESS_STRING="login:" - local LOGFILE="/tmp/qemu_boot_test_${IMAGE_PATTERN}.log" - local ORIGINAL_DIR - ORIGINAL_DIR="$(pwd)" - - echo "Looking for compressed raw image matching pattern: *${IMAGE_PATTERN}*.raw.gz" - - cd "$WORKING_DIR" - - if ls ./*"${IMAGE_PATTERN}"*.raw.gz 1>/dev/null 2>&1; then - GZ_IMAGE=$(ls ./*"${IMAGE_PATTERN}"*.raw.gz | head -1) - echo "Found compressed image: $GZ_IMAGE" - echo "Extracting..." - gunzip -k "$GZ_IMAGE" - RAW_IMAGE="${GZ_IMAGE%.gz}" - - if [ ! -f "$RAW_IMAGE" ]; then - echo "Error: extraction failed, $RAW_IMAGE not found" - cd "$ORIGINAL_DIR" - return 1 - fi - - IMAGE="$RAW_IMAGE" - else - echo "Compressed raw image file matching pattern '*${IMAGE_PATTERN}*.raw.gz' not found!" - return 1 - fi - - echo "Booting image: $IMAGE" - sudo bash -c " - LOGFILE=\"$LOGFILE\" - SUCCESS_STRING=\"$SUCCESS_STRING\" - IMAGE=\"$IMAGE\" - RAW_IMAGE=\"$RAW_IMAGE\" - ORIGINAL_DIR=\"$ORIGINAL_DIR\" - - touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\" - nohup qemu-system-x86_64 \\ - -m 2048 \\ - -enable-kvm \\ - -cpu host \\ - -drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\ - -device nvme,drive=nvme0,serial=deadbeef \\ - -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\ - -drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\ - -nographic \\ - -serial mon:stdio \\ - -append 'console=ttyS0' > \"\$LOGFILE\" 2>&1 & - - QEMU_PID=\$! - TIMEOUT=180 - ELAPSED=0 - - while [ \$ELAPSED -lt \$TIMEOUT ]; do - if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" 2>/dev/null; then - echo \"Boot successful - found '\$SUCCESS_STRING' in output\" - kill \$QEMU_PID 2>/dev/null || true - break - fi - if ! ps -p \$QEMU_PID > /dev/null 2>&1; then - echo \"QEMU process exited unexpectedly\" - break - fi - sleep 5 - ELAPSED=\$((ELAPSED + 5)) - echo \"Waiting for boot... (\${ELAPSED}s/\${TIMEOUT}s)\" - done - - kill \$QEMU_PID 2>/dev/null || true - - if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then - echo \"Boot test PASSED\" - result=0 - else - echo \"Boot failed or timed out\" - result=1 - fi - - if [ -f \"\$RAW_IMAGE\" ]; then - echo \"Cleaning up extracted image file: \$RAW_IMAGE\" - rm -f \"\$RAW_IMAGE\" - fi - - cd \"\$ORIGINAL_DIR\" - exit \$result - " - - qemu_result=$? - return $qemu_result -} - -git branch - -echo "Building the ICT..." -echo "Generating binary with go build..." -go build ./cmd/image-composer-tool - -build_elxr_edge_26_04_dlstreamer_image() { - echo "Building ELXR Edge 26.04 DLStreamer Image. (using image-composer-tool binary)" - echo "Ensuring we're in the working directory before starting builds..." - cd "$WORKING_DIR" - echo "Current working directory: $(pwd)" - - set +e - output=$(sudo -S ./image-composer-tool build image-templates/elxr-edge-26.04-x86_64-dlstreamer.yml 2>&1) - build_exit_code=$? - set -e - - if [ $build_exit_code -eq 0 ] && echo "$output" | grep -q "image build completed successfully"; then - echo "ELXR Edge 26.04 DLStreamer Image build passed." - if [ "$RUN_QEMU_TESTS" = true ]; then - echo "Running QEMU boot test for ELXR Edge 26.04 DLStreamer image..." - if run_qemu_boot_test "elxr-edge-26.04-dlstreamer-x86_64"; then - echo "QEMU boot test PASSED for ELXR Edge 26.04 DLStreamer image" - else - echo "QEMU boot test FAILED for ELXR Edge 26.04 DLStreamer image" - exit 1 - fi - cleanup_image_files raw - fi - else - echo "ELXR Edge 26.04 DLStreamer Image build failed." - echo "Build output:" - echo "$output" - exit 1 - fi -} - -build_elxr_edge_26_04_dlstreamer_image