Also Cache Non-Explicitly Listed APT PKGs

Apt installs more packages than just those explicitly listed. This can
lead to issues of missing files when the cache is restored.
This commit is contained in:
Nate Bohman 2022-03-16 14:36:54 -06:00
parent a56b21237f
commit 6d622023ef
No known key found for this signature in database
GPG key ID: C10546A54ABA1CE5
5 changed files with 76 additions and 59 deletions

View file

@ -25,6 +25,9 @@ outputs:
# This compound expression is needed because lhs can be empty. # This compound expression is needed because lhs can be empty.
# Need to output true and false instead of true and nothing. # Need to output true and false instead of true and nothing.
value: ${{ steps.load-cache.outputs.cache-hit || false }} value: ${{ steps.load-cache.outputs.cache-hit || false }}
cache-key:
description: 'The key where the cache is stored with packages, their versions, and the cache version (i.e. package=version package=version @ 1).'
value: ${{ steps.pre-cache.outputs.cache-key }}
package-version-list: package-version-list:
description: 'The packages and versions that are installed as a comma delimited list with colon delimit on the package version (i.e. <package>:<version,<package>:<version>).' description: 'The packages and versions that are installed as a comma delimited list with colon delimit on the package version (i.e. <package>:<version,<package>:<version>).'
value: ${{ steps.post-cache.outputs.package-version-list }} value: ${{ steps.post-cache.outputs.package-version-list }}
@ -39,6 +42,7 @@ runs:
"${{ inputs.version }}" \ "${{ inputs.version }}" \
${{ inputs.packages }} ${{ inputs.packages }}
echo "CACHE_KEY=$(cat ~/cache-apt-pkgs/cache_key.md5)" >> $GITHUB_ENV echo "CACHE_KEY=$(cat ~/cache-apt-pkgs/cache_key.md5)" >> $GITHUB_ENV
echo "::set-output name=cache-key::$(cat ~/cache-apt-pkgs/cache_key.md5)"
shell: bash shell: bash
- id: load-cache - id: load-cache

View file

@ -4,49 +4,62 @@
set -e set -e
# Directory that holds the cached packages. # Directory that holds the cached packages.
cache_dir=$1 cache_dir="${1}"
# List of the packages to use. # List of the packages to use.
packages="${@:2}" packages="${@:2}"
package_count=$(echo $packages | wc -w) # Sort these packages by name and split on commas.
echo "Clean installing and caching $package_count package(s)." packages=$(echo "${packages}" | sed 's/[\s,]+/ /g' | tr ' ' '\n' | sort | tr '\n' ' ')
# Remove extraneous spaces
packages="$(echo "${packages}" | sed 's/\s\+/ /g;s/^\s\+//g;s/\s\+$//g')"
package_count=$(echo "${packages}" | wc -w)
echo "Clean installing and caching ${package_count} package(s)."
echo "Package list:" echo "Package list:"
for package in $packages; do for package in ${packages}; do
echo "- $package" echo "- ${package}"
done done
echo -n "Updating APT package list..." echo -n "Updating APT package list..."
sudo apt-get update > /dev/null sudo apt-get update > /dev/null
echo "done." echo "done."
echo "Clean installing and caching $(echo $packages | wc -w) packages..." manifest=
for package in $packages; do echo "Clean installing and caching ${package_count} packages..."
cache_filepath=$cache_dir/$package.tar.gz for package in ${packages}; do
echo "- ${package}"
echo "- $package"
echo -n " Installing..." echo -n " Installing..."
sudo apt-get --yes install $package > /dev/null
# Gather a list of all packages apt installs to make this package work
required_packages=$(apt-get install --dry-run --yes "${package}" | grep -Po "(?<=Inst )[^\s]+" || echo "${package}")
echo "Package ${package} installs the following packages: ${required_packages//$'\n'/, }"
sudo DEBIAN_FRONTEND=noninteractive apt-get --yes install "${package}" > /dev/null
echo "done." echo "done."
echo -n " Caching to $cache_filepath..." for cache_package in ${required_packages}; do
# Pipe all package files (no folders) to Tar. cache_filepath="${cache_dir}/${cache_package}.tar.gz"
dpkg -L "$(echo "${package}" | cut -d"=" -f1)" | if [ ! -f "${cache_filepath}" ]; then
while IFS= read -r f; do package_name="$(echo "${cache_package}" | cut -d"=" -f1)"
if test -f $f; then echo ${f:1}; fi; #${f:1} removes the leading slash that Tar disallows echo -n " Caching ${package_name} to ${cache_filepath}..."
done | # Pipe all package files (no folders) to Tar.
xargs tar -czf $cache_filepath -C / dpkg -L "${package_name}" |
echo "done." while IFS= read -r f; do
if test -f $f; then echo "${f:1}"; fi; #${f:1} removes the leading slash that Tar disallows
done |
xargs tar -czf "${cache_filepath}" -C /
echo "done."
# Add package to manifest
manifest="${manifest}${package_name}:$(dpkg -s "${package_name}" | grep Version | awk '{print $2}'),"
fi
done
done done
echo "done." echo "done."
manifest_filepath="$cache_dir/manifest.log" manifest_filepath="${cache_dir}/manifest.log"
echo -n "Writing package manifest to $manifest_filepath..." echo -n "Writing package manifest to ${manifest_filepath}..."
manifest=
for package in $packages; do
package="$(echo "${package}" | cut -d"=" -f1)"
manifest=$manifest$package:$(dpkg -s $package | grep Version | awk '{print $2}'),
done
# Remove trailing comma. # Remove trailing comma.
echo ${manifest:0:-1} > $manifest_filepath echo ${manifest:0:-1} > ${manifest_filepath}
echo "done." echo "done."

View file

@ -4,23 +4,23 @@
set -e set -e
# Directory that holds the cached packages. # Directory that holds the cached packages.
cache_dir=$1 cache_dir="${1}"
# Root directory to untar the cached packages to. # Root directory to untar the cached packages to.
# Typically filesystem root '/' but can be changed for testing. # Typically filesystem root '/' but can be changed for testing.
cache_restore_root=$2 cache_restore_root="${2}"
# Indicates that the cache was found. # Indicates that the cache was found.
cache_hit=$3 cache_hit="${3}"
# List of the packages to use. # List of the packages to use.
packages="${@:4}" packages="${@:4}"
script_dir=$(dirname $0) script_dir="$(dirname -- "$(realpath -- "${0}")")"
if [ "$cache_hit" == true ]; then if [ "${cache_hit}" == true ]; then
$script_dir/restore_pkgs.sh ~/cache-apt-pkgs $cache_restore_root "${script_dir}/restore_pkgs.sh" ~/cache-apt-pkgs "${cache_restore_root}"
else else
$script_dir/install_and_cache_pkgs.sh ~/cache-apt-pkgs $packages "${script_dir}/install_and_cache_pkgs.sh" ~/cache-apt-pkgs "${packages}"
fi fi
echo "" echo ""

View file

@ -4,7 +4,7 @@
cache_dir="${1}" cache_dir="${1}"
# Version of the cache to create or load. # Version of the cache to create or load.
version="${2}" cache_version="${2}"
# List of the packages to use. # List of the packages to use.
packages="${@:3}" packages="${@:3}"
@ -15,11 +15,11 @@ packages=$(echo "${packages}" | sed 's/[\s,]+/ /g' | tr ' ' '\n' | sort | tr '\n
# Create cache directory so artifacts can be saved. # Create cache directory so artifacts can be saved.
mkdir -p "${cache_dir}" mkdir -p "${cache_dir}"
echo -n "Validating action arguments (version='${version}', packages='${packages}')..."; echo -n "Validating action arguments (version='${cache_version}', packages='${packages}')...";
if echo "${version}" | grep -q " " > /dev/null; then if echo "${cache_version}" | grep -q " " > /dev/null; then
echo "aborted." echo "aborted."
echo "Version value '${version}' cannot contain spaces." >&2 echo "Version value '${cache_version}' cannot contain spaces." >&2
exit 1 exit 1
fi fi
if [ "${packages}" == "" ]; then if [ "${packages}" == "" ]; then
@ -36,10 +36,10 @@ echo "done."
echo -n "Verifying packages..." echo -n "Verifying packages..."
for package in ${packages}; do for package in ${packages}; do
if echo "${package}" | grep -q "="; then if echo "${package}" | grep -q "="; then
pkg_name=$(echo "${package}" | cut -d "=" -f1) package_name=$(echo "${package}" | cut -d "=" -f1)
pkg_ver=$(echo "${package}" | cut -d "=" -f2) package_ver=$(echo "${package}" | cut -d "=" -f2)
else else
pkg_name="${package}" package_name="${package}"
fi fi
apt_show=$(apt show "${package}") apt_show=$(apt show "${package}")
if echo ${apt_show} | grep -qi "No packages found" > /dev/null; then if echo ${apt_show} | grep -qi "No packages found" > /dev/null; then
@ -47,10 +47,10 @@ for package in ${packages}; do
echo "Package '${package}' not found." >&2 echo "Package '${package}' not found." >&2
exit 3 exit 3
fi fi
if [ -z "${pkg_ver}" ]; then if [ -z "${package_ver}" ]; then
pkg_ver=$(echo "${apt_show}" | grep -Po "(?<=Version: )[^\s]+") package_ver=$(echo "${apt_show}" | grep -Po "(?<=Version: )[^\s]+")
fi fi
package_list="${package_list} ${pkg_name}=${pkg_ver}" package_list="${package_list} ${package_name}=${package_ver}"
done done
echo "done." echo "done."
@ -63,7 +63,7 @@ echo "Creating cache key..."
package_list="$(echo "${package_list}" | sed 's/\s\+/ /g;s/^\s\+//g;s/\s\+$//g')" package_list="$(echo "${package_list}" | sed 's/\s\+/ /g;s/^\s\+//g;s/\s\+$//g')"
echo "- Normalized package list is '$package_list'." echo "- Normalized package list is '$package_list'."
value=$(echo "${package_list} @ ${version}") value=$(echo "${package_list} @ ${cache_version}")
echo "- Value to hash is '${value}'." echo "- Value to hash is '${value}'."
key=$(echo "${value}" | md5sum | /bin/cut -f1 -d' ') key=$(echo "${value}" | md5sum | /bin/cut -f1 -d' ')

View file

@ -4,31 +4,31 @@
set -e set -e
# Directory that holds the cached packages. # Directory that holds the cached packages.
cache_dir=$1 cache_dir="${1}"
# Root directory to untar the cached packages to. # Root directory to untar the cached packages to.
# Typically filesystem root '/' but can be changed for testing. # Typically filesystem root '/' but can be changed for testing.
cache_restore_root=$2 cache_restore_root="${2}"
cache_filepaths=$(ls -1 $cache_dir | sort) cache_filepaths="$(ls -1 "${cache_dir}" | sort)"
echo "Found $(echo $cache_filepaths | wc -w) files in the cache." echo "Found $(echo "${cache_filepaths}" | wc -w) files in the cache."
for cache_filepath in $cache_filepaths; do for cache_filepath in ${cache_filepaths}; do
echo "- $(basename $cache_filepath)" echo "- $(basename "${cache_filepath}")"
done done
echo "Reading from manifest..." echo "Reading from manifest..."
for logline in $(cat $cache_dir/manifest.log | tr ',' '\n' ); do for logline in $(cat "${cache_dir}/manifest.log" | tr ',' '\n' ); do
echo "- $(echo $logline | tr ':' ' ')" echo "- $(echo "${logline}" | tr ':' ' ')"
done done
echo "done." echo "done."
# Only search for archived results. Manifest and cache key also live here. # Only search for archived results. Manifest and cache key also live here.
cache_pkg_filepaths=$(ls -1 $cache_dir/*.tar.gz | sort) cache_pkg_filepaths=$(ls -1 ${cache_dir}/*.tar.gz | sort)
cache_pkg_filecount=$(echo $cache_pkg_filepaths | wc -w) cache_pkg_filecount=$(echo "${cache_pkg_filepaths}" | wc -w)
echo "Restoring $cache_pkg_filecount packages from cache..." echo "Restoring ${cache_pkg_filecount} packages from cache..."
for cache_pkg_filepath in $cache_pkg_filepaths; do for cache_pkg_filepath in ${cache_pkg_filepaths}; do
echo -n "- $(basename $cache_pkg_filepath) restoring..." echo -n "- $(basename "${cache_pkg_filepath}") restoring..."
sudo tar -xf $cache_pkg_filepath -C $cache_restore_root > /dev/null sudo tar -xf ${cache_pkg_filepath} -C ${cache_restore_root} > /dev/null
echo "done." echo "done."
done done
echo "done." echo "done."