Initial commit.

This commit is contained in:
awalsh128 2021-10-13 21:11:27 -07:00
commit b07ee5cce8
7 changed files with 230 additions and 0 deletions

19
.github/workflows/pub_staging_pr.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: Publish Staging Pull Request
on:
workflow_dispatch:
pull_request:
branches:
- staging
jobs:
publish_event:
runs-on: ubuntu-latest
name: Publish staging pull request.
steps:
- run: |
curl -i \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ secrets.TRIGGER_PUBLISH_STAGING_PR_TOKEN }}" \
https://api.github.com/repos/awalsh128/cache-apt-pkgs-action-ci/dispatches \
-d '{"event_type":"staging_pull_request"}'

13
LICENSE Normal file
View file

@ -0,0 +1,13 @@
Copyright 2021 Andrew Walsh
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

99
README.md Normal file
View file

@ -0,0 +1,99 @@
# cache-apt-pkgs-action
[![License: Apache2](https://shields.io/badge/license-apache2-blue.svg)](https://github.com/awalsh128/fluentcpp/blob/master/LICENSE)
[![GitHub Actions status](https://github.com/awalsh128/cache-apt-pkgs-action/workflows/Tests/badge.svg?branch=main&event=push)](https://github.com/awalsh128/cache-apt-pkgs-action/actions?query=workflow%3ATests)
This action allows caching of Advanced Package Tool (APT) package dependencies to improve workflow execution time.
## Documentation
This action is a composition of [actions/cache](https://github.com/actions/cache/README.md) and the `apt` utility. Some actions require additional APT based packages to be installed in order for other steps to be executed. Packages can be installed when ran but can consume much of the execution workflow time.
## Usage
### Pre-requisites
Create a workflow `.yml` file in your repositories `.github/workflows` directory. An [example workflow](#example-workflow) is available below. For more information, reference the GitHub Help Documentation for [Creating a workflow file](https://help.github.com/en/articles/configuring-a-workflow#creating-a-workflow-file).
### Inputs
* `key` - Unique key representing the cache being used.
* `packages` - Space delimited list of packages to install.
### Outputs
* `cache-hit` - A boolean value to indicate a cache was found for the packages requested.
### Cache scopes
The cache is scoped to the key and branch. The default branch cache is available to other branches.
See [Matching a cache key](https://help.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key) for more info.
### Example workflow
This was a motivating use case for creating this action.
```yaml
name: Documentation
on: push
jobs:
build_and_deploy_docs:
runs-on: ubuntu-latest
name: Build Doxygen documentation and deploy
steps:
- uses: actions/checkout@v2
- uses: awalsh128/cache-apt-pkgs-action-action@v1
with:
cache_key: doxygen_env
packages: dia doxygen doxygen-doc doxygen-gui doxygen-latex graphviz mscgen
- name: Build
run: |
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
branch: gh-pages
folder: ${{github.workspace}}/build/website
```
## Creating a cache key
A cache key can include any of the contexts, functions, literals, and operators supported by GitHub Actions.
For example, using the [`hashFiles`](https://help.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#hashfiles) function allows you to create a new cache when dependencies change.
```yaml
- uses: awalsh128/cache-apt-pkgs-action@v1
with:
cache_key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
packages: dot
```
Additionally, you can use arbitrary command output in a cache key, such as a date or software version:
```yaml
# http://man7.org/linux/man-pages/man1/date.1.html
- name: Get Epoch Seconds
id: get-epoch-sec
run: |
echo "::set-output name=epoch_sec::$(/bin/date +%s)"
shell: bash
- uses: awalsh128/cache-apt-pkgs-action@v1
with:
cache_key: ${{ runner.os }}-${{ steps.get-epoch-sec.outputs.epoch_sec }}-${{ hashFiles('**/lockfiles') }}
packages: dot
```
See [Using contexts to create cache keys](https://help.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows#using-contexts-to-create-cache-keys)
## Cache Limits
A repository can have up to 5GB of caches. Once the 5GB limit is reached, older caches will be evicted based on when the cache was last accessed. Caches that are not accessed within the last week will also be evicted.

41
action.yml Normal file
View file

@ -0,0 +1,41 @@
name: 'Cache APT Packages'
description: 'Install APT based packages and cache them for future runs.'
author: awalsh128
inputs:
packages:
description: 'Space delimited list of packages to install.'
required: true
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 }}
runs:
using: "composite"
steps:
- name: Validate Packages
run: ${{ github.action_path }}/validate_pkgs.sh ${{ inputs.packages }}
- name: Create Cache Key
run: echo ${{ inputs.packages }} | sed 's/[\s,]+/\n/g' | sort > /tmp/package_list.txt
shell: bash
- name: Load Package Cache
id: load-pkg-cache
uses: actions/cache@v2
with:
path: ~/cache-apt-pkgs
key: cache-apt-pkgs_${{ hashFiles('/tmp/package_list.txt') }}
- name: Install and Cache Packages
run: ${{ github.action_path }}/install_and_cache.sh ~/cache-apt-pkgs ${{ inputs.packages }}
shell: bash
if: steps.cache-primes.outputs.cache-hit != 'true'
- name: Restore Cached Packages
run: ${{ github.action_path }}/run.sh ~/cache-apt-pkgs /
shell: bash
if: steps.cache-primes.outputs.cache-hit != 'true'

24
install_and_cache_pkgs.sh Executable file
View file

@ -0,0 +1,24 @@
#!/bin/bash
# Directory that holds the cached packages.
cache_dir=$1
# List of the packages to use.
packages="${@:2}"
mkdir -p $cache_dir
for package in $packages; do
cache_filepath=$cache_dir/$package.tar.gz
echo "* Clean installing $package... "
sudo apt-get --yes install $package
echo "* Caching $package to $cache_filepath..."
# Pipe all package files (no folders) to Tar.
dpkg -L $package |
while IFS= read -r f; do
if test -f $f; then echo $f; fi;
done |
xargs tar -czf $cache_filepath -C /
fi
echo "Action complete. ${#packages[@]} package(s) installed and cached."

15
restore_pkgs.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
# 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
for cache_filepath in $(ls $cache_dir); do
echo "* Restoring $package from cache $cache_filepath... "
sudo tar -xf $cache_filepath -C $cache_restore_root
sudo apt-get --yes --only-upgrade install $package
fi
echo "Action complete. ${#packages[@]} package(s) restored."

19
validate_pkgs.sh Executable file
View file

@ -0,0 +1,19 @@
#!/bin/bash
packages=$1
echo -n "* Validating action arguments... ";
if [ "$packages" == "" ]; then
echo "aborted."
echo "* Packages argument cannot be empty." >&2
exit 1
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
fi
done
echo "done."