diff --git a/README.md b/README.md index b1762f5..e03856e 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Create a workflow `.yml` file in your repositories `.github/workflows` directory ### Inputs * `packages` - Space delimited list of packages to install. +* `version` - Version of cache to load. Each version will have its own cache. Note, all characters except spaces are allowed. ### Outputs @@ -44,6 +45,7 @@ jobs: - uses: awalsh128/cache-apt-pkgs-action@v1 with: packages: dia doxygen doxygen-doc doxygen-gui doxygen-latex graphviz mscgen + version: 1.0 - name: Build run: | diff --git a/action.yml b/action.yml index 1675e0c..67ebb1c 100644 --- a/action.yml +++ b/action.yml @@ -10,36 +10,42 @@ inputs: description: 'Space delimited list of packages to install.' required: true default: '' + version: + description: 'Version will create a new cache and install packages.' + required: false + default: '' outputs: cache-hit: description: 'A boolean value to indicate a cache was found for the packages requested.' - value: ${{ steps.load-pkg-cache.outputs.cache-hit }} + # This compound expression is needed because lhs can be empty. + # Need to output true and false instead of true and nothing. + value: ${{ steps.load-cache.outputs.cache-hit || false }} runs: using: "composite" steps: - name: Validate Packages - run: ${{ github.action_path }}/validate_pkgs.sh ${{ inputs.packages }} + run: ${{ github.action_path }}/validate_pkgs.sh "${{ inputs.version }}" ${{ inputs.packages }} shell: bash - name: Create Cache Key - run: echo ${{ inputs.packages }} | sed 's/[\s,]+/\n/g' | sort > /tmp/package_list.txt + run: | + ${{ github.action_path }}/create_cache_key.sh "${{ inputs.version }})" ${{ inputs.packages }} shell: bash - name: Load Package Cache - id: load-pkg-cache + id: load-cache uses: actions/cache@v2 with: path: ~/cache-apt-pkgs - key: cache-apt-pkgs_${{ hashFiles('/tmp/package_list.txt') }} + key: cache-apt-pkgs_${{ env.CACHE_KEY }} - - name: Install and Cache Packages - if: steps.load-pkg-cache.outputs.cache-hit != 'true' - run: ${{ github.action_path }}/install_and_cache.sh ~/cache-apt-pkgs ${{ inputs.packages }} - shell: bash - - - name: Restore Cached Packages - if: steps.load-pkg-cache.outputs.cache-hit != 'true' - run: ${{ github.action_path }}/run.sh ~/cache-apt-pkgs / + - name: Load Packages + run: | + if [ ${{ steps.load-cache.outputs.cache-hit }} ]; then + ${{ github.action_path }}/restore_pkgs.sh ~/cache-apt-pkgs / + else + ${{ github.action_path }}/install_and_cache_pkgs.sh ~/cache-apt-pkgs ${{ inputs.packages }} + fi shell: bash diff --git a/create_cache_key.sh b/create_cache_key.sh new file mode 100755 index 0000000..9d5c98f --- /dev/null +++ b/create_cache_key.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Fail on any error. +set -e + +version=$1 +packages=${@:2} + +echo "* Creating cache key..." + +# Remove package delimiters, sort (requires newline) and then convert back to inline list. +normalized_list=$(echo $packages | sed 's/[\s,]+/ /g' | tr ' ' '\n' | sort | tr '\n' ' ') +echo "* Normalized package list is '$normalized_list'." + +value=$(echo $normalized_list @ $version) +echo "* Value to hash is '$value'." + +key=$(echo $value | md5sum | /bin/cut -f1 -d' ') +echo "* Value hashed as '$key'." + +echo "CACHE_KEY=$key" >> $GITHUB_ENV \ No newline at end of file diff --git a/install_and_cache_pkgs.sh b/install_and_cache_pkgs.sh index e73b978..9d68cf8 100755 --- a/install_and_cache_pkgs.sh +++ b/install_and_cache_pkgs.sh @@ -1,10 +1,19 @@ #!/bin/bash +# Fail on any error. +set -e + # Directory that holds the cached packages. cache_dir=$1 # List of the packages to use. packages="${@:2}" +package_count=$(echo $packages | wc -w) +echo "* Clean installing $package_count packages..." +for package in $packages; do + echo " - $package" +done + mkdir -p $cache_dir for package in $packages; do cache_filepath=$cache_dir/$package.tar.gz @@ -19,6 +28,6 @@ for package in $packages; do if test -f $f; then echo $f; fi; done | xargs tar -czf $cache_filepath -C / -fi +done -echo "Action complete. ${#packages[@]} package(s) installed and cached." +echo "Action complete. $(echo $packages | wc -w) package(s) installed and cached." diff --git a/restore_pkgs.sh b/restore_pkgs.sh index c83c6ea..9f151e6 100755 --- a/restore_pkgs.sh +++ b/restore_pkgs.sh @@ -1,15 +1,30 @@ #!/bin/bash +# Fail on any error. +set -e + # Directory that holds the cached packages. cache_dir=$1 # Root directory to untar the cached packages to. # Typically filesystem root '/' but can be changed for testing. cache_restore_root=$2 +# List of the packages to use. +packages="${@:3}" -for cache_filepath in $(ls $cache_dir); do - echo "* Restoring $package from cache $cache_filepath... " +cache_filenames=$(ls -1 $cache_dir | sort) +cache_filename_count=$(echo $cache_filenames | wc -w) +echo "* Found $cache_filename_count files in cache..." +for cache_filename in $cache_filenames; do + echo " - $cache_filename" +done + +for package in $packages; do + cache_filepath=$cache_dir/$package.tar.gz + echo "* Restoring package $package ($cache_filepath) from cache... " sudo tar -xf $cache_filepath -C $cache_restore_root + # Upgrade the install from last state. + # TODO(awalsh128) Add versioning to cache key creation. sudo apt-get --yes --only-upgrade install $package -fi +done -echo "Action complete. ${#packages[@]} package(s) restored." +echo "Action complete. $cache_filename_count package(s) restored." diff --git a/validate_pkgs.sh b/validate_pkgs.sh index 09e3e52..e06e463 100755 --- a/validate_pkgs.sh +++ b/validate_pkgs.sh @@ -1,19 +1,30 @@ #!/bin/bash -packages=$1 +version=$1 +packages=${@:2} echo -n "* Validating action arguments... "; + +echo $version | grep -o " " > /dev/null +if [ $? -eq 0 ]; then + echo "aborted." + echo "* Version value '$version' cannot contain spaces." >&2 + exit 1 +fi + if [ "$packages" == "" ]; then echo "aborted." echo "* Packages argument cannot be empty." >&2 - exit 1 + exit 2 fi + for package in $packages; do apt-cache search ^$package$ | grep $package > /dev/null if [ $? -ne 0 ]; then echo "aborted." echo "* Package '$package' not found." >&2 - exit 2 + exit 3 fi done + echo "done."