From dfb27081dc172056668a65d1f6e7d5dda8675774 Mon Sep 17 00:00:00 2001 From: Mahyar McDonald Date: Mon, 3 Nov 2025 15:53:06 -0800 Subject: [PATCH] fix some package hash getting bad input? --- README.md | 8 +++++--- action.yml | 2 +- lib.sh | 8 ++++++-- src/internal/common/apt.go | 23 ++++++++++++++++++++--- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e189feb..b1f3f0f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ There are three kinds of version labels you can use. - `execute_install_scripts` - Execute Debian package pre and post install script upon restore. See [Caveats / Non-file Dependencies](#non-file-dependencies) for more information. - `empty_packages_behavior` - Desired behavior when the given `packages` is empty. `'error'` (default), `'warn'` or `'ignore'`. - `add-repository` - Space delimited list of repositories to add via `apt-add-repository` before installing packages. Supports PPA (e.g., `ppa:user/repo`) and other repository formats. -- `use_aptfile` - Whether to read packages from `Aptfile` at repository root. Set to `false` to disable Aptfile usage even if `Aptfile` exists. Default is `true`. +- `use_aptfile` - Whether to read packages from `Aptfile` at repository root. Set to `true` to enable Aptfile usage if `Aptfile` exists. Default is `false`. ### Outputs @@ -124,7 +124,7 @@ install_from_multiple_repos: ### Using Aptfile -You can also use an `Aptfile` at your repository root to specify packages. The action will automatically read and cache packages from the `Aptfile` if it exists. Comments (lines starting with `#`) and inline comments are supported. +You can use an `Aptfile` at your repository root to specify packages. To enable Aptfile reading, set `use_aptfile` to `true`. Comments (lines starting with `#`) and inline comments are supported. **Example Aptfile:** ``` @@ -152,6 +152,7 @@ jobs: - uses: awalsh128/cache-apt-pkgs-action@latest with: version: v1 + use_aptfile: true # Enable Aptfile reading # packages input can be omitted if using Aptfile only - name: Build run: make @@ -162,12 +163,13 @@ You can also combine packages from both the input and `Aptfile`: - uses: awalsh128/cache-apt-pkgs-action@latest with: version: v1 + use_aptfile: true # Enable Aptfile reading packages: protobuf-compiler sd # Additional packages beyond Aptfile ``` ### Disabling Aptfile Usage -If you want to disable Aptfile reading even when an `Aptfile` exists in your repository, set `use_aptfile` to `false`: +By default, Aptfile reading is disabled (`use_aptfile: false`). If you want to explicitly disable it or ensure it stays disabled, you can set `use_aptfile` to `false`: ```yaml - uses: awalsh128/cache-apt-pkgs-action@latest diff --git a/action.yml b/action.yml index ef95422..59c7b3d 100644 --- a/action.yml +++ b/action.yml @@ -42,7 +42,7 @@ inputs: use_aptfile: description: 'Whether to read packages from Aptfile at repository root. Set to false to disable Aptfile usage even if Aptfile exists.' required: false - default: 'true' + default: 'false' outputs: cache-hit: diff --git a/lib.sh b/lib.sh index 92ca9a6..96c71c3 100755 --- a/lib.sh +++ b/lib.sh @@ -196,8 +196,12 @@ function write_manifest { log "Skipped ${1} manifest write. No packages to install." else log "Writing ${1} packages manifest to ${3}..." - # 0:-1 to remove trailing comma, delimit by newline and sort. - echo "${2:0:-1}" | tr ',' '\n' | sort > ${3} + # Remove trailing comma if present, delimit by newline and sort. + local content="${2}" + if [ ${#content} -gt 0 ] && [ "${content: -1}" = "," ]; then + content="${content:0:-1}" + fi + echo "${content}" | tr ',' '\n' | sort > "${3}" log "done" fi } diff --git a/src/internal/common/apt.go b/src/internal/common/apt.go index b497a66..1ccd41d 100644 --- a/src/internal/common/apt.go +++ b/src/internal/common/apt.go @@ -33,7 +33,10 @@ func isErrLine(line string) bool { // Resolves virtual packages names to their concrete one. func getNonVirtualPackage(executor exec.Executor, name string) (pkg *AptPackage, err error) { - execution := executor.Exec("bash", "-c", fmt.Sprintf("apt-cache showpkg %s | grep -A 1 \"Reverse Provides\" | tail -1", name)) + // Use grep with -A to get the line after "Reverse Provides", then filter out the header line itself + // The -v flag filters out lines containing "Reverse Provides" to exclude the header + // Then use tail -1 to get the last (first non-header) line, matching original behavior + execution := executor.Exec("bash", "-c", fmt.Sprintf("apt-cache showpkg %s | grep -A 1 \"Reverse Provides\" | grep -v \"Reverse Provides\" | tail -1", name)) err = execution.Error() if err != nil { logging.Fatal(err) @@ -42,11 +45,25 @@ func getNonVirtualPackage(executor exec.Executor, name string) (pkg *AptPackage, if isErrLine(execution.CombinedOut) { return pkg, execution.Error() } - splitLine := GetSplitLine(execution.CombinedOut, " ", 3) + // Trim whitespace and handle the output + output := strings.TrimSpace(execution.CombinedOut) + if output == "" { + return pkg, fmt.Errorf("empty output from apt-cache showpkg for virtual package '%s'", name) + } + // Skip if the output is the header line "Reverse Provides:" itself (defensive check) + if strings.HasPrefix(output, "Reverse Provides") { + return pkg, fmt.Errorf("unable to find concrete package for virtual package '%s'. Output was header line: %s", name, output) + } + splitLine := GetSplitLine(output, " ", 3) if len(splitLine.Words) < 2 { return pkg, fmt.Errorf("unable to parse space delimited line's package name and version from apt-cache showpkg output below:\n%s", execution.CombinedOut) } - return &AptPackage{Name: splitLine.Words[0], Version: splitLine.Words[1]}, nil + // Validate that we got a valid package name (not "Reverse" or "Provides") + packageName := splitLine.Words[0] + if packageName == "Reverse" || packageName == "Provides" || strings.HasPrefix(packageName, "Reverse") { + return pkg, fmt.Errorf("unable to parse valid package name from apt-cache showpkg output for virtual package '%s'. Output: %s", name, output) + } + return &AptPackage{Name: packageName, Version: splitLine.Words[1]}, nil } func getPackage(executor exec.Executor, paragraph string) (pkg *AptPackage, err error) {