Skip to content

Fix virtual package parsing to prevent invalid cache entries#171

Draft
Copilot wants to merge 8 commits intomasterfrom
copilot/fix-3a5d64e3-6924-4fd5-bd1d-4f4014a65826
Draft

Fix virtual package parsing to prevent invalid cache entries#171
Copilot wants to merge 8 commits intomasterfrom
copilot/fix-3a5d64e3-6924-4fd5-bd1d-4f4014a65826

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Sep 30, 2025

Summary

Fixed the issue where APT virtual packages with no concrete providers caused invalid package names to be cached instead of failing with a clear error message.

Changes Made

  • Root Cause Analysis: Identified that virtual packages with no reverse provides (like python) return "Reverse Provides:" which gets parsed as "Reverse=Provides:" package
  • Core Fix: Enhanced getNonVirtualPackage function in src/internal/common/apt.go to detect and properly handle virtual packages with no providers
  • Error Handling: Action now fails with clear error message: "virtual package 'python' has no concrete package providers available"
  • Consolidate Logic: Added isVirtualPackage helper function to centralize virtual package detection logic
  • Fix Duplicate Messages: Removed redundant errMsgs = append(errMsgs, strings.Join(errMsgs, "\n")) line that was causing error messages to be duplicated
  • Test Coverage: Added comprehensive test case TestNormalizedList_VirtualPackageWithNoProviders_StderrsErrorMessage
  • Binary Updates: Rebuilt both x86 and ARM64 apt_query binaries with the fix
  • Verification: Confirmed end-to-end functionality:
    • ✅ Invalid virtual packages (e.g., python) now fail with clear error (shown once, not duplicated)
    • ✅ Valid packages continue to work normally
    • ✅ Virtual packages with providers (e.g., libz-devzlib1g-dev) resolve correctly

Design Decisions

The code already automatically installs concrete packages when virtual packages have providers (preserving efficiency). When no providers exist, it fails with a clear error message to inform users they need to specify a valid package name. This approach:

  1. Maintains efficiency by auto-resolving when possible
  2. Prevents silent failures by explicitly reporting when resolution is not possible
  3. Gives users clear, actionable feedback (without message duplication)

Impact

Users will no longer experience silent failures where invalid packages get cached. Instead, they'll receive immediate, actionable error messages (shown once, clearly) when using virtual packages that have no concrete implementations.

Original prompt

This section details on the original issue you should resolve

<issue_title>APT no-installation candidates for package still saves to cache rather than failing with clear error message.</issue_title>
<issue_description>I have a Github Action running daily on a private repo which tries to run some quick tests to verify an (extremely old) application is working. July 7th and prior ran fine before the latest update for the Google URL shortener removal, but July 8th and onward have failed (undetected by my checks, as my scripts were still reporting success even though the apt dependencies were not present. oops).

It seems to be failing because of the - Reverse=Provides: line is erroneously detecting as a package to install. E: Unable to locate package Reverse.

I have tried to update my Action to use Ubuntu v24.04 but unfortunately the application code I am running has not been touched since ~2019ish and thus there are build errors on newer Ubuntu versions that are a headache for another day. I am hoping there could be a quick fix for this so that I can continue caching my apt installs without having to touch ~30 year old C/C++ code 🙏.

Here is the relevant part of my ci.yml:

jobs:
  build-and-test:
    runs-on: ubuntu-22.04
    steps:
    - name: Checkout Repository
      uses: actions/checkout@v4
      with:
        fetch-depth: 0
        submodules: true

    - name: Install Packages
      uses: awalsh128/cache-apt-pkgs-action@latest
      with:
        packages: build-essential telnet expect git python bison \
          autoconf automake autogen libevent-dev libjemalloc-dev \
          default-libmysqlclient-dev libpcre3-dev libpq-dev libsqlite3-dev \
          libssl-dev libz-dev libgtest-dev
        version: 1.0
July 8th run

Run awalsh128/cache-apt-pkgs-action@latest
  with:
    packages: build-essential telnet expect git python bison \ autoconf automake autogen libevent-dev libjemalloc-dev \ default-libmysqlclient-dev libpcre3-dev libpq-dev libsqlite3-dev \ libssl-dev libz-dev libgtest-dev
    version: 1
    execute_install_scripts: false
    debug: false
Run ${GITHUB_ACTION_PATH}/pre_cache_action.sh \
  ${GITHUB_ACTION_PATH}/pre_cache_action.sh \
    ~/cache-apt-pkgs \
    "$VERSION" \
    "$EXEC_INSTALL_SCRIPTS" \
    "$DEBUG" \
    "$PACKAGES"
  echo "CACHE_KEY=$(cat ~/cache-apt-pkgs/cache_key.md5)" >> $GITHUB_ENV
  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
  env:
    VERSION: 1
    EXEC_INSTALL_SCRIPTS: false
    DEBUG: false
    PACKAGES: build-essential telnet expect git python bison \ autoconf automake autogen libevent-dev libjemalloc-dev \ default-libmysqlclient-dev libpcre3-dev libpq-dev libsqlite3-dev \ libssl-dev libz-dev libgtest-dev
Normalizing package list...
done
Validating action arguments (version='1', packages='Reverse=Provides: autoconf=2.71-2 autogen=1:5.18.16-4 automake=1:1.16.5-1.3 bison=2:3.8.2+dfsg-1build1 build-essential=12.9ubuntu3 default-libmysqlclient-dev=1.0.8 expect=5.45.4-2build1 git=1:2.49.0-2~ppa1~ubuntu22.04.1 libevent-dev=2.1.12-stable-1build3 libgtest-dev=1.11.0-3 libjemalloc-dev=5.2.1-4ubuntu1 libpcre3-dev=2:8.39-13ubuntu0.22.04.1 libpq-dev=17.5-1.pgdg22.04+1 libsqlite3-dev=3.37.2-2ubuntu0.4 libssl-dev=3.0.2-0ubuntu1.19 telnet=0.17-44build1')...
done

Creating cache key...
- Value to hash is 'Reverse=Provides: autoconf=2.71-2 autogen=1:5.18.16-4 automake=1:1.16.5-1.3 bison=2:3.8.2+dfsg-1build1 build-essential=12.9ubuntu3 default-libmysqlclient-dev=1.0.8 expect=5.45.4-2build1 git=1:2.49.0-2~ppa1~ubuntu22.04.1 libevent-dev=2.1.12-stable-1build3 libgtest-dev=1.11.0-3 libjemalloc-dev=5.2.1-4ubuntu1 libpcre3-dev=2:8.39-13ubuntu0.22.04.1 libpq-dev=17.5-1.pgdg22.04+1 libsqlite3-dev=3.37.2-2ubuntu0.4 libssl-dev=3.0.2-0ubuntu1.19 telnet=0.17-44build1 @ 1 3'.
- Value hashed as '68dff83ef6c4bb3671c78ab4e04a9cf1'.
done
Hash value written to /home/runner/cache-apt-pkgs/cache_key.md5
Run actions/cache/restore@v4
Cache not found for input keys: cache-apt-pkgs_68dff83ef6c4bb3671c78ab4e04a9cf1
Run ${GITHUB_ACTION_PATH}/post_cache_action.sh \
Updating APT package list...
done

Clean installing and caching 17 package(s).

Package list:
- Reverse=Provides:
- autoconf=2.71-2
- autogen=1:5.18.16-4
- automake=1:1.16.5-1.3
- bison=2:3.8.2+dfsg-1build1
- build-essential=12.9ubuntu3
- default-libmysqlclient-dev=1.0.8
- expect=5.45.4-2build1
- git=1:2.49.0-2~ppa1~ubuntu22.04.1
- libevent-dev=2.1.12-stable-1build3
- libgtest-dev=1.11.0-3
- libjemalloc-dev=5.2.1-4ubuntu1
- libpcre3-dev=2:8.39-13ubuntu0.22.04.1
- libpq-dev=17.5-1.pgdg22.04+1
- libsqlite3-dev=3.37.2-2ubuntu0.4
- libssl-dev=3.0.2-0ubuntu1.19
- telnet=0.17-44build1
Writing main packages manifest to /home/runner/cache-apt-pkgs/manifest_main.log...
done

Clean installing 17 packages...
E: Unable to locate package Reverse
[apt-fast 12:47:24]Package manager quit with exit code.
done
Installation log written to /home/runner/cache-apt-pkgs/install.log

Installed package list:

Caching 0...

</details>
Fixes awalsh128/cache-apt-pkgs-action#166

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click [here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start the survey.

Copilot AI and others added 4 commits September 30, 2025 07:31
Co-authored-by: awalsh128 <2087466+awalsh128@users.noreply.github.com>
Co-authored-by: awalsh128 <2087466+awalsh128@users.noreply.github.com>
Co-authored-by: awalsh128 <2087466+awalsh128@users.noreply.github.com>
Co-authored-by: awalsh128 <2087466+awalsh128@users.noreply.github.com>
Copilot AI changed the title [WIP] APT no-installation candidates for package still saves to cache rather than failing with clear error message. Fix virtual package parsing to prevent invalid cache entries Sep 30, 2025
Copilot AI requested a review from awalsh128 September 30, 2025 07:38
}

// Check if the output is just "Reverse Provides:" with no actual package info
trimmedOutput := strings.TrimSpace(execution.CombinedOut)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other code locations where virtual packages are evaluated. Consolidate this logic and how it is reported.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidated virtual package detection by introducing isVirtualPackage helper function (commit 49b6053). This centralizes the logic for detecting "as it is purely virtual" messages and makes the code more maintainable.

Comment thread src/internal/common/apt.go Outdated
// Check if the output is just "Reverse Provides:" with no actual package info
trimmedOutput := strings.TrimSpace(execution.CombinedOut)
if trimmedOutput == "Reverse Provides:" {
return pkg, fmt.Errorf("virtual package '%s' has no concrete package providers", name)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we lose efficiency if the code automatically gets a concrete package related to it and installs that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code already automatically resolves virtual packages to concrete ones when providers are available (e.g., libz-devzlib1g-dev), preserving efficiency. When no providers exist (e.g., python on Ubuntu 24.04), it fails with a clear error message. This prevents silent failures while maintaining efficiency for resolvable virtual packages.

@awalsh128 awalsh128 removed their assignment Sep 30, 2025
@awalsh128
Copy link
Copy Markdown
Owner

@copilot Please continue working on this PR.

Co-authored-by: awalsh128 <2087466+awalsh128@users.noreply.github.com>
Copilot AI requested a review from awalsh128 October 1, 2025 01:43
Comment on lines +16 to +18
2025/09/30 07:33:27 Encountered error resolving some or all package names, see combined std[out,err] below.
virtual package 'python' has no concrete package providers
virtual package 'python' has no concrete package providers
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the duplicate message due to message "virtual package 'python' has no concrete package providers" being output to stdout and stderr? If so, why? If not, provide an explaination.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The duplicate message was caused by a bug in GetAptPackages (line 131 in apt.go). The line errMsgs = append(errMsgs, strings.Join(errMsgs, "\n")) was appending all error messages back to the slice, then line 138 joined them again, creating duplicates. Fixed in commit c08f9f0 by removing the redundant line 131.

@awalsh128
Copy link
Copy Markdown
Owner

@copilot Please continue working on this PR.

Co-authored-by: awalsh128 <2087466+awalsh128@users.noreply.github.com>
Copilot AI requested a review from awalsh128 October 4, 2025 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants