From 55a08257a9debafe5e586c58df280f1624f07d3e Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 06:56:34 +0530 Subject: [PATCH 01/16] Add RPM compatibility testing workflow This workflow tests the compatibility of the Tuttle RPM package across multiple Linux distributions, including Fedora, Rocky Linux, AlmaLinux, CentOS Stream, and Oracle Linux. It checks for dependencies, installs the package, and verifies successful installation. --- .github/workflows/rpm-compatibility.yml | 173 ++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 .github/workflows/rpm-compatibility.yml diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml new file mode 100644 index 00000000..f4c3d182 --- /dev/null +++ b/.github/workflows/rpm-compatibility.yml @@ -0,0 +1,173 @@ + +name: RPM Compatibility + +on: + workflow_dispatch: + +jobs: + rpm-test: + name: ${{ matrix.name }} + + strategy: + fail-fast: false + matrix: + include: + - name: Fedora 44 + image: fedora:44 + + - name: Rocky Linux 9 + image: rockylinux:9 + + - name: AlmaLinux 9 + image: almalinux:9 + + - name: CentOS Stream 9 + image: quay.io/centos/centos:stream9 + + - name: Oracle Linux 9 + image: oraclelinux:9 + + runs-on: ubuntu-latest + + container: + image: ${{ matrix.image }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Show operating system + run: | + echo "======================================" + echo "Operating System" + echo "======================================" + cat /etc/os-release + + - name: Install RPM test tools + run: | + dnf install -y rpm dnf + + - name: Show enabled repositories + run: | + echo "======================================" + echo "Enabled repositories" + echo "======================================" + dnf repolist + + - name: Find Tuttle RPM + id: find-rpm + run: | + RPM=$(find . -type f -name '*.rpm' | head -n 1) + + if [ -z "$RPM" ]; then + echo "❌ FAIL: No Tuttle RPM found" + exit 1 + fi + + echo "Tuttle RPM: $RPM" + echo "rpm=$RPM" >> "$GITHUB_OUTPUT" + + - name: Inspect Tuttle dependencies + run: | + RPM="${{ steps.find-rpm.outputs.rpm }}" + + echo "======================================" + echo "Tuttle RPM dependencies" + echo "======================================" + + rpm -qp --requires "$RPM" + + echo + echo "======================================" + echo "FUSE dependencies" + echo "======================================" + + rpm -qp --requires "$RPM" | grep -i fuse || true + + - name: Check fuse2-libs availability + run: | + RPM="${{ steps.find-rpm.outputs.rpm }}" + + echo "======================================" + echo "Checking FUSE 2 package" + echo "======================================" + + if rpm -qp --requires "$RPM" | grep -qx 'fuse2-libs'; then + echo "Tuttle requires fuse2-libs" + + if dnf repoquery --whatprovides 'fuse2-libs' 2>/dev/null | grep -q .; then + echo "✅ PASS: fuse2-libs is available" + else + echo "❌ FAIL: fuse2-libs is NOT available" + exit 1 + fi + else + echo "Tuttle does not explicitly require fuse2-libs" + echo "Continuing..." + fi + + - name: Check libfuse.so.2 availability + run: | + RPM="${{ steps.find-rpm.outputs.rpm }}" + + echo "======================================" + echo "Checking libfuse.so.2" + echo "======================================" + + if rpm -qp --requires "$RPM" | grep -q 'fuse2-libs'; then + + if dnf provides '*/libfuse.so.2' 2>/dev/null | grep -q .; then + echo "✅ PASS: libfuse.so.2 is available" + else + echo "❌ FAIL: libfuse.so.2 is NOT available" + exit 1 + fi + + else + echo "libfuse.so.2 is not required by the RPM" + fi + + - name: Test Tuttle RPM installation + run: | + RPM="${{ steps.find-rpm.outputs.rpm }}" + + echo "======================================" + echo "Testing Tuttle installation" + echo "======================================" + + if dnf install -y "$RPM"; then + echo + echo "======================================" + echo "✅ PASS: Tuttle installed successfully" + echo "======================================" + else + echo + echo "======================================" + echo "❌ FAIL: Tuttle installation failed" + echo "======================================" + exit 1 + fi + + - name: Verify installed package + run: | + echo "======================================" + echo "Installed Tuttle packages" + echo "======================================" + + rpm -qa | grep -i tuttle || { + echo "❌ FAIL: Tuttle package not found after installation" + exit 1 + } + + echo + echo "======================================" + echo "✅ PASS: Tuttle package is installed" + echo "======================================" + + - name: Final result + run: | + echo + echo "======================================" + echo "✅ PASS: ${{ matrix.name }}" + echo "Tuttle RPM works with the default repositories." + echo "======================================" From 76b460c7a58301098e08eb61655b1ed0aed0dd2e Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 11:50:02 +0530 Subject: [PATCH 02/16] Update rpm-compatibility.yml --- .github/workflows/rpm-compatibility.yml | 166 +++++++++++++++++++----- 1 file changed, 132 insertions(+), 34 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index f4c3d182..e22db671 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -1,8 +1,12 @@ - name: RPM Compatibility on: workflow_dispatch: + inputs: + tag: + description: "Tuttle release tag to test" + required: true + default: "v4.2.1" jobs: rpm-test: @@ -10,6 +14,7 @@ jobs: strategy: fail-fast: false + matrix: include: - name: Fedora 44 @@ -33,43 +38,102 @@ jobs: image: ${{ matrix.image }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - + # --------------------------------------------------------- + # 1. Install tools + # --------------------------------------------------------- + - name: Install test tools + run: | + dnf install -y \ + curl \ + rpm \ + dnf \ + jq \ + ca-certificates + + # --------------------------------------------------------- + # 2. Show OS + # --------------------------------------------------------- - name: Show operating system run: | echo "======================================" echo "Operating System" echo "======================================" - cat /etc/os-release - - name: Install RPM test tools - run: | - dnf install -y rpm dnf + cat /etc/os-release + # --------------------------------------------------------- + # 3. Show repositories + # --------------------------------------------------------- - name: Show enabled repositories run: | echo "======================================" echo "Enabled repositories" echo "======================================" + dnf repolist - - name: Find Tuttle RPM - id: find-rpm + # --------------------------------------------------------- + # 4. Download RPM from GitHub Release + # --------------------------------------------------------- + - name: Download Tuttle RPM + env: + TAG: ${{ inputs.tag }} run: | - RPM=$(find . -type f -name '*.rpm' | head -n 1) + echo "======================================" + echo "Downloading Tuttle RPM" + echo "Release: ${TAG}" + echo "======================================" + + mkdir -p /tmp/tuttle + + # Get release metadata from GitHub + curl -fsSL \ + "https://api.github.com/repos/tuttle-dev/tuttle/releases/tags/${TAG}" \ + -o /tmp/tuttle/release.json + + echo + echo "Release assets:" + jq -r '.assets[].browser_download_url' /tmp/tuttle/release.json || true + + # Download the first architecture-appropriate RPM asset (excluding debuginfo) + RPM_URL=$(jq -r '.assets[] | select(.name | endswith(".rpm") and (contains("debuginfo") | not)) | .browser_download_url' /tmp/tuttle/release.json | head -n 1) - if [ -z "$RPM" ]; then - echo "❌ FAIL: No Tuttle RPM found" + if [ -z "$RPM_URL" ] || [ "$RPM_URL" = "null" ]; then + echo "❌ FAIL: No valid RPM asset found in release ${TAG}" exit 1 fi - echo "Tuttle RPM: $RPM" - echo "rpm=$RPM" >> "$GITHUB_OUTPUT" + echo + echo "RPM URL:" + echo "$RPM_URL" + + curl -fL \ + "$RPM_URL" \ + -o /tmp/tuttle/tuttle.rpm + echo + echo "Downloaded RPM:" + ls -lh /tmp/tuttle/tuttle.rpm + + # --------------------------------------------------------- + # 5. Verify RPM + # --------------------------------------------------------- + - name: Verify RPM + run: | + RPM=/tmp/tuttle/tuttle.rpm + + echo "======================================" + echo "RPM Information" + echo "======================================" + + rpm -qip "$RPM" + + # --------------------------------------------------------- + # 6. Inspect dependencies + # --------------------------------------------------------- - name: Inspect Tuttle dependencies run: | - RPM="${{ steps.find-rpm.outputs.rpm }}" + RPM=/tmp/tuttle/tuttle.rpm echo "======================================" echo "Tuttle RPM dependencies" @@ -84,15 +148,19 @@ jobs: rpm -qp --requires "$RPM" | grep -i fuse || true + # --------------------------------------------------------- + # 7. Check fuse2-libs + # --------------------------------------------------------- - name: Check fuse2-libs availability run: | - RPM="${{ steps.find-rpm.outputs.rpm }}" + RPM=/tmp/tuttle/tuttle.rpm echo "======================================" - echo "Checking FUSE 2 package" + echo "Checking fuse2-libs" echo "======================================" - if rpm -qp --requires "$RPM" | grep -qx 'fuse2-libs'; then + if rpm -qp --requires "$RPM" | grep -q 'fuse2-libs'; then + echo "Tuttle requires fuse2-libs" if dnf repoquery --whatprovides 'fuse2-libs' 2>/dev/null | grep -q .; then @@ -101,14 +169,17 @@ jobs: echo "❌ FAIL: fuse2-libs is NOT available" exit 1 fi + else - echo "Tuttle does not explicitly require fuse2-libs" - echo "Continuing..." + echo "ℹ️ Tuttle does not explicitly require fuse2-libs" fi + # --------------------------------------------------------- + # 8. Check libfuse.so.2 + # --------------------------------------------------------- - name: Check libfuse.so.2 availability run: | - RPM="${{ steps.find-rpm.outputs.rpm }}" + RPM=/tmp/tuttle/tuttle.rpm echo "======================================" echo "Checking libfuse.so.2" @@ -124,50 +195,77 @@ jobs: fi else - echo "libfuse.so.2 is not required by the RPM" + echo "ℹ️ libfuse.so.2 is not required by the RPM" fi + # --------------------------------------------------------- + # 9. Test actual installation + # --------------------------------------------------------- - name: Test Tuttle RPM installation run: | - RPM="${{ steps.find-rpm.outputs.rpm }}" + RPM=/tmp/tuttle/tuttle.rpm echo "======================================" echo "Testing Tuttle installation" echo "======================================" if dnf install -y "$RPM"; then + echo echo "======================================" echo "✅ PASS: Tuttle installed successfully" echo "======================================" + else + echo echo "======================================" echo "❌ FAIL: Tuttle installation failed" echo "======================================" + exit 1 fi + # --------------------------------------------------------- + # 10. Verify package + # --------------------------------------------------------- - name: Verify installed package run: | echo "======================================" - echo "Installed Tuttle packages" + echo "Verifying installed Tuttle package" echo "======================================" - rpm -qa | grep -i tuttle || { - echo "❌ FAIL: Tuttle package not found after installation" - exit 1 - } + if rpm -qa | grep -qi '^tuttle'; then - echo - echo "======================================" - echo "✅ PASS: Tuttle package is installed" - echo "======================================" + echo + echo "======================================" + echo "✅ PASS: Tuttle package is installed" + echo "======================================" + rpm -qa | grep -i tuttle + + else + + echo + echo "======================================" + echo "❌ FAIL: Tuttle package not found" + echo "======================================" + + exit 1 + fi + + # --------------------------------------------------------- + # 11. Final result + # --------------------------------------------------------- - name: Final result run: | echo echo "======================================" echo "✅ PASS: ${{ matrix.name }}" - echo "Tuttle RPM works with the default repositories." echo "======================================" + echo + echo "Tuttle RPM:" + echo "${{ inputs.tag }}" + echo + echo "The RPM successfully installed using" + echo "the distribution's configured repositories." From fa675db8bd17058b7b2484977f242947b64d40d8 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 12:01:19 +0530 Subject: [PATCH 03/16] Update dnf install command to include --allowerasing --- .github/workflows/rpm-compatibility.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index e22db671..3b7e1476 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -43,7 +43,7 @@ jobs: # --------------------------------------------------------- - name: Install test tools run: | - dnf install -y \ + dnf install -y --allowerasing \ curl \ rpm \ dnf \ From cd4e637a4db15b9a961230a01246dda58c1e3111 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 12:07:46 +0530 Subject: [PATCH 04/16] Update fuse2-libs dependency to fuse-libs for RPM based distro --- ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/package.json b/ui/package.json index f343ad91..aa108706 100644 --- a/ui/package.json +++ b/ui/package.json @@ -84,7 +84,7 @@ "rpm": { "depends": [ "zlib", - "fuse2-libs" + "fuse-libs" ] } }, From dc88679ddbaf118a1ff83c9ba39ee99388c8b6c4 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 12:30:06 +0530 Subject: [PATCH 05/16] Refactor RPM compatibility workflow for multiple OS --- .github/workflows/rpm-compatibility.yml | 431 +++++++++++++----------- 1 file changed, 228 insertions(+), 203 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index 3b7e1476..07f93854 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -2,141 +2,169 @@ name: RPM Compatibility on: workflow_dispatch: - inputs: - tag: - description: "Tuttle release tag to test" - required: true - default: "v4.2.1" jobs: - rpm-test: - name: ${{ matrix.name }} - - strategy: - fail-fast: false - - matrix: - include: - - name: Fedora 44 - image: fedora:44 - - - name: Rocky Linux 9 - image: rockylinux:9 - - - name: AlmaLinux 9 - image: almalinux:9 - - - name: CentOS Stream 9 - image: quay.io/centos/centos:stream9 - - - name: Oracle Linux 9 - image: oraclelinux:9 - + # ========================================================= + # Build the REAL Tuttle RPM from source on Fedora 44 + # ========================================================= + build-rpm: + name: Build RPM on Fedora 44 runs-on: ubuntu-latest - container: - image: ${{ matrix.image }} - steps: - # --------------------------------------------------------- - # 1. Install tools - # --------------------------------------------------------- - - name: Install test tools - run: | - dnf install -y --allowerasing \ - curl \ - rpm \ - dnf \ - jq \ - ca-certificates - - # --------------------------------------------------------- - # 2. Show OS - # --------------------------------------------------------- - - name: Show operating system - run: | - echo "======================================" - echo "Operating System" - echo "======================================" - - cat /etc/os-release + - name: Checkout repository + uses: actions/checkout@v6 - # --------------------------------------------------------- - # 3. Show repositories - # --------------------------------------------------------- - - name: Show enabled repositories + - name: Build Tuttle RPM on Fedora 44 run: | - echo "======================================" - echo "Enabled repositories" - echo "======================================" + docker run --rm \ + -v "$GITHUB_WORKSPACE:/workspace" \ + -w /workspace \ + fedora:44 \ + bash -c ' + set -e + + echo "======================================" + echo "Operating System" + echo "======================================" + + cat /etc/os-release + + echo + echo "======================================" + echo "Install system dependencies" + echo "======================================" + + dnf install -y \ + curl \ + git \ + gcc \ + gcc-c++ \ + make \ + rpm \ + rpm-build \ + python3 \ + python3-devel \ + jq \ + ca-certificates \ + tar \ + gzip + + echo + echo "======================================" + echo "Install Node.js 22" + echo "======================================" + + curl -fsSL https://rpm.nodesource.com/setup_22.x | bash - + dnf install -y nodejs + + node --version + npm --version + + echo + echo "======================================" + echo "Install uv" + echo "======================================" + + curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.local/bin:$PATH" + + uv --version + + echo + echo "======================================" + echo "Install Python 3.13" + echo "======================================" + + uv python install 3.13 + + echo + echo "======================================" + echo "Install Python dependencies" + echo "======================================" + + uv sync --all-groups + + echo + echo "======================================" + echo "Build Python core" + echo "======================================" + + uv run pyinstaller \ + --clean \ + --noconfirm \ + tuttle-rpc.spec + + echo + echo "======================================" + echo "Smoke test Python core" + echo "======================================" + + uv run python scripts/smoke_core.py + + echo + echo "======================================" + echo "Install Electron dependencies" + echo "======================================" + + cd ui + + npm ci + + echo + echo "======================================" + echo "Build Electron app" + echo "======================================" + + npm run build + + echo + echo "======================================" + echo "Build RPM" + echo "======================================" - dnf repolist + npx electron-builder \ + --linux rpm \ + --publish never - # --------------------------------------------------------- - # 4. Download RPM from GitHub Release - # --------------------------------------------------------- - - name: Download Tuttle RPM - env: - TAG: ${{ inputs.tag }} + echo + echo "======================================" + echo "Generated RPM" + echo "======================================" + + find release -type f -name "*.rpm" -print + ' + + - name: Verify RPM was generated run: | echo "======================================" - echo "Downloading Tuttle RPM" - echo "Release: ${TAG}" + echo "Generated RPM" echo "======================================" - mkdir -p /tmp/tuttle - - # Get release metadata from GitHub - curl -fsSL \ - "https://api.github.com/repos/tuttle-dev/tuttle/releases/tags/${TAG}" \ - -o /tmp/tuttle/release.json + find ui/release -type f -name "*.rpm" -print - echo - echo "Release assets:" - jq -r '.assets[].browser_download_url' /tmp/tuttle/release.json || true - - # Download the first architecture-appropriate RPM asset (excluding debuginfo) - RPM_URL=$(jq -r '.assets[] | select(.name | endswith(".rpm") and (contains("debuginfo") | not)) | .browser_download_url' /tmp/tuttle/release.json | head -n 1) + RPM_COUNT=$(find ui/release -type f -name "*.rpm" | wc -l) - if [ -z "$RPM_URL" ] || [ "$RPM_URL" = "null" ]; then - echo "❌ FAIL: No valid RPM asset found in release ${TAG}" + if [ "$RPM_COUNT" -eq 0 ]; then + echo "❌ FAIL: No RPM generated" exit 1 fi - echo - echo "RPM URL:" - echo "$RPM_URL" - - curl -fL \ - "$RPM_URL" \ - -o /tmp/tuttle/tuttle.rpm - - echo - echo "Downloaded RPM:" - ls -lh /tmp/tuttle/tuttle.rpm + echo "✅ Found $RPM_COUNT RPM" - # --------------------------------------------------------- - # 5. Verify RPM - # --------------------------------------------------------- - - name: Verify RPM + - name: Inspect RPM dependencies run: | - RPM=/tmp/tuttle/tuttle.rpm + RPM=$(find ui/release -type f -name "*.rpm" | head -n 1) echo "======================================" - echo "RPM Information" + echo "RPM information" echo "======================================" rpm -qip "$RPM" - # --------------------------------------------------------- - # 6. Inspect dependencies - # --------------------------------------------------------- - - name: Inspect Tuttle dependencies - run: | - RPM=/tmp/tuttle/tuttle.rpm - + echo echo "======================================" - echo "Tuttle RPM dependencies" + echo "RPM dependencies" echo "======================================" rpm -qp --requires "$RPM" @@ -148,124 +176,121 @@ jobs: rpm -qp --requires "$RPM" | grep -i fuse || true - # --------------------------------------------------------- - # 7. Check fuse2-libs - # --------------------------------------------------------- - - name: Check fuse2-libs availability - run: | - RPM=/tmp/tuttle/tuttle.rpm + - name: Upload RPM + uses: actions/upload-artifact@v7 + with: + name: tuttle-rpm + path: ui/release/*.rpm + if-no-files-found: error - echo "======================================" - echo "Checking fuse2-libs" - echo "======================================" - if rpm -qp --requires "$RPM" | grep -q 'fuse2-libs'; then + # ========================================================= + # Test the SAME RPM on RPM-based distributions + # ========================================================= + rpm-test: + name: ${{ matrix.name }} - echo "Tuttle requires fuse2-libs" + needs: build-rpm - if dnf repoquery --whatprovides 'fuse2-libs' 2>/dev/null | grep -q .; then - echo "✅ PASS: fuse2-libs is available" - else - echo "❌ FAIL: fuse2-libs is NOT available" - exit 1 - fi + runs-on: ubuntu-latest - else - echo "ℹ️ Tuttle does not explicitly require fuse2-libs" - fi + strategy: + fail-fast: false - # --------------------------------------------------------- - # 8. Check libfuse.so.2 - # --------------------------------------------------------- - - name: Check libfuse.so.2 availability - run: | - RPM=/tmp/tuttle/tuttle.rpm + matrix: + include: + - name: Fedora 44 + image: fedora:44 - echo "======================================" - echo "Checking libfuse.so.2" - echo "======================================" + - name: Rocky Linux 9 + image: rockylinux:9 - if rpm -qp --requires "$RPM" | grep -q 'fuse2-libs'; then + - name: AlmaLinux 9 + image: almalinux:9 - if dnf provides '*/libfuse.so.2' 2>/dev/null | grep -q .; then - echo "✅ PASS: libfuse.so.2 is available" - else - echo "❌ FAIL: libfuse.so.2 is NOT available" - exit 1 - fi + - name: CentOS Stream 9 + image: quay.io/centos/centos:stream9 - else - echo "ℹ️ libfuse.so.2 is not required by the RPM" - fi + - name: Oracle Linux 9 + image: oraclelinux:9 + + steps: + - name: Download RPM + uses: actions/download-artifact@v7 + with: + name: tuttle-rpm + path: /tmp/tuttle - # --------------------------------------------------------- - # 9. Test actual installation - # --------------------------------------------------------- - - name: Test Tuttle RPM installation + - name: Test RPM on ${{ matrix.name }} + env: + IMAGE: ${{ matrix.image }} run: | - RPM=/tmp/tuttle/tuttle.rpm + docker run --rm \ + -v "/tmp/tuttle:/tmp/tuttle:ro" \ + "$IMAGE" \ + bash -c ' + set -e - echo "======================================" - echo "Testing Tuttle installation" - echo "======================================" + echo "======================================" + echo "Operating System" + echo "======================================" - if dnf install -y "$RPM"; then + cat /etc/os-release - echo - echo "======================================" - echo "✅ PASS: Tuttle installed successfully" - echo "======================================" + echo + echo "======================================" + echo "Install RPM tools" + echo "======================================" - else + dnf install -y \ + rpm \ + dnf \ + ca-certificates - echo - echo "======================================" - echo "❌ FAIL: Tuttle installation failed" - echo "======================================" + RPM=$(find /tmp/tuttle -type f -name "*.rpm" | head -n 1) - exit 1 - fi + if [ -z "$RPM" ]; then + echo "❌ FAIL: RPM not found" + exit 1 + fi - # --------------------------------------------------------- - # 10. Verify package - # --------------------------------------------------------- - - name: Verify installed package - run: | - echo "======================================" - echo "Verifying installed Tuttle package" - echo "======================================" + echo + echo "======================================" + echo "RPM information" + echo "======================================" - if rpm -qa | grep -qi '^tuttle'; then + rpm -qip "$RPM" - echo - echo "======================================" - echo "✅ PASS: Tuttle package is installed" - echo "======================================" + echo + echo "======================================" + echo "RPM dependencies" + echo "======================================" - rpm -qa | grep -i tuttle + rpm -qp --requires "$RPM" - else + echo + echo "======================================" + echo "FUSE dependencies" + echo "======================================" - echo - echo "======================================" - echo "❌ FAIL: Tuttle package not found" - echo "======================================" + rpm -qp --requires "$RPM" | grep -i fuse || true - exit 1 - fi + echo + echo "======================================" + echo "Testing installation" + echo "======================================" - # --------------------------------------------------------- - # 11. Final result - # --------------------------------------------------------- - - name: Final result - run: | - echo - echo "======================================" - echo "✅ PASS: ${{ matrix.name }}" - echo "======================================" - echo - echo "Tuttle RPM:" - echo "${{ inputs.tag }}" - echo - echo "The RPM successfully installed using" - echo "the distribution's configured repositories." + dnf install -y "$RPM" + + echo + echo "======================================" + echo "Verify installation" + echo "======================================" + + rpm -qa | grep -i "^tuttle" + + echo + echo "======================================" + echo "✅ PASS: ${{ matrix.name }}" + echo "======================================" + ' From 7537652c42b28baf7d72b699797d4a7e3c3aa00a Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 12:38:57 +0530 Subject: [PATCH 06/16] Add dependency installation step for RPM build --- .github/workflows/rpm-compatibility.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index 07f93854..b16f572e 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -14,7 +14,9 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v6 - + - name: Install dependencies + run: | + sudo dnf install -y libxcrypt-compat - name: Build Tuttle RPM on Fedora 44 run: | docker run --rm \ From a5fff9ecbed007f175cd095418a8ba45e3a3fb48 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 12:45:45 +0530 Subject: [PATCH 07/16] Update rpm-compatibility.yml --- .github/workflows/rpm-compatibility.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index b16f572e..29497161 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -13,10 +13,8 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 - - name: Install dependencies - run: | - sudo dnf install -y libxcrypt-compat + uses: actions/checkout@v4 + - name: Build Tuttle RPM on Fedora 44 run: | docker run --rm \ @@ -38,6 +36,7 @@ jobs: echo "======================================" dnf install -y \ + libxcrypt-compat \ curl \ git \ gcc \ @@ -179,7 +178,7 @@ jobs: rpm -qp --requires "$RPM" | grep -i fuse || true - name: Upload RPM - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@v4 with: name: tuttle-rpm path: ui/release/*.rpm @@ -218,7 +217,7 @@ jobs: steps: - name: Download RPM - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v4 with: name: tuttle-rpm path: /tmp/tuttle From c441fcdd55f80982b08dc06b861000d38e36de01 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 21:24:15 +0530 Subject: [PATCH 08/16] Implement smoke test for app with Xvfb Added smoke test for app under Xvfb with crash report checks. --- .github/workflows/rpm-compatibility.yml | 69 +++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index 29497161..3954c54d 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -290,6 +290,75 @@ jobs: rpm -qa | grep -i "^tuttle" + echo + echo "======================================" + echo "Install Xvfb (virtual display)" + echo "======================================" + + dnf install -y xorg-x11-server-Xvfb + + echo + echo "======================================" + echo "Locate app binary" + echo "======================================" + + BINARY=$(rpm -ql tuttle | grep -E "^/usr/bin/|^/opt/.*/[Tt]uttle$" | head -n 1) + + if [ -z "$BINARY" ]; then + echo "❌ FAIL: Could not locate app binary" + rpm -ql tuttle + exit 1 + fi + + echo "Binary: $BINARY" + + echo + echo "======================================" + echo "Smoke test app under Xvfb (display)" + echo "======================================" + + rm -rf /tmp/crash-reports + mkdir -p /tmp/crash-reports + + set +e + xvfb-run --auto-servernum --server-args="-screen 0 1280x1024x24" \ + timeout 20s "$BINARY" \ + --no-sandbox \ + --disable-gpu \ + --crash-dumps-dir=/tmp/crash-reports \ + > /tmp/app-stdout.log 2>&1 + APP_EXIT=$? + set -e + + echo "--- App stdout/stderr ---" + cat /tmp/app-stdout.log || true + + echo + echo "======================================" + echo "Check for crash artifacts" + echo "======================================" + + CRASH_FILES=$(find /tmp/crash-reports -type f 2>/dev/null | wc -l) + CORE_FILES=$(find / -maxdepth 2 -name "core*" -newer /tmp/app-stdout.log 2>/dev/null | wc -l) + + echo "Crash dump files: $CRASH_FILES" + echo "Core files: $CORE_FILES" + echo "App exit code: $APP_EXIT" + + # Exit code 124 = timeout (expected for a long-running GUI app + # that launched fine and had to be killed) -- treat as success. + if [ "$APP_EXIT" -ne 0 ] && [ "$APP_EXIT" -ne 124 ]; then + echo "❌ FAIL: App exited abnormally (code $APP_EXIT)" + exit 1 + fi + + if [ "$CRASH_FILES" -gt 0 ] || [ "$CORE_FILES" -gt 0 ]; then + echo "❌ FAIL: Crash artifacts detected" + exit 1 + fi + + echo "✅ PASS: No crash on launch (${{ matrix.name }})" + echo echo "======================================" echo "✅ PASS: ${{ matrix.name }}" From 0a044264d361539fdad79a309da5fd3df3ffcfc1 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Wed, 12 Aug 2026 21:50:54 +0530 Subject: [PATCH 09/16] Enhance RPM installation verification in workflow Added verification steps for Tuttle RPM installation to the workflow. --- .github/workflows/rpm-compatibility.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index 3954c54d..e3f773eb 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -282,7 +282,24 @@ jobs: echo "======================================" dnf install -y "$RPM" - + echo "======================================" + echo "Verify Tuttle RPM installation" + echo "======================================" + + echo "RPM package status:" + rpm -q tuttle || true + + echo "" + echo "Installed files:" + rpm -ql tuttle || true + + echo "" + echo "Tuttle executables:" + rpm -ql tuttle | grep -Ei 'tuttle|/bin/' || true + + echo "" + echo "Searching filesystem:" + find /usr /opt -iname '*tuttle*' -type f 2>/dev/null || true echo echo "======================================" echo "Verify installation" From 87912bd8cb5ac2459c3769f53387834404908ee8 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Thu, 13 Aug 2026 07:02:32 +0530 Subject: [PATCH 10/16] Refactor RPM build and test workflow Updated the workflow to improve clarity and consistency in RPM generation and testing steps, including enhanced logging and error handling. --- .github/workflows/rpm-compatibility.yml | 324 ++++++++++++++++++++---- 1 file changed, 276 insertions(+), 48 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index e3f773eb..d50c7e10 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -12,16 +12,34 @@ jobs: runs-on: ubuntu-latest steps: + # ------------------------------------------------------- + # Checkout + # ------------------------------------------------------- - name: Checkout repository uses: actions/checkout@v4 + # ------------------------------------------------------- + # Build RPM inside Fedora 44 + # ------------------------------------------------------- - name: Build Tuttle RPM on Fedora 44 run: | + set -e + + echo "======================================" + echo "Pull Fedora 44" + echo "======================================" + + docker pull fedora:44 + + echo "======================================" + echo "Build Tuttle RPM inside Fedora 44" + echo "======================================" + docker run --rm \ -v "$GITHUB_WORKSPACE:/workspace" \ -w /workspace \ fedora:44 \ - bash -c ' + bash -lc ' set -e echo "======================================" @@ -49,7 +67,8 @@ jobs: jq \ ca-certificates \ tar \ - gzip + gzip \ + findutils echo echo "======================================" @@ -59,7 +78,12 @@ jobs: curl -fsSL https://rpm.nodesource.com/setup_22.x | bash - dnf install -y nodejs + echo + echo "Node version:" node --version + + echo + echo "npm version:" npm --version echo @@ -68,8 +92,10 @@ jobs: echo "======================================" curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.local/bin:$PATH" + echo uv --version echo @@ -79,6 +105,10 @@ jobs: uv python install 3.13 + echo + echo "Python versions:" + uv python list + echo echo "======================================" echo "Install Python dependencies" @@ -114,7 +144,7 @@ jobs: echo echo "======================================" - echo "Build Electron app" + echo "Build Electron application" echo "======================================" npm run build @@ -130,19 +160,40 @@ jobs: echo echo "======================================" - echo "Generated RPM" + echo "Generated RPM files" echo "======================================" - find release -type f -name "*.rpm" -print + find release \ + -type f \ + -name "*.rpm" \ + -print + + RPM_COUNT=$(find release -type f -name "*.rpm" | wc -l) + + if [ "$RPM_COUNT" -eq 0 ]; then + echo "❌ FAIL: electron-builder did not generate an RPM" + exit 1 + fi + + echo + echo "✅ Successfully generated $RPM_COUNT RPM file(s)" ' + # ------------------------------------------------------- + # Verify RPM exists + # ------------------------------------------------------- - name: Verify RPM was generated run: | + set -e + echo "======================================" echo "Generated RPM" echo "======================================" - find ui/release -type f -name "*.rpm" -print + find ui/release \ + -type f \ + -name "*.rpm" \ + -print RPM_COUNT=$(find ui/release -type f -name "*.rpm" | wc -l) @@ -151,11 +202,32 @@ jobs: exit 1 fi - echo "✅ Found $RPM_COUNT RPM" + echo "✅ Found $RPM_COUNT RPM file(s)" + # ------------------------------------------------------- + # Install RPM tool on GitHub runner + # ------------------------------------------------------- + - name: Install RPM inspection tools + run: | + sudo apt-get update + sudo apt-get install -y rpm + + # ------------------------------------------------------- + # Inspect RPM + # ------------------------------------------------------- - name: Inspect RPM dependencies run: | - RPM=$(find ui/release -type f -name "*.rpm" | head -n 1) + set -e + + RPM=$(find ui/release \ + -type f \ + -name "*.rpm" \ + | head -n 1) + + if [ -z "$RPM" ]; then + echo "❌ RPM not found" + exit 1 + fi echo "======================================" echo "RPM information" @@ -177,6 +249,9 @@ jobs: rpm -qp --requires "$RPM" | grep -i fuse || true + # ------------------------------------------------------- + # Upload RPM + # ------------------------------------------------------- - name: Upload RPM uses: actions/upload-artifact@v4 with: @@ -186,7 +261,7 @@ jobs: # ========================================================= - # Test the SAME RPM on RPM-based distributions + # Test SAME RPM on RPM-based distributions # ========================================================= rpm-test: name: ${{ matrix.name }} @@ -216,20 +291,75 @@ jobs: image: oraclelinux:9 steps: + # ------------------------------------------------------- + # Download RPM + # ------------------------------------------------------- - name: Download RPM uses: actions/download-artifact@v4 with: name: tuttle-rpm path: /tmp/tuttle + # ------------------------------------------------------- + # Verify downloaded RPM on host + # ------------------------------------------------------- + - name: Verify downloaded RPM + run: | + set -e + + echo "======================================" + echo "Downloaded RPM" + echo "======================================" + + find /tmp/tuttle \ + -type f \ + -name "*.rpm" \ + -print + + RPM_COUNT=$(find /tmp/tuttle \ + -type f \ + -name "*.rpm" \ + | wc -l) + + if [ "$RPM_COUNT" -eq 0 ]; then + echo "❌ FAIL: RPM artifact not found" + exit 1 + fi + + echo "✅ Found $RPM_COUNT RPM file(s)" + + # ------------------------------------------------------- + # Pull test image + # ------------------------------------------------------- + - name: Pull ${{ matrix.name }} image + env: + IMAGE: ${{ matrix.image }} + run: | + set -e + + echo "======================================" + echo "Pull Docker image" + echo "======================================" + + echo "Image: $IMAGE" + + docker pull "$IMAGE" + + echo "✅ Docker image pulled successfully" + + # ------------------------------------------------------- + # Test RPM + # ------------------------------------------------------- - name: Test RPM on ${{ matrix.name }} env: IMAGE: ${{ matrix.image }} run: | + set -e + docker run --rm \ -v "/tmp/tuttle:/tmp/tuttle:ro" \ "$IMAGE" \ - bash -c ' + bash -lc ' set -e echo "======================================" @@ -246,15 +376,26 @@ jobs: dnf install -y \ rpm \ dnf \ - ca-certificates + ca-certificates \ + findutils - RPM=$(find /tmp/tuttle -type f -name "*.rpm" | head -n 1) + echo + echo "======================================" + echo "Locate RPM" + echo "======================================" + + RPM=$(find /tmp/tuttle \ + -type f \ + -name "*.rpm" \ + | head -n 1) if [ -z "$RPM" ]; then echo "❌ FAIL: RPM not found" exit 1 fi + echo "RPM: $RPM" + echo echo "======================================" echo "RPM information" @@ -278,106 +419,193 @@ jobs: echo echo "======================================" - echo "Testing installation" + echo "Testing RPM installation" echo "======================================" dnf install -y "$RPM" + + echo echo "======================================" echo "Verify Tuttle RPM installation" echo "======================================" - + echo "RPM package status:" - rpm -q tuttle || true - - echo "" + rpm -q tuttle + + echo echo "Installed files:" - rpm -ql tuttle || true - - echo "" - echo "Tuttle executables:" - rpm -ql tuttle | grep -Ei 'tuttle|/bin/' || true - - echo "" + rpm -ql tuttle + + echo + echo "Tuttle-related files:" + rpm -ql tuttle | grep -Ei "tuttle|/bin/" || true + + echo echo "Searching filesystem:" - find /usr /opt -iname '*tuttle*' -type f 2>/dev/null || true + find /usr /opt \ + -iname "*tuttle*" \ + -type f \ + 2>/dev/null || true + echo echo "======================================" - echo "Verify installation" + echo "Verify package database" echo "======================================" rpm -qa | grep -i "^tuttle" echo echo "======================================" - echo "Install Xvfb (virtual display)" + echo "Install Xvfb" echo "======================================" - dnf install -y xorg-x11-server-Xvfb + dnf install -y \ + xorg-x11-server-Xvfb \ + procps-ng \ + which echo echo "======================================" - echo "Locate app binary" + echo "Locate application binary" echo "======================================" - BINARY=$(rpm -ql tuttle | grep -E "^/usr/bin/|^/opt/.*/[Tt]uttle$" | head -n 1) + BINARY="" + + # First try normal executable locations + for candidate in \ + /usr/bin/tuttle \ + /usr/bin/Tuttle \ + /opt/tuttle/tuttle \ + /opt/Tuttle/Tuttle \ + /opt/Tuttle/tuttle + do + if [ -x "$candidate" ]; then + BINARY="$candidate" + break + fi + done + # If not found, search RPM file list if [ -z "$BINARY" ]; then - echo "❌ FAIL: Could not locate app binary" + BINARY=$(rpm -ql tuttle \ + | grep -E "/(tuttle|Tuttle)$" \ + | head -n 1 || true) + fi + + if [ -z "$BINARY" ]; then + echo "❌ FAIL: Could not locate Tuttle executable" + + echo + echo "Complete RPM file list:" rpm -ql tuttle + exit 1 fi echo "Binary: $BINARY" + if [ ! -x "$BINARY" ]; then + echo "❌ FAIL: Located file is not executable" + ls -la "$BINARY" + exit 1 + fi + + echo + echo "======================================" + echo "Binary information" + echo "======================================" + + file "$BINARY" + + echo + echo "======================================" + echo "Check shared libraries" + echo "======================================" + + if command -v ldd >/dev/null 2>&1; then + ldd "$BINARY" || true + fi + echo echo "======================================" - echo "Smoke test app under Xvfb (display)" + echo "Smoke test app under Xvfb" echo "======================================" rm -rf /tmp/crash-reports mkdir -p /tmp/crash-reports + rm -f /tmp/app-stdout.log + set +e - xvfb-run --auto-servernum --server-args="-screen 0 1280x1024x24" \ - timeout 20s "$BINARY" \ - --no-sandbox \ - --disable-gpu \ - --crash-dumps-dir=/tmp/crash-reports \ - > /tmp/app-stdout.log 2>&1 + + xvfb-run \ + --auto-servernum \ + --server-args="-screen 0 1280x1024x24" \ + timeout 20s \ + "$BINARY" \ + --no-sandbox \ + --disable-gpu \ + --disable-dev-shm-usage \ + --crash-dumps-dir=/tmp/crash-reports \ + > /tmp/app-stdout.log 2>&1 + APP_EXIT=$? + set -e + echo echo "--- App stdout/stderr ---" cat /tmp/app-stdout.log || true echo echo "======================================" - echo "Check for crash artifacts" + echo "Check crash artifacts" echo "======================================" - CRASH_FILES=$(find /tmp/crash-reports -type f 2>/dev/null | wc -l) - CORE_FILES=$(find / -maxdepth 2 -name "core*" -newer /tmp/app-stdout.log 2>/dev/null | wc -l) + CRASH_FILES=$(find /tmp/crash-reports \ + -type f \ + 2>/dev/null \ + | wc -l) + + CORE_FILES=$(find / \ + -maxdepth 3 \ + -name "core*" \ + -type f \ + 2>/dev/null \ + | wc -l) echo "Crash dump files: $CRASH_FILES" echo "Core files: $CORE_FILES" echo "App exit code: $APP_EXIT" - # Exit code 124 = timeout (expected for a long-running GUI app - # that launched fine and had to be killed) -- treat as success. + echo + echo "======================================" + echo "Evaluate application result" + echo "======================================" + + # 124 means timeout killed the process. + # This is expected if the GUI launched successfully + # and continued running for 20 seconds. if [ "$APP_EXIT" -ne 0 ] && [ "$APP_EXIT" -ne 124 ]; then - echo "❌ FAIL: App exited abnormally (code $APP_EXIT)" + echo "❌ FAIL: App exited abnormally" + echo "Exit code: $APP_EXIT" exit 1 fi - if [ "$CRASH_FILES" -gt 0 ] || [ "$CORE_FILES" -gt 0 ]; then - echo "❌ FAIL: Crash artifacts detected" + if [ "$CRASH_FILES" -gt 0 ]; then + echo "❌ FAIL: Crash dump files detected" + find /tmp/crash-reports -type f -print exit 1 fi - echo "✅ PASS: No crash on launch (${{ matrix.name }})" + if [ "$CORE_FILES" -gt 0 ]; then + echo "❌ FAIL: Core dump files detected" + exit 1 + fi echo echo "======================================" - echo "✅ PASS: ${{ matrix.name }}" + echo "✅ PASS: No crash on launch" + echo "Distribution: ${{ matrix.name }}" echo "======================================" ' From 7a18450836549bbc5307ce7f9cd5dedfa5d94e02 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Fri, 14 Aug 2026 11:54:29 +0530 Subject: [PATCH 11/16] Refactor RPM build workflow for clarity and error handling Updated the RPM build workflow for better error handling and clarity. Enhanced comments and organized steps for improved readability. --- .github/workflows/rpm-compatibility.yml | 471 +++++++++++++++++++++--- 1 file changed, 412 insertions(+), 59 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index d50c7e10..e80a9b56 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -4,14 +4,16 @@ on: workflow_dispatch: jobs: + # ========================================================= - # Build the REAL Tuttle RPM from source on Fedora 44 + # BUILD REAL TUTTLE RPM # ========================================================= build-rpm: name: Build RPM on Fedora 44 runs-on: ubuntu-latest steps: + # ------------------------------------------------------- # Checkout # ------------------------------------------------------- @@ -23,7 +25,7 @@ jobs: # ------------------------------------------------------- - name: Build Tuttle RPM on Fedora 44 run: | - set -e + set -Eeuo pipefail echo "======================================" echo "Pull Fedora 44" @@ -36,11 +38,13 @@ jobs: echo "======================================" docker run --rm \ + --privileged \ -v "$GITHUB_WORKSPACE:/workspace" \ -w /workspace \ fedora:44 \ bash -lc ' - set -e + + set -Eeuo pipefail echo "======================================" echo "Operating System" @@ -48,6 +52,13 @@ jobs: cat /etc/os-release + echo + echo "======================================" + echo "Architecture" + echo "======================================" + + uname -m + echo echo "======================================" echo "Install system dependencies" @@ -68,7 +79,9 @@ jobs: ca-certificates \ tar \ gzip \ - findutils + findutils \ + which \ + file echo echo "======================================" @@ -176,6 +189,64 @@ jobs: fi echo + echo "======================================" + echo "RPM metadata" + echo "======================================" + + for RPM in release/*.rpm; do + + echo + echo "--------------------------------------" + echo "RPM: $RPM" + echo "--------------------------------------" + + rpm -qip "$RPM" + + echo + echo "Package name:" + rpm -qp --qf "%{NAME}\n" "$RPM" + + echo "Version:" + rpm -qp --qf "%{VERSION}\n" "$RPM" + + echo "Release:" + rpm -qp --qf "%{RELEASE}\n" "$RPM" + + echo "Architecture:" + rpm -qp --qf "%{ARCH}\n" "$RPM" + + done + + echo + echo "======================================" + echo "RPM scriptlets" + echo "======================================" + + for RPM in release/*.rpm; do + echo + echo "--------------------------------------" + echo "Scripts in: $RPM" + echo "--------------------------------------" + + rpm -qp --scripts "$RPM" || true + done + + echo + echo "======================================" + echo "RPM dependency check" + echo "======================================" + + for RPM in release/*.rpm; do + echo + echo "Dependencies for $RPM:" + rpm -qp --requires "$RPM" || true + done + + echo + echo "======================================" + echo "RPM build completed" + echo "======================================" + echo "✅ Successfully generated $RPM_COUNT RPM file(s)" ' @@ -184,7 +255,7 @@ jobs: # ------------------------------------------------------- - name: Verify RPM was generated run: | - set -e + set -Eeuo pipefail echo "======================================" echo "Generated RPM" @@ -195,29 +266,42 @@ jobs: -name "*.rpm" \ -print - RPM_COUNT=$(find ui/release -type f -name "*.rpm" | wc -l) + RPM_COUNT=$(find ui/release \ + -type f \ + -name "*.rpm" \ + | wc -l) if [ "$RPM_COUNT" -eq 0 ]; then echo "❌ FAIL: No RPM generated" exit 1 fi + echo + echo "Found RPM files:" + find ui/release \ + -type f \ + -name "*.rpm" \ + -print + + echo echo "✅ Found $RPM_COUNT RPM file(s)" # ------------------------------------------------------- - # Install RPM tool on GitHub runner + # Install RPM inspection tools # ------------------------------------------------------- - name: Install RPM inspection tools run: | + set -Eeuo pipefail + sudo apt-get update sudo apt-get install -y rpm # ------------------------------------------------------- # Inspect RPM # ------------------------------------------------------- - - name: Inspect RPM dependencies + - name: Inspect RPM run: | - set -e + set -Eeuo pipefail RPM=$(find ui/release \ -type f \ @@ -235,6 +319,23 @@ jobs: rpm -qip "$RPM" + echo + echo "======================================" + echo "Package identity" + echo "======================================" + + echo "Name:" + rpm -qp --qf "%{NAME}\n" "$RPM" + + echo "Version:" + rpm -qp --qf "%{VERSION}\n" "$RPM" + + echo "Release:" + rpm -qp --qf "%{RELEASE}\n" "$RPM" + + echo "Architecture:" + rpm -qp --qf "%{ARCH}\n" "$RPM" + echo echo "======================================" echo "RPM dependencies" @@ -242,6 +343,13 @@ jobs: rpm -qp --requires "$RPM" + echo + echo "======================================" + echo "RPM scripts" + echo "======================================" + + rpm -qp --scripts "$RPM" || true + echo echo "======================================" echo "FUSE dependencies" @@ -261,9 +369,10 @@ jobs: # ========================================================= - # Test SAME RPM on RPM-based distributions + # TEST SAME RPM ON RPM DISTRIBUTIONS # ========================================================= rpm-test: + name: ${{ matrix.name }} needs: build-rpm @@ -274,7 +383,9 @@ jobs: fail-fast: false matrix: + include: + - name: Fedora 44 image: fedora:44 @@ -290,7 +401,9 @@ jobs: - name: Oracle Linux 9 image: oraclelinux:9 + steps: + # ------------------------------------------------------- # Download RPM # ------------------------------------------------------- @@ -301,11 +414,11 @@ jobs: path: /tmp/tuttle # ------------------------------------------------------- - # Verify downloaded RPM on host + # Verify downloaded RPM # ------------------------------------------------------- - name: Verify downloaded RPM run: | - set -e + set -Eeuo pipefail echo "======================================" echo "Downloaded RPM" @@ -328,14 +441,16 @@ jobs: echo "✅ Found $RPM_COUNT RPM file(s)" + # ------------------------------------------------------- # Pull test image # ------------------------------------------------------- - name: Pull ${{ matrix.name }} image env: IMAGE: ${{ matrix.image }} + run: | - set -e + set -Eeuo pipefail echo "======================================" echo "Pull Docker image" @@ -347,20 +462,29 @@ jobs: echo "✅ Docker image pulled successfully" + # ------------------------------------------------------- # Test RPM # ------------------------------------------------------- - name: Test RPM on ${{ matrix.name }} env: IMAGE: ${{ matrix.image }} + run: | - set -e + + set -Eeuo pipefail + + echo "======================================" + echo "Starting privileged test container" + echo "======================================" docker run --rm \ + --privileged \ -v "/tmp/tuttle:/tmp/tuttle:ro" \ "$IMAGE" \ bash -lc ' - set -e + + set -Eeuo pipefail echo "======================================" echo "Operating System" @@ -368,6 +492,13 @@ jobs: cat /etc/os-release + echo + echo "======================================" + echo "Architecture" + echo "======================================" + + uname -m + echo echo "======================================" echo "Install RPM tools" @@ -377,7 +508,12 @@ jobs: rpm \ dnf \ ca-certificates \ - findutils + findutils \ + which \ + file \ + procps-ng \ + xorg-x11-server-Xvfb \ + fuse-libs echo echo "======================================" @@ -403,6 +539,38 @@ jobs: rpm -qip "$RPM" + echo + echo "======================================" + echo "RPM package identity" + echo "======================================" + + PACKAGE_NAME=$(rpm -qp --qf "%{NAME}" "$RPM") + PACKAGE_VERSION=$(rpm -qp --qf "%{VERSION}" "$RPM") + PACKAGE_RELEASE=$(rpm -qp --qf "%{RELEASE}" "$RPM") + PACKAGE_ARCH=$(rpm -qp --qf "%{ARCH}" "$RPM") + + echo "Package: $PACKAGE_NAME" + echo "Version: $PACKAGE_VERSION" + echo "Release: $PACKAGE_RELEASE" + echo "Architecture: $PACKAGE_ARCH" + + echo + echo "======================================" + echo "Validate architecture" + echo "======================================" + + CURRENT_ARCH=$(uname -m) + + echo "Host architecture: $CURRENT_ARCH" + echo "RPM architecture: $PACKAGE_ARCH" + + if [ "$CURRENT_ARCH" = "x86_64" ] && [ "$PACKAGE_ARCH" != "x86_64" ]; then + echo "❌ FAIL: RPM architecture does not match runner" + exit 1 + fi + + echo "✅ Architecture is compatible" + echo echo "======================================" echo "RPM dependencies" @@ -412,96 +580,235 @@ jobs: echo echo "======================================" - echo "FUSE dependencies" + echo "RPM scripts BEFORE installation" echo "======================================" - rpm -qp --requires "$RPM" | grep -i fuse || true + rpm -qp --scripts "$RPM" || true + + echo + echo "======================================" + echo "Check unshare capability" + echo "======================================" + + if command -v unshare >/dev/null 2>&1; then + + echo "unshare binary:" + command -v unshare + + echo + echo "Testing namespace creation..." + + if unshare --mount true >/dev/null 2>&1; then + echo "✅ unshare works" + else + echo "⚠️ unshare is restricted" + echo "Container is privileged, but this runtime still restricts namespace creation." + fi + + else + + echo "Installing util-linux..." + + dnf install -y util-linux + + if unshare --mount true >/dev/null 2>&1; then + echo "✅ unshare works" + else + echo "⚠️ unshare is restricted" + fi + + fi echo echo "======================================" echo "Testing RPM installation" echo "======================================" + set +e + dnf install -y "$RPM" + INSTALL_EXIT=$? + + set -e + + echo + echo "dnf exit code: $INSTALL_EXIT" + + if [ "$INSTALL_EXIT" -ne 0 ]; then + echo "❌ FAIL: RPM installation failed" + + echo + echo "Package database:" + rpm -qa | grep -i tuttle || true + + exit "$INSTALL_EXIT" + fi + + echo "✅ dnf reported successful installation" + echo echo "======================================" - echo "Verify Tuttle RPM installation" + echo "Verify package by detected name" echo "======================================" - echo "RPM package status:" - rpm -q tuttle + if rpm -q "$PACKAGE_NAME" >/dev/null 2>&1; then + echo "✅ Package is installed:" + rpm -q "$PACKAGE_NAME" + else + echo "❌ FAIL: Package was not installed" + echo "Expected package: $PACKAGE_NAME" - echo - echo "Installed files:" - rpm -ql tuttle + echo + echo "Installed Tuttle packages:" + rpm -qa | grep -i tuttle || true + + exit 1 + fi echo - echo "Tuttle-related files:" - rpm -ql tuttle | grep -Ei "tuttle|/bin/" || true + echo "======================================" + echo "Installed package files" + echo "======================================" + + rpm -ql "$PACKAGE_NAME" echo - echo "Searching filesystem:" - find /usr /opt \ - -iname "*tuttle*" \ - -type f \ - 2>/dev/null || true + echo "======================================" + echo "Tuttle-related installed files" + echo "======================================" + + rpm -ql "$PACKAGE_NAME" \ + | grep -Ei "tuttle|/bin/|\.desktop$" \ + || true echo echo "======================================" echo "Verify package database" echo "======================================" - rpm -qa | grep -i "^tuttle" + rpm -qa | grep -i tuttle || true echo echo "======================================" - echo "Install Xvfb" + echo "Install additional runtime dependencies" echo "======================================" dnf install -y \ xorg-x11-server-Xvfb \ procps-ng \ - which + which \ + file echo echo "======================================" - echo "Locate application binary" + echo "Locate application executable" echo "======================================" BINARY="" - # First try normal executable locations - for candidate in \ - /usr/bin/tuttle \ - /usr/bin/Tuttle \ - /opt/tuttle/tuttle \ - /opt/Tuttle/Tuttle \ - /opt/Tuttle/tuttle - do - if [ -x "$candidate" ]; then - BINARY="$candidate" - break + # ------------------------------------------------- + # First inspect files registered by RPM + # ------------------------------------------------- + + while IFS= read -r FILE; do + + if [ -f "$FILE" ] && [ -x "$FILE" ]; then + + BASENAME=$(basename "$FILE") + + case "$BASENAME" in + + tuttle|Tuttle|tuttle-ui|TuttleUI) + BINARY="$FILE" + break + ;; + + esac + fi - done - # If not found, search RPM file list + done < <(rpm -ql "$PACKAGE_NAME") + + # ------------------------------------------------- + # Search standard executable locations + # ------------------------------------------------- + if [ -z "$BINARY" ]; then - BINARY=$(rpm -ql tuttle \ - | grep -E "/(tuttle|Tuttle)$" \ + + for candidate in \ + /usr/bin/tuttle \ + /usr/bin/Tuttle \ + /usr/bin/tuttle-ui \ + /usr/bin/TuttleUI \ + /opt/tuttle/tuttle \ + /opt/Tuttle/Tuttle \ + /opt/Tuttle/tuttle + + do + + if [ -x "$candidate" ]; then + BINARY="$candidate" + break + fi + + done + + fi + + # ------------------------------------------------- + # Search filesystem if still not found + # ------------------------------------------------- + + if [ -z "$BINARY" ]; then + + echo "Standard binary locations failed." + + echo + echo "Searching filesystem..." + + BINARY=$(find /usr /opt \ + -type f \ + -perm /111 \ + \( \ + -iname "tuttle" \ + -o \ + -iname "tuttle-ui" \ + -o \ + -iname "Tuttle" \ + -o \ + -iname "TuttleUI" \ + \) \ + 2>/dev/null \ | head -n 1 || true) + fi if [ -z "$BINARY" ]; then + + echo echo "❌ FAIL: Could not locate Tuttle executable" echo echo "Complete RPM file list:" - rpm -ql tuttle + rpm -ql "$PACKAGE_NAME" + + echo + echo "Tuttle files on filesystem:" + find /usr /opt \ + -iname "*tuttle*" \ + 2>/dev/null \ + || true exit 1 + fi + echo + echo "======================================" + echo "Executable found" + echo "======================================" + echo "Binary: $BINARY" if [ ! -x "$BINARY" ]; then @@ -517,15 +824,40 @@ jobs: file "$BINARY" + echo + echo "Permissions:" + ls -la "$BINARY" + echo echo "======================================" echo "Check shared libraries" echo "======================================" if command -v ldd >/dev/null 2>&1; then + ldd "$BINARY" || true + + echo + echo "Missing libraries:" + + ldd "$BINARY" 2>/dev/null \ + | grep "not found" \ + || echo "No missing shared libraries detected" + fi + echo + echo "======================================" + echo "Electron application diagnostics" + echo "======================================" + + echo "Electron-related files:" + + rpm -ql "$PACKAGE_NAME" \ + | grep -Ei \ + "electron|chrome|chromium|resources|app.asar" \ + || true + echo echo "======================================" echo "Smoke test app under Xvfb" @@ -555,6 +887,7 @@ jobs: echo echo "--- App stdout/stderr ---" + cat /tmp/app-stdout.log || true echo @@ -575,37 +908,57 @@ jobs: | wc -l) echo "Crash dump files: $CRASH_FILES" - echo "Core files: $CORE_FILES" - echo "App exit code: $APP_EXIT" + echo "Core files: $CORE_FILES" + echo "App exit code: $APP_EXIT" echo echo "======================================" echo "Evaluate application result" echo "======================================" - # 124 means timeout killed the process. - # This is expected if the GUI launched successfully - # and continued running for 20 seconds. + # 124 = timeout. + # This is acceptable because GUI applications normally + # continue running. + if [ "$APP_EXIT" -ne 0 ] && [ "$APP_EXIT" -ne 124 ]; then + echo "❌ FAIL: App exited abnormally" echo "Exit code: $APP_EXIT" + exit 1 + fi if [ "$CRASH_FILES" -gt 0 ]; then + echo "❌ FAIL: Crash dump files detected" - find /tmp/crash-reports -type f -print + + find /tmp/crash-reports \ + -type f \ + -print + exit 1 + fi if [ "$CORE_FILES" -gt 0 ]; then + echo "❌ FAIL: Core dump files detected" + exit 1 + fi echo echo "======================================" - echo "✅ PASS: No crash on launch" - echo "Distribution: ${{ matrix.name }}" + echo "✅ PASS: RPM installed and app did not crash" echo "======================================" + + echo "Distribution: ${{ matrix.name }}" + echo "Package: $PACKAGE_NAME" + echo "Version: $PACKAGE_VERSION" + echo "Release: $PACKAGE_RELEASE" + echo "Architecture: $PACKAGE_ARCH" + echo "Binary: $BINARY" + ' From 84961562240ebc5209f45f5107371d7961100bfe Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Fri, 14 Aug 2026 12:09:29 +0530 Subject: [PATCH 12/16] Add 'nspr' as a dependency in package.json --- ui/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/package.json b/ui/package.json index aa108706..3367f060 100644 --- a/ui/package.json +++ b/ui/package.json @@ -84,7 +84,8 @@ "rpm": { "depends": [ "zlib", - "fuse-libs" + "fuse-libs", + "nspr" ] } }, From b6ebe3146e5e9da8bea668c3f88b210dbd8fa66a Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Fri, 14 Aug 2026 12:18:01 +0530 Subject: [PATCH 13/16] Add dependencies for RPM packaging Added additional dependencies for RPM packaging. --- ui/package.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui/package.json b/ui/package.json index 3367f060..87ddeb7e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -85,7 +85,15 @@ "depends": [ "zlib", "fuse-libs", - "nspr" + "nspr", + "gtk3", + "libnotify", + "nss", + "libXScrnSaver", + "libXtst", + "xdg-utils", + "at-spi2-core", + "libuuid" ] } }, From 4dab0b32a4d63e6e86bcb716c6fe359f8d3036b5 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Fri, 14 Aug 2026 14:53:25 +0530 Subject: [PATCH 14/16] Enhance RPM compatibility workflow diagnostics Refactor RPM compatibility workflow to improve diagnostics and dependency checks. Removed unnecessary checks and added specific dependency verifications for NSS and NSPR. --- .github/workflows/rpm-compatibility.yml | 204 ++++++++++++++++-------- 1 file changed, 139 insertions(+), 65 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index e80a9b56..06632886 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -223,12 +223,14 @@ jobs: echo "======================================" for RPM in release/*.rpm; do + echo echo "--------------------------------------" echo "Scripts in: $RPM" echo "--------------------------------------" rpm -qp --scripts "$RPM" || true + done echo @@ -237,9 +239,11 @@ jobs: echo "======================================" for RPM in release/*.rpm; do + echo echo "Dependencies for $RPM:" rpm -qp --requires "$RPM" || true + done echo @@ -278,6 +282,7 @@ jobs: echo echo "Found RPM files:" + find ui/release \ -type f \ -name "*.rpm" \ @@ -383,7 +388,6 @@ jobs: fail-fast: false matrix: - include: - name: Fedora 44 @@ -513,7 +517,8 @@ jobs: file \ procps-ng \ xorg-x11-server-Xvfb \ - fuse-libs + fuse-libs \ + util-linux echo echo "======================================" @@ -564,7 +569,8 @@ jobs: echo "Host architecture: $CURRENT_ARCH" echo "RPM architecture: $PACKAGE_ARCH" - if [ "$CURRENT_ARCH" = "x86_64" ] && [ "$PACKAGE_ARCH" != "x86_64" ]; then + if [ "$CURRENT_ARCH" = "x86_64" ] && + [ "$PACKAGE_ARCH" != "x86_64" ]; then echo "❌ FAIL: RPM architecture does not match runner" exit 1 fi @@ -580,44 +586,26 @@ jobs: echo echo "======================================" - echo "RPM scripts BEFORE installation" + echo "Check important Electron dependencies" echo "======================================" - rpm -qp --scripts "$RPM" || true + echo "NSS dependency:" + rpm -qp --requires "$RPM" \ + | grep -Ei "nss|libnss" \ + || echo "⚠️ NSS dependency not explicitly listed" + + echo + echo "NSPR dependency:" + rpm -qp --requires "$RPM" \ + | grep -Ei "nspr|libnspr" \ + || echo "⚠️ NSPR dependency not explicitly listed" echo echo "======================================" - echo "Check unshare capability" + echo "RPM scripts BEFORE installation" echo "======================================" - if command -v unshare >/dev/null 2>&1; then - - echo "unshare binary:" - command -v unshare - - echo - echo "Testing namespace creation..." - - if unshare --mount true >/dev/null 2>&1; then - echo "✅ unshare works" - else - echo "⚠️ unshare is restricted" - echo "Container is privileged, but this runtime still restricts namespace creation." - fi - - else - - echo "Installing util-linux..." - - dnf install -y util-linux - - if unshare --mount true >/dev/null 2>&1; then - echo "✅ unshare works" - else - echo "⚠️ unshare is restricted" - fi - - fi + rpm -qp --scripts "$RPM" || true echo echo "======================================" @@ -636,6 +624,7 @@ jobs: echo "dnf exit code: $INSTALL_EXIT" if [ "$INSTALL_EXIT" -ne 0 ]; then + echo "❌ FAIL: RPM installation failed" echo @@ -643,6 +632,7 @@ jobs: rpm -qa | grep -i tuttle || true exit "$INSTALL_EXIT" + fi echo "✅ dnf reported successful installation" @@ -653,9 +643,12 @@ jobs: echo "======================================" if rpm -q "$PACKAGE_NAME" >/dev/null 2>&1; then + echo "✅ Package is installed:" rpm -q "$PACKAGE_NAME" + else + echo "❌ FAIL: Package was not installed" echo "Expected package: $PACKAGE_NAME" @@ -664,6 +657,7 @@ jobs: rpm -qa | grep -i tuttle || true exit 1 + fi echo @@ -691,7 +685,7 @@ jobs: echo echo "======================================" - echo "Install additional runtime dependencies" + echo "Install Xvfb" echo "======================================" dnf install -y \ @@ -720,6 +714,7 @@ jobs: case "$BASENAME" in tuttle|Tuttle|tuttle-ui|TuttleUI) + BINARY="$FILE" break ;; @@ -730,6 +725,7 @@ jobs: done < <(rpm -ql "$PACKAGE_NAME") + # ------------------------------------------------- # Search standard executable locations # ------------------------------------------------- @@ -748,14 +744,17 @@ jobs: do if [ -x "$candidate" ]; then + BINARY="$candidate" break + fi done fi + # ------------------------------------------------- # Search filesystem if still not found # ------------------------------------------------- @@ -784,6 +783,7 @@ jobs: fi + if [ -z "$BINARY" ]; then echo @@ -804,6 +804,7 @@ jobs: fi + echo echo "======================================" echo "Executable found" @@ -812,11 +813,16 @@ jobs: echo "Binary: $BINARY" if [ ! -x "$BINARY" ]; then + echo "❌ FAIL: Located file is not executable" + ls -la "$BINARY" + exit 1 + fi + echo echo "======================================" echo "Binary information" @@ -828,24 +834,71 @@ jobs: echo "Permissions:" ls -la "$BINARY" + echo echo "======================================" echo "Check shared libraries" echo "======================================" - if command -v ldd >/dev/null 2>&1; then + echo "Running ldd..." - ldd "$BINARY" || true + ldd "$BINARY" | tee /tmp/tuttle-ldd.txt || true - echo - echo "Missing libraries:" + echo + echo "======================================" + echo "Missing shared libraries" + echo "======================================" + + MISSING_LIBS=$(grep "not found" \ + /tmp/tuttle-ldd.txt \ + || true) - ldd "$BINARY" 2>/dev/null \ - | grep "not found" \ - || echo "No missing shared libraries detected" + if [ -n "$MISSING_LIBS" ]; then + + echo "❌ FAIL: Missing shared libraries detected:" + echo "$MISSING_LIBS" + + exit 1 fi + echo "✅ No missing shared libraries" + + + echo + echo "======================================" + echo "Check NSPR" + echo "======================================" + + if ldconfig -p 2>/dev/null \ + | grep -q "libnspr4.so"; then + + echo "✅ libnspr4.so available" + + else + + echo "⚠️ libnspr4.so not found in ldconfig" + + fi + + + echo + echo "======================================" + echo "Check NSS" + echo "======================================" + + if ldconfig -p 2>/dev/null \ + | grep -q "libnss3.so"; then + + echo "✅ libnss3.so available" + + else + + echo "⚠️ libnss3.so not found in ldconfig" + + fi + + echo echo "======================================" echo "Electron application diagnostics" @@ -856,7 +909,8 @@ jobs: rpm -ql "$PACKAGE_NAME" \ | grep -Ei \ "electron|chrome|chromium|resources|app.asar" \ - || true + || true + echo echo "======================================" @@ -885,11 +939,13 @@ jobs: set -e + echo echo "--- App stdout/stderr ---" cat /tmp/app-stdout.log || true + echo echo "======================================" echo "Check crash artifacts" @@ -900,38 +956,59 @@ jobs: 2>/dev/null \ | wc -l) - CORE_FILES=$(find / \ - -maxdepth 3 \ - -name "core*" \ - -type f \ - 2>/dev/null \ - | wc -l) - echo "Crash dump files: $CRASH_FILES" - echo "Core files: $CORE_FILES" echo "App exit code: $APP_EXIT" + + echo + echo "======================================" + echo "DBus messages" + echo "======================================" + + if grep -qi "dbus" /tmp/app-stdout.log; then + + echo "ℹ️ DBus messages detected." + echo "These are ignored for this container smoke test." + + else + + echo "No DBus messages detected." + + fi + + echo echo "======================================" echo "Evaluate application result" echo "======================================" - # 124 = timeout. - # This is acceptable because GUI applications normally - # continue running. + # ------------------------------------------------- + # Exit code 124 means timeout terminated the app + # after 20 seconds. + # + # This is EXPECTED for this smoke test. + # ------------------------------------------------- - if [ "$APP_EXIT" -ne 0 ] && [ "$APP_EXIT" -ne 124 ]; then + if [ "$APP_EXIT" -ne 0 ] && + [ "$APP_EXIT" -ne 124 ]; then - echo "❌ FAIL: App exited abnormally" + echo "❌ FAIL: Tuttle exited abnormally" echo "Exit code: $APP_EXIT" exit 1 fi + + # ------------------------------------------------- + # ONLY check Tuttle-specific crash dumps. + # + # DO NOT search / for core* files. + # ------------------------------------------------- + if [ "$CRASH_FILES" -gt 0 ]; then - echo "❌ FAIL: Crash dump files detected" + echo "❌ FAIL: Tuttle crash dump files detected" find /tmp/crash-reports \ -type f \ @@ -941,17 +1018,14 @@ jobs: fi - if [ "$CORE_FILES" -gt 0 ]; then - - echo "❌ FAIL: Core dump files detected" - - exit 1 - - fi echo echo "======================================" - echo "✅ PASS: RPM installed and app did not crash" + echo "✅ PASS: RPM installed successfully" + echo "✅ PASS: Tuttle executable found" + echo "✅ PASS: Shared libraries available" + echo "✅ PASS: Tuttle launched under Xvfb" + echo "✅ PASS: No Tuttle crash dumps" echo "======================================" echo "Distribution: ${{ matrix.name }}" From b6e905648dbbf279d446e9aad82f32295ee78554 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Fri, 14 Aug 2026 15:04:56 +0530 Subject: [PATCH 15/16] Fix missing newline at end of rpm-compatibility.yml From d703b44d220d42d6fea477fa2aefec0f3f6fbc42 Mon Sep 17 00:00:00 2001 From: Arunmanikandan dev Date: Fri, 14 Aug 2026 16:04:02 +0530 Subject: [PATCH 16/16] Update rpm-compatibility.yml to remove Linux images Removed AlmaLinux 9 and Oracle Linux 9 from the workflow. --- .github/workflows/rpm-compatibility.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/rpm-compatibility.yml b/.github/workflows/rpm-compatibility.yml index 06632886..79414aeb 100644 --- a/.github/workflows/rpm-compatibility.yml +++ b/.github/workflows/rpm-compatibility.yml @@ -396,14 +396,9 @@ jobs: - name: Rocky Linux 9 image: rockylinux:9 - - name: AlmaLinux 9 - image: almalinux:9 - - name: CentOS Stream 9 image: quay.io/centos/centos:stream9 - - name: Oracle Linux 9 - image: oraclelinux:9 steps: