mirror of
https://github.com/awalsh128/cache-apt-pkgs-action.git
synced 2026-07-06 17:14:36 +00:00
fixed errors and restoring as a pure port from v1
This commit is contained in:
parent
42b6b9694b
commit
1d921eeba9
40
.github/actions/codehealth/action.yml
vendored
40
.github/actions/codehealth/action.yml
vendored
|
|
@ -20,43 +20,35 @@ runs:
|
|||
|
||||
- name: Type Coverage
|
||||
shell: bash
|
||||
run: npx type-coverage --at-least 95
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: 'github/codeql-action/init@1a818fd5f97ed0ee9a823421bd5b171add01227f' # v4.36.2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# Use 'security-extended' for more comprehensive security checks
|
||||
# and 'security-and-quality' to include code quality queries.
|
||||
queries: security-extended,security-and-quality
|
||||
run: npm run typecoverage
|
||||
|
||||
- name: Check Action Pinning
|
||||
shell: bash
|
||||
run: |
|
||||
# Install pinact (example via go or download binary)
|
||||
go install github.com/suzuki-shunsuke/pinact/cmd/pinact@latest
|
||||
|
||||
# Run check on the composite action file
|
||||
pinact run -check .github/actions/my-composite-action/action.yml
|
||||
pinact run -check .github/actions/codehealth/action.yml
|
||||
pinact run -check .github/actions/setup-env/action.yml
|
||||
pinact run -check .github/workflows/ci.yml
|
||||
pinact run -check .github/workflows/release.yml
|
||||
|
||||
- name: Verify ts-apt dependency reference is not locally switched
|
||||
shell: bash
|
||||
run: |
|
||||
if bash ./dev_scripts/switch_tsapt_local.sh --is_local_switched; then
|
||||
echo "Error: ts-apt dependency is switched to a local path. Please switch it back before running CI."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: npm run build
|
||||
|
||||
- name: Unit tests
|
||||
if: ${{ inputs.run_tests == 'true' }}
|
||||
shell: bash
|
||||
run: npm run test:unit
|
||||
|
||||
- name: Integration tests
|
||||
if: ${{ inputs.run_tests == 'true' }}
|
||||
shell: bash
|
||||
run: npm run test:integration
|
||||
|
||||
- name: Generate API docs
|
||||
shell: bash
|
||||
run: npm run docs:api
|
||||
|
||||
- name: Verify API docs are up to date
|
||||
- name: Tests
|
||||
if: ${{ inputs.run_tests == 'true' }}
|
||||
shell: bash
|
||||
run: git diff --exit-code -- docs/api
|
||||
run: npm test
|
||||
|
|
|
|||
8
.github/actions/setup-env/action.yml
vendored
8
.github/actions/setup-env/action.yml
vendored
|
|
@ -10,6 +10,14 @@ runs:
|
|||
node-version: 24
|
||||
cache: "npm"
|
||||
|
||||
- name: Verify ts-apt dependency is not locally switched
|
||||
shell: bash
|
||||
run: |
|
||||
if bash ./dev_scripts/switch_tsapt_local.sh --is_local_switched; then
|
||||
echo "Error: ts-apt dependency is switched to a local workspace path. Switch it back before pushing or opening a pull request."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: npm ci
|
||||
|
|
|
|||
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
|
|
@ -33,6 +33,12 @@ jobs:
|
|||
- name: Setup
|
||||
uses: ./.github/actions/setup-env
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: "github/codeql-action/init@1a818fd5f97ed0ee9a823421bd5b171add01227f" # v4.36.2
|
||||
with:
|
||||
languages: javascript-typescript
|
||||
queries: security-extended,security-and-quality
|
||||
|
||||
- name: Check code health
|
||||
uses: ./.github/actions/codehealth
|
||||
with:
|
||||
|
|
@ -40,7 +46,7 @@ jobs:
|
|||
|
||||
- name: Run tests with coverage
|
||||
shell: bash
|
||||
run: npm test
|
||||
run: npm run test:coverage
|
||||
|
||||
- name: Upload coverage info
|
||||
uses: "codecov/codecov-action@e53489f4d376d79066609109e7a95a29eb3740b1" # v7.0.0
|
||||
|
|
@ -55,6 +61,9 @@ jobs:
|
|||
coverage: ./coverage/coverage-final.json
|
||||
only-changed-files: true
|
||||
|
||||
- name: Analyze with CodeQL
|
||||
uses: "github/codeql-action/analyze@1a818fd5f97ed0ee9a823421bd5b171add01227f" # v4.36.2
|
||||
|
||||
# All other jobs should depend on build_binaries (if run) or check_distribute (if not needed)
|
||||
list_all_versions:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
|
|
@ -22,12 +22,11 @@ jobs:
|
|||
RELEASE_TAG: ${{ github.ref_type == 'tag' && github.ref_name || inputs.tag }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' # v7.0.0
|
||||
uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v7.0.0
|
||||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-env
|
||||
|
||||
# Preflight checks (validate tag format, version consistency, etc.)
|
||||
- name: Release preflight (tag/version)
|
||||
run: npm run release:preflight
|
||||
|
||||
|
|
@ -42,7 +41,7 @@ jobs:
|
|||
id-token: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' # v7.0.0
|
||||
uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v7.0.0
|
||||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-env
|
||||
|
|
@ -68,19 +67,19 @@ jobs:
|
|||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: 'softprops/action-gh-release@2bb465e97f322d3cb2a965294d483e0d26a67aa9' # v3.0.1
|
||||
uses: "softprops/action-gh-release@2bb465e97f322d3cb2a965294d483e0d26a67aa9" # v3.0.1
|
||||
with:
|
||||
generate_release_notes: true
|
||||
tag_name: ${{ github.ref_type == 'tag' && github.ref_name || inputs.tag }}
|
||||
|
||||
- name: Setup Pages
|
||||
uses: 'actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d' # v6.0.0
|
||||
uses: "actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d" # v6.0.0
|
||||
|
||||
- name: Upload Pages artifact
|
||||
uses: 'actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9' # v5.0.0
|
||||
uses: "actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9" # v5.0.0
|
||||
with:
|
||||
path: docs/api
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: 'actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128' # v5.0.0
|
||||
uses: "actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128" # v5.0.0
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ There are three kinds of version labels you can use.
|
|||
|
||||
### Security Compliance
|
||||
|
||||
This action runs as a JavaScript GitHub Action on the `node20` runtime and does not require consumers to run `npm install` in their workflow in order to use it. The implementation dependency surface is limited to the action runtime packages declared in `package.json`: `@actions/cache`, `@actions/core`, `tar`, `winston`, and `ts-apt`.
|
||||
This action runs as a JavaScript GitHub Action on the `node24` runtime and does not require consumers to run `npm install` in their workflow in order to use it. The implementation dependency surface is limited to the action runtime packages declared in `package.json`: `@actions/cache`, `@actions/core`, `tar`, `winston`, and `ts-apt`.
|
||||
|
||||
For workflows with stricter compliance requirements, the main security characteristics are:
|
||||
|
||||
|
|
|
|||
92
action.yml
92
action.yml
|
|
@ -1,46 +1,46 @@
|
|||
name: "Cache APT Packages"
|
||||
description: "Install APT based packages and cache them for future runs."
|
||||
author: awalsh128
|
||||
branding:
|
||||
icon: "hard-drive"
|
||||
color: "green"
|
||||
|
||||
inputs:
|
||||
packages:
|
||||
description: "Space delimited list of packages to install. Version can be specified optionally using APT command syntax of <name>=<version> (e.g. xdot=1.2-2)."
|
||||
required: true
|
||||
default: ""
|
||||
version:
|
||||
description: "Version of cache to load. Each version will have its own cache. Note, all characters except spaces are allowed."
|
||||
required: false
|
||||
default: ""
|
||||
execute_install_scripts:
|
||||
description: "Execute Debian package pre and post install script upon restore. See README.md caveats for more information."
|
||||
required: false
|
||||
default: "false"
|
||||
empty_packages_behavior:
|
||||
description: >
|
||||
Desired behavior when the provided package list is empty.
|
||||
|
||||
Available Options:
|
||||
error: Fail the action with an error message
|
||||
warn: Output a warning without failing the action
|
||||
ignore: Proceed silently without warnings or errors
|
||||
required: false
|
||||
default: "error"
|
||||
debug:
|
||||
description: "Enable debugging when there are issues with action. Minor performance penalty."
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: "A boolean value to indicate a cache was found for the packages requested."
|
||||
package-version-list:
|
||||
description: "The main requested packages and versions that are installed. Represented as a comma delimited list with equals delimit on the package version (i.e. <package>:<version,<package>:<version>)."
|
||||
all-package-version-list:
|
||||
description: "All the pulled in packages and versions, including dependencies, that are installed. Represented as a comma delimited list with equals delimit on the package version (i.e. <package>:<version,<package>:<version>)."
|
||||
|
||||
runs:
|
||||
using: "node20"
|
||||
main: "dist/index.js"
|
||||
name: "Cache APT Packages"
|
||||
description: "Install APT based packages and cache them for future runs."
|
||||
author: awalsh128
|
||||
branding:
|
||||
icon: "hard-drive"
|
||||
color: "green"
|
||||
|
||||
inputs:
|
||||
packages:
|
||||
description: "Space delimited list of packages to install. Version can be specified optionally using APT command syntax of <name>=<version> (e.g. xdot=1.2-2)."
|
||||
required: true
|
||||
default: ""
|
||||
version:
|
||||
description: "Version of cache to load. Each version will have its own cache. Note, all characters except spaces are allowed."
|
||||
required: false
|
||||
default: ""
|
||||
execute_install_scripts:
|
||||
description: "Execute Debian package pre and post install script upon restore. See README.md caveats for more information."
|
||||
required: false
|
||||
default: "false"
|
||||
empty_packages_behavior:
|
||||
description: >
|
||||
Desired behavior when the provided package list is empty.
|
||||
|
||||
Available Options:
|
||||
error: Fail the action with an error message
|
||||
warn: Output a warning without failing the action
|
||||
ignore: Proceed silently without warnings or errors
|
||||
required: false
|
||||
default: "error"
|
||||
debug:
|
||||
description: "Enable debugging when there are issues with action. Minor performance penalty."
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: "A boolean value to indicate a cache was found for the packages requested."
|
||||
package-version-list:
|
||||
description: "The main requested packages and versions that are installed. Represented as a comma delimited list with equals delimit on the package version (i.e. <package>:<version,<package>:<version>)."
|
||||
all-package-version-list:
|
||||
description: "All the pulled in packages and versions, including dependencies, that are installed. Represented as a comma delimited list with equals delimit on the package version (i.e. <package>:<version,<package>:<version>)."
|
||||
|
||||
runs:
|
||||
using: "node24"
|
||||
main: "dist/index.js"
|
||||
|
|
|
|||
30
dev_scripts/release-preflight.mjs
Normal file
30
dev_scripts/release-preflight.mjs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
const repoRoot = path.resolve(import.meta.dirname, "..");
|
||||
const packageJsonPath = path.join(repoRoot, "package.json");
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
||||
|
||||
const rawTag = process.env.RELEASE_TAG ?? process.argv[2] ?? "";
|
||||
if (!rawTag) {
|
||||
throw new Error("RELEASE_TAG must be provided for release preflight checks.");
|
||||
}
|
||||
|
||||
if (!/^v\d+\.\d+\.\d+(?:[-.][0-9A-Za-z.-]+)?$/.test(rawTag)) {
|
||||
throw new Error(`Release tag '${rawTag}' is not a valid semver-style tag.`);
|
||||
}
|
||||
|
||||
const expectedVersion = String(packageJson.version ?? "");
|
||||
const actualVersion = rawTag.slice(1);
|
||||
if (expectedVersion !== actualVersion) {
|
||||
throw new Error(
|
||||
`Release tag '${rawTag}' does not match package.json version '${expectedVersion}'.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (packageJson.private === true) {
|
||||
throw new Error("package.json must not be private for publish releases.");
|
||||
}
|
||||
|
||||
process.stdout.write(`Release preflight passed for ${rawTag}.\n`);
|
||||
|
|
@ -5,17 +5,31 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||
source "${SCRIPT_DIR}/lib.sh"
|
||||
|
||||
PACKAGE_PATH="${SCRIPT_DIR}/../package.json"
|
||||
LOCAL_VAL="../../ts-apt"
|
||||
NPM_VAL="^ts-apt/$(npm view ts-apt version 2> /dev/null | tr -d '\n')"
|
||||
LOCAL_VAL="file:../ts-apt"
|
||||
NPM_VAL="^$(npm view ts-apt version 2> /dev/null | tr -d '\n')"
|
||||
|
||||
if ! grep -q "\"ts-apt\": \"${LOCAL_VAL}\"," "${PACKAGE_PATH}"; then
|
||||
echo "Switching ts-apt dependency to local path '${LOCAL_VAL}'..."
|
||||
if [[ ! -d "${SCRIPT_DIR}/../ts-apt" ]]; then
|
||||
echo "Local ts-apt path '${LOCAL_VAL}' does not exist. Checking out..."
|
||||
clone_repo "ts-apt" "${SCRIPT_DIR}/../ts-apt"
|
||||
function is_local_switched() {
|
||||
grep -q "\"ts-apt\": \"${LOCAL_VAL}\"," "${PACKAGE_PATH}"
|
||||
}
|
||||
|
||||
function switch() {
|
||||
if ! is_local_switched; then
|
||||
echo "Switching ts-apt dependency to local path '${LOCAL_VAL}'..."
|
||||
if [[ ! -d "${SCRIPT_DIR}/../ts-apt" ]]; then
|
||||
echo "Local ts-apt path '${LOCAL_VAL}' does not exist. Checking out..."
|
||||
clone_repo "ts-apt" "${SCRIPT_DIR}/../ts-apt"
|
||||
fi
|
||||
sed -i "s#\"ts-apt\": \".*\",#\"ts-apt\": \"${LOCAL_VAL}\",#" "${PACKAGE_PATH}"
|
||||
echo "Switched to local ts-apt. Run 'npm install --ignore-scripts' to refresh node_modules and package-lock.json."
|
||||
else
|
||||
echo "Switching ts-apt dependency to NPM version '${NPM_VAL}'..."
|
||||
sed -i "s#\"ts-apt\": \".*\",#\"ts-apt\": \"${NPM_VAL}\",#" "${PACKAGE_PATH}"
|
||||
echo "Switched to published ts-apt. Run 'npm install --ignore-scripts' to refresh node_modules and package-lock.json."
|
||||
fi
|
||||
sed -i "s#\"ts-apt\": \".*\",#\"ts-apt\": \"${LOCAL_VAL}\",#" "${PACKAGE_PATH}"
|
||||
}
|
||||
|
||||
if [[ "$1" == "--is_local_switched" ]]; then
|
||||
is_local_switched
|
||||
else
|
||||
echo "Switching ts-apt dependency to NPM version '${NPM_VAL}'..."
|
||||
sed -i "s#\"ts-apt\": \".*\",#\"ts-apt\": \"${NPM_VAL}\",#" "${PACKAGE_PATH}"
|
||||
switch
|
||||
fi
|
||||
1
docs/api/.nojekyll
Normal file
1
docs/api/.nojekyll
Normal file
|
|
@ -0,0 +1 @@
|
|||
TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
|
||||
1
docs/api/assets/hierarchy.js
Normal file
1
docs/api/assets/hierarchy.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
window.hierarchyData = "eJyrVirKzy8pVrKKjtVRKkpNy0lNLsnMzytWsqqurQUAmx4Kpg=="
|
||||
64
docs/api/assets/highlight.css
Normal file
64
docs/api/assets/highlight.css
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
:root {
|
||||
--light-hl-0: #800000;
|
||||
--dark-hl-0: #569CD6;
|
||||
--light-hl-1: #000000;
|
||||
--dark-hl-1: #D4D4D4;
|
||||
--light-hl-2: #0000FF;
|
||||
--dark-hl-2: #CE9178;
|
||||
--light-hl-3: #0000FF;
|
||||
--dark-hl-3: #569CD6;
|
||||
--light-hl-4: #098658;
|
||||
--dark-hl-4: #B5CEA8;
|
||||
--light-hl-5: #AF00DB;
|
||||
--dark-hl-5: #C586C0;
|
||||
--light-code-background: #FFFFFF;
|
||||
--dark-code-background: #1E1E1E;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) { :root {
|
||||
--hl-0: var(--light-hl-0);
|
||||
--hl-1: var(--light-hl-1);
|
||||
--hl-2: var(--light-hl-2);
|
||||
--hl-3: var(--light-hl-3);
|
||||
--hl-4: var(--light-hl-4);
|
||||
--hl-5: var(--light-hl-5);
|
||||
--code-background: var(--light-code-background);
|
||||
} }
|
||||
|
||||
@media (prefers-color-scheme: dark) { :root {
|
||||
--hl-0: var(--dark-hl-0);
|
||||
--hl-1: var(--dark-hl-1);
|
||||
--hl-2: var(--dark-hl-2);
|
||||
--hl-3: var(--dark-hl-3);
|
||||
--hl-4: var(--dark-hl-4);
|
||||
--hl-5: var(--dark-hl-5);
|
||||
--code-background: var(--dark-code-background);
|
||||
} }
|
||||
|
||||
:root[data-theme='light'] {
|
||||
--hl-0: var(--light-hl-0);
|
||||
--hl-1: var(--light-hl-1);
|
||||
--hl-2: var(--light-hl-2);
|
||||
--hl-3: var(--light-hl-3);
|
||||
--hl-4: var(--light-hl-4);
|
||||
--hl-5: var(--light-hl-5);
|
||||
--code-background: var(--light-code-background);
|
||||
}
|
||||
|
||||
:root[data-theme='dark'] {
|
||||
--hl-0: var(--dark-hl-0);
|
||||
--hl-1: var(--dark-hl-1);
|
||||
--hl-2: var(--dark-hl-2);
|
||||
--hl-3: var(--dark-hl-3);
|
||||
--hl-4: var(--dark-hl-4);
|
||||
--hl-5: var(--dark-hl-5);
|
||||
--code-background: var(--dark-code-background);
|
||||
}
|
||||
|
||||
.hl-0 { color: var(--hl-0); }
|
||||
.hl-1 { color: var(--hl-1); }
|
||||
.hl-2 { color: var(--hl-2); }
|
||||
.hl-3 { color: var(--hl-3); }
|
||||
.hl-4 { color: var(--hl-4); }
|
||||
.hl-5 { color: var(--hl-5); }
|
||||
pre, code { background: var(--code-background); }
|
||||
18
docs/api/assets/icons.js
Normal file
18
docs/api/assets/icons.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/assets/icons.svg
Normal file
1
docs/api/assets/icons.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 14 KiB |
60
docs/api/assets/main.js
Normal file
60
docs/api/assets/main.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/assets/navigation.js
Normal file
1
docs/api/assets/navigation.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
window.navigationData = "eJyNkk9PwzAMxb9LztUQE0yotzIJaRoDxHXaIWpdaq11qjiFDcR3R8pK/yXLdo3f+zn28/ZHGDgYEQuZGlQkIlFLU4hYVCprSuCb0/usMFUpIrFHykQ8j0RaYJlpIBFvO0RipW8y3csPeJEV9LS0lMw9zVGO+bfzh99ogn1viEBfIJ5El2ErqhvDPQzJgM5lOuWddJPh7xcO77Ux1wFbYYhISleyxG+wzdsdDdB5QxbVkf2GcYvF3aBDLTXDo1IlSApwh7IATTeUTG7HQXUah7MbkJAyOLgXaJ8nGxu6lMeirjrYpUwLz5GimtlK6I6sYA3H8+41HEOANievv62F7BkwaLSxu1/p949q5lEG0kROavOMbPhJAxdnmBNVMNVKEubAxk3pv3JVVhpktmkNCS/50/e1juioAyN/aTSwcX7poY6UnqF3f0nc1Lc="
|
||||
1
docs/api/assets/search.js
Normal file
1
docs/api/assets/search.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
window.searchData = "eJy9mm1v2zYQx7+L8lZwzSfF9rtsWLGie0K3dS+MYFBlOiGqSIYkp+uCfPeBEmXd+SibitO9auHo/nckf3c8UXyKqvJLHa3WT9FnU2yiFY+jIn3Q0SpKs8aURRRH+yqPVtFDudnnun7T/Ty7bx7yKI6yPK1rXUerKHqOew3GFweVm/bx39Lsc3qnf7G/9YLOtBckD3pcxNEurXTRDNENThUbQs/Kom6qfdaU1TR3V9jylGuqAGdgzuUhmo2pm6qcGMjB6HViKCbP/JUzeR3/j7qqIU1hIQxWL46Cz+UAY60rk+bm36lTAe1ePh8kKz7si0KfIbR75v/IBeBpehq4oYzM+6e9yTdvTa5/MnXztqzcBIXH0wpsTa5zUzfbstodBC6ObWuKzbuibtI8/z2rzK4Jj8qams607k0vjudON9+n2b1+r7+GR3Knm8wafW6NXi2GD2U5YTr6IKrO6uIo3NTeFJs2GAdNHR6QE0iLTRvXbhC4OLairB7aivCu2O2b6aEd7I21/yaR9UH9ZZr7j10hfUmAfWxfTHP/OMhcHKfT/X2nM7M1uvqjPN8dwAD7uHr7pgzfsM5FVtX6u7LMdXpmw8LxVLX+dLC6OIpK12X+2K/ix5D9E4bjzN0sTdpIz8bVlNULstEZvibr1b64wV3q+Sj2xaGxvdh/k1YfdJ42xq5Tcx8eRZNWlTPcdYYXx7LfbdJG3+wau8dOWJbOLt01ubO7OJLHNDdW84eHXfN1Oie9ubbml9KikqOeq63XQzSmaHS1TbPjgLrHJrZduOvXn/Z3U/xc9RYBA3WjGHGt4cR/p+/TRwOav5BQ0Nx/GhQuD+0fne0bjRquSatx5RRQ3xWIx+nQdsekhkQzjc/TARy/I4X4n1TYiXuaHr/um6D8cM9dkiBpnuPNzRauSY6v0jzHG1zeSQTMRT/QkeDahvFHMzGe1urevE4Iuwsn5/VmJpGhfe92X7Qah7j8z0/EJpGnezPiFT71cl+0uyCODo9M9MLBS85G/0MO2dpfT56xAYWSmpfB53PtqxXZnE05a/9welimfMGZA5IOOmjoLeDoE84kpMLTfGFHJ9ssn4ej92Hf6zj2cKebU6/fHh9kHU45ea+/fsPV6NUnLYgNd6y4V9n4ihycuade7GVbVpn+s21g3xVZpR+s5VmvrVXX9hpg9eIoDjVuM9rskhgGm7MdREAEY6erxO25dsHvK/AMlXg7f2w6MjaQF2NHhaacuT99m6yA4qFJ0cc65Qz+2NXJQ4zzPk6QgNwEgEA9hXOAfAVhQL0l8F3qoEHq5LAnm3LmeXACHsCjqfs36beVru/93o4emuBpwPAhLcxWg96u38P7P5zcyWG3otPNz87mpv6+fvTEfNAkD5+O/RCk1/OXyjT65+NxeLyiB0M93sauR1o9HeheRXwmZssojrZG5xv7/bLPrqx8cPV8U2b79r+37rGP2iawfbh7+s08itfzWFzP5kre3sbr3rj9Q/tDrzH80hqyKF4znyEjhgwZ8ihe85jL2TxhyJATQ44MRRSvhc+jIIYCGcooXstYsNlSJshQEkOJDFUUr1XMk9k8WSBDRQwVMkyieJ3EfDFTCzzGhBgmyPA6itfXvjFeE8NrZLgYm9UFMVwgw2UUrxc+j0tiuMQAWB6WXgIoO+wInpYeL3fMww8GiFksmJ89yhDDEDGLBuNeY8oRwyAxiwcTPpQYZYlhmJhFhEmvZ8oTw0AxiwlTXmPKFMNQMYsKS7xhU64YBotZXJiXSUbZYhguZpFhXrwY5YthwLhlhi19YXNKGMeEccsM9xLGKWH8qES1NcpLGPdUKUwYt8xwL2GcEsYxYdwyw71VjlPCOCaMW2a4lzBOCeOYMG6Z4V7COCWMY8K4ZYYnXmNKGMeE8bZ2eQnjlDCOCePLsRrNKWAcAyYsMtxLp6CACQyYaAHz1j9BARMYMGGREV46BQVMHO2D7UbopVN4tkIMmBgvYYICJjBgQo0WEkEBExgwkYyms6CACQyYsMgIb1IJCpjAgAmLjPC3DhQwgQETlhnhTSpBCROYMDkf25YlBUxiwKRFRngTUlLAJAZMtoB5E1JSwCQGTLaAeRNSUsDkUbMlR4fsabcwX9ISI7wJKSlfEvMlLTHCm5CS8iUxX9ISI70JKSlfEvMlF2M1SFK8JMZLLsdaRUnpkpguZYGR3kKgKF4K46XY2DopSpfCdCk+1lErCpfCcCkx2lRTthRmS8mxyVKULXXUy1tapLeCKE87j9lSlhbprSCKsqUwW6ply1tBFGVLYbaUxUV6q4CicCkMl7K8SG8VUJQu91P7svmoq0Zv3nUvnev14SLsU/S3exOd9+++T9E8Wj09Pw/vnaunZ/Dqaf9m/XQSxn17HoS4GJS4nCBV9t/pgNZi0BJTwnInkN0L9KDHBjk2Qa1ylxoHoetB6DpMyP9ZDwx1CYYaGFx71DxICDBbUgVJjF5CHFSB6DJIM+s+v4C4JBjaBI32qyOQAYgKHi7TfsEAMmDtpAiTgWelYMkA6J3lovtHzt2/svtXha2nuywBHICJ42ELCk4LfYOXIGYVqOhubYMZBOsQJDFy9QIMVIGBJmGa/jsTQDMBmmFJ6rn8OuiB/GRhpcj/UQbMI5CUYaNGl2JBXQOpwcJgwzdbgRSskWFZ1n8lBCMDcy/DRNxHY6ABUBVh6zd6ORYMD6iyMHoNhh/SvwgTqPuraNvu4B3kI1BTYQgMp+tABhQKFTZXx1sjUOirVtjC+T77AVlApgyMbOQeMVhEMGvMRSvCWo0zd4CBDzAhLKxSejZPCbJJhVUN34A52LN4GHRjd4nBCEHRZWHsnW5hBBisCMstfMMYxAYKCLt2Kxy6Cg3uisAwZVhttJ+S+jRL68x+dwJLCvRU2FqMXFwGwwXry4I18dVjoAZaNhbWb4ErxEAH7E/ctTQiDBTwfXTQA2uauAZp6UpNWPKSK8YgQ0Cd4WGrfHxLGIgBkHlYFRy54Qs0YbcYlhweUCB7nRV3Uyhd76nCtNvvlt6tBKySCoDnNo52ZqdzU+hotb59fv4P0wXb3Q==";
|
||||
1633
docs/api/assets/style.css
Normal file
1633
docs/api/assets/style.css
Normal file
File diff suppressed because it is too large
Load diff
7
docs/api/classes/action.ActionPackageName.html
Normal file
7
docs/api/classes/action.ActionPackageName.html
Normal file
File diff suppressed because one or more lines are too long
17
docs/api/classes/action.ActionRunner.html
Normal file
17
docs/api/classes/action.ActionRunner.html
Normal file
File diff suppressed because one or more lines are too long
4
docs/api/classes/io.Cache.html
Normal file
4
docs/api/classes/io.Cache.html
Normal file
File diff suppressed because one or more lines are too long
7
docs/api/classes/io.CacheKey.html
Normal file
7
docs/api/classes/io.CacheKey.html
Normal file
File diff suppressed because one or more lines are too long
5
docs/api/classes/io.Package.html
Normal file
5
docs/api/classes/io.Package.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/action.normalizeInputPackages.html
Normal file
1
docs/api/functions/action.normalizeInputPackages.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/action.parseBoolean.html
Normal file
1
docs/api/functions/action.parseBoolean.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/action.runAction.html
Normal file
1
docs/api/functions/action.runAction.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/io.deserializeCacheKey.html
Normal file
1
docs/api/functions/io.deserializeCacheKey.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/io.isAptListsFresh.html
Normal file
1
docs/api/functions/io.isAptListsFresh.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/manifest.readManifestAsCsv.html
Normal file
1
docs/api/functions/manifest.readManifestAsCsv.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/functions/manifest.writeManifest.html
Normal file
1
docs/api/functions/manifest.writeManifest.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/hierarchy.html
Normal file
1
docs/api/hierarchy.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html class="default" lang="en" data-base="./"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>cache-apt-pkgs-action</title><meta name="description" content="Documentation for cache-apt-pkgs-action"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script defer src="assets/main.js"></script><script async src="assets/icons.js" id="tsd-icons-script"></script><script async src="assets/search.js" id="tsd-search-script"></script><script async src="assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="index.html" class="title">cache-apt-pkgs-action</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><h1>cache-apt-pkgs-action</h1></div><h2>Hierarchy Summary</h2></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">cache-apt-pkgs-action</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
|
||||
108
docs/api/index.html
Normal file
108
docs/api/index.html
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<!DOCTYPE html><html class="default" lang="en" data-base="./"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>cache-apt-pkgs-action</title><meta name="description" content="Documentation for cache-apt-pkgs-action"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script defer src="assets/main.js"></script><script async src="assets/icons.js" id="tsd-icons-script"></script><script async src="assets/search.js" id="tsd-search-script"></script><script async src="assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="index.html" class="title">cache-apt-pkgs-action</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><h1>cache-apt-pkgs-action</h1></div><div class="tsd-panel tsd-typography"><h1 id="cache-apt-pkgs-action" class="tsd-anchor-link">cache-apt-pkgs-action<a href="#cache-apt-pkgs-action" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h1>
|
||||
<p><a href="https://github.com/awalsh128/fluentcpp/blob/master/LICENSE"><img src="https://shields.io/badge/license-apache2-blue.svg" alt="License: Apache2"></a>
|
||||
<a href="https://github.com/awalsh128/cache-apt-pkgs-action-ci/actions/workflows/master_test.yml"><img src="https://github.com/awalsh128/cache-apt-pkgs-action-ci/actions/workflows/master_test.yml/badge.svg" alt="Master Test status"></a>
|
||||
<a href="https://github.com/awalsh128/cache-apt-pkgs-action-ci/actions/workflows/dev_test.yml"><img src="https://github.com/awalsh128/cache-apt-pkgs-action-ci/actions/workflows/dev_test.yml/badge.svg" alt="Dev Test status"></a></p>
|
||||
<p>This action allows caching of Advanced Package Tool (APT) package dependencies to improve workflow execution time instead of installing the packages on every run.</p>
|
||||
<div class="tsd-alert tsd-alert-note"><div class="tsd-alert-title"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><use href="assets/icons.svg#icon-alertNote"></use></svg><span>Note</span></div><p>
|
||||
The open source projects that I maintain are a labor of love. If you find this useful and want to support open source, <strong>please consider donating and <a href="http://buymeacoffee.com/awalsh128">Buy Me a Coffe</a></strong>.</p>
|
||||
</div>
|
||||
<div class="tsd-alert tsd-alert-note"><div class="tsd-alert-title"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><use href="assets/icons.svg#icon-alertNote"></use></svg><span>Note</span></div><p>
|
||||
Version 2 of the action is now available! See <a href="media/V2_FAQ.MD">Version 2 FAQ</a> for more information.</p>
|
||||
</div>
|
||||
<div class="tsd-alert tsd-alert-important"><div class="tsd-alert-title"><svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><use href="assets/icons.svg#icon-alertImportant"></use></svg><span>Important</span></div><p>
|
||||
Looking for co-maintainers to help review changes, and investigate issues. I haven't had as much time to stay on top of this action as I would like to and want to make sure it is still responsive and reliable for the community. If you are interested, please reach out.</p>
|
||||
</div>
|
||||
<h2 id="documentation" class="tsd-anchor-link">Documentation<a href="#documentation" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
||||
<p>This action is a composition of <a href="https://github.com/actions/cache/">actions/cache</a> and the <code>apt</code> 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.</p>
|
||||
<h2 id="usage" class="tsd-anchor-link">Usage<a href="#usage" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
||||
<h3 id="pre-requisites" class="tsd-anchor-link">Pre-requisites<a href="#pre-requisites" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>Create a workflow <code>.yml</code> file in your repositories <code>.github/workflows</code> directory. An <a href="#example-workflow">example workflow</a> is available below. For more information, reference the GitHub Help Documentation for <a href="https://help.github.com/en/articles/configuring-a-workflow#creating-a-workflow-file">Creating a workflow file</a>.</p>
|
||||
<h3 id="versions" class="tsd-anchor-link">Versions<a href="#versions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>There are three kinds of version labels you can use.</p>
|
||||
<ul>
|
||||
<li><code>@latest</code> - This will give you the latest release.</li>
|
||||
<li><code>@v#</code> - Major only will give you the latest release for that major version only (e.g. <code>v1</code>).</li>
|
||||
<li>Branch
|
||||
<ul>
|
||||
<li><code>@master</code> - Most recent manual and automated tested code. Possibly unstable since it is pre-release.</li>
|
||||
<li><code>@staging</code> - Most recent automated tested code and can sometimes contain experimental features. Is pulled from dev stable code.</li>
|
||||
<li><code>@dev</code> - Very unstable and contains experimental features. Automated testing may not show breaks since CI is also updated based on code in dev.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="inputs" class="tsd-anchor-link">Inputs<a href="#inputs" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<ul>
|
||||
<li><code>packages</code> - Space delimited list of packages to install.</li>
|
||||
<li><code>version</code> - Version of cache to load. Each version will have its own cache. Note, all characters except spaces are allowed.</li>
|
||||
<li><code>execute_install_scripts</code> - Execute Debian package pre and post install script upon restore. See <a href="#non-file-dependencies">Caveats / Non-file Dependencies</a> for more information.</li>
|
||||
<li><code>empty_packages_behavior</code> - Desired behavior when the given <code>packages</code> is empty. <code>'error'</code> (default), <code>'warn'</code> or <code>'ignore'</code>.</li>
|
||||
</ul>
|
||||
<h3 id="outputs" class="tsd-anchor-link">Outputs<a href="#outputs" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<ul>
|
||||
<li><code>cache-hit</code> - A boolean value to indicate a cache was found for the packages requested.</li>
|
||||
<li><code>package-version-list</code> - The main requested packages and versions that are installed. Represented as a comma delimited list with equals delimit on the package version (i.e. <package1>=<version1>,<package2>=<version2>,...).</li>
|
||||
<li><code>all-package-version-list</code> - All the pulled in packages and versions, including dependencies, that are installed. Represented as a comma delimited list with equals delimit on the package version (i.e. <package1>=<version1>,<package2>=<version2>,...).</li>
|
||||
</ul>
|
||||
<h3 id="security-compliance" class="tsd-anchor-link">Security Compliance<a href="#security-compliance" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>This action runs as a JavaScript GitHub Action on the <code>node24</code> runtime and does not require consumers to run <code>npm install</code> in their workflow in order to use it. The implementation dependency surface is limited to the action runtime packages declared in <code>package.json</code>: <code>@actions/cache</code>, <code>@actions/core</code>, <code>tar</code>, <code>winston</code>, and <code>ts-apt</code>.</p>
|
||||
<p>For workflows with stricter compliance requirements, the main security characteristics are:</p>
|
||||
<ul>
|
||||
<li><code>packages</code> should be treated as an allowlisted input in your workflow. Prefer explicit package names and versions where reproducibility matters.</li>
|
||||
<li><code>version</code> can be used as a cache namespace so you can intentionally rotate caches when package policy or runner baselines change.</li>
|
||||
<li><code>empty_packages_behavior</code> can be left at the default <code>error</code> to fail closed when an expected package list is missing.</li>
|
||||
<li><code>execute_install_scripts</code> is disabled by default. Enable it only when required, because Debian maintainer scripts execute arbitrary package-provided shell logic during restore.</li>
|
||||
<li><code>debug</code> is disabled by default. Enable it only for investigation and review logs before sharing them outside your organization.</li>
|
||||
</ul>
|
||||
<h4 id="features" class="tsd-anchor-link">Features<a href="#features" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4>
|
||||
<p>Security-relevant action features:</p>
|
||||
<ul>
|
||||
<li>Package inputs are normalized before cache lookup, which reduces accidental cache divergence from ordering, commas, backslashes, or duplicate whitespace in the package list.</li>
|
||||
<li>Unpinned package names are resolved to concrete package versions before the cache key is generated, which improves traceability of what was actually cached for a run.</li>
|
||||
<li>Cache keys are derived from the normalized package set, the user-provided <code>version</code>, and the runner architecture, which helps isolate caches across package changes and incompatible platforms.</li>
|
||||
<li>The action rejects invalid boolean inputs and rejects <code>version</code> values containing spaces, reducing ambiguous workflow configuration.</li>
|
||||
<li>When creating archives, the action records installed package manifests and only archives existing files and symlinks from installed packages, plus maintainer scripts when present.</li>
|
||||
<li>The <code>package-version-list</code> and <code>all-package-version-list</code> outputs can be captured by downstream workflow steps for audit logs, attestation inputs, or compliance reporting.</li>
|
||||
</ul>
|
||||
<h4 id="usage-recommendations" class="tsd-anchor-link">Usage Recommendations<a href="#usage-recommendations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h4>
|
||||
<p>For GitHub Actions workflow hardening, prefer the following controls around this action:</p>
|
||||
<ul>
|
||||
<li>Pin this action to a major version you trust, or to a full commit SHA for stricter supply chain control.</li>
|
||||
<li>Use the minimum required workflow <code>permissions</code> instead of broad defaults.</li>
|
||||
<li>Run on GitHub-hosted or otherwise trusted runners with controlled APT sources.</li>
|
||||
<li>Limit who can modify workflow files and package lists through branch protection and pull request review.</li>
|
||||
<li>Review whether cached APT contents are acceptable for your repository's cache retention policy and data handling requirements.</li>
|
||||
</ul>
|
||||
<p>Example hardened usage:</p>
|
||||
<pre><code class="yaml"><span class="hl-0">permissions</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">contents</span><span class="hl-1">: </span><span class="hl-2">read</span><br/><br/><span class="hl-0">jobs</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">build</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">runs-on</span><span class="hl-1">: </span><span class="hl-2">ubuntu-latest</span><br/><span class="hl-1"> </span><span class="hl-0">steps</span><span class="hl-1">:</span><br/><span class="hl-1"> - </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">actions/checkout@v4</span><br/><span class="hl-1"> - </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">awalsh128/cache-apt-pkgs-action@v2</span><br/><span class="hl-1"> </span><span class="hl-0">with</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">packages</span><span class="hl-1">: </span><span class="hl-2">curl=8.5.0-2ubuntu10.6 jq=1.7.1-3build1</span><br/><span class="hl-1"> </span><span class="hl-0">version</span><span class="hl-1">: </span><span class="hl-2">ubuntu-24.04-v1</span><br/><span class="hl-1"> </span><span class="hl-0">empty_packages_behavior</span><span class="hl-1">: </span><span class="hl-2">error</span><br/><span class="hl-1"> </span><span class="hl-0">execute_install_scripts</span><span class="hl-1">: </span><span class="hl-3">false</span>
|
||||
</code><button type="button">Copy</button></pre>
|
||||
|
||||
<h3 id="cache-scopes" class="tsd-anchor-link">Cache scopes<a href="#cache-scopes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>The cache is scoped to the packages given and the branch. The default branch cache is available to other branches.</p>
|
||||
<h3 id="example-workflow" class="tsd-anchor-link">Example workflow<a href="#example-workflow" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>This was a motivating use case for creating this action.</p>
|
||||
<pre><code class="yaml"><span class="hl-0">name</span><span class="hl-1">: </span><span class="hl-2">Create Documentation</span><br/><span class="hl-3">on</span><span class="hl-1">: </span><span class="hl-2">push</span><br/><span class="hl-0">jobs</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">build_and_deploy_docs</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">runs-on</span><span class="hl-1">: </span><span class="hl-2">ubuntu-latest</span><br/><span class="hl-1"> </span><span class="hl-0">name</span><span class="hl-1">: </span><span class="hl-2">Build Doxygen documentation and deploy</span><br/><span class="hl-1"> </span><span class="hl-0">steps</span><span class="hl-1">:</span><br/><span class="hl-1"> - </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">actions/checkout@v4</span><br/><span class="hl-1"> - </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">awalsh128/cache-apt-pkgs-action@latest</span><br/><span class="hl-1"> </span><span class="hl-0">with</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">packages</span><span class="hl-1">: </span><span class="hl-2">dia doxygen doxygen-doc doxygen-gui doxygen-latex graphviz mscgen</span><br/><span class="hl-1"> </span><span class="hl-0">version</span><span class="hl-1">: </span><span class="hl-4">1.0</span><br/><br/><span class="hl-1"> - </span><span class="hl-0">name</span><span class="hl-1">: </span><span class="hl-2">Build</span><br/><span class="hl-1"> </span><span class="hl-0">run</span><span class="hl-1">: </span><span class="hl-5">|</span><br/><span class="hl-2"> cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} </span><br/><span class="hl-2"> cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}</span><br/><br/><span class="hl-1"> - </span><span class="hl-0">name</span><span class="hl-1">: </span><span class="hl-2">Deploy</span><br/><span class="hl-1"> </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">JamesIves/github-pages-deploy-action@4.1.5</span><br/><span class="hl-1"> </span><span class="hl-0">with</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">branch</span><span class="hl-1">: </span><span class="hl-2">gh-pages</span><br/><span class="hl-1"> </span><span class="hl-0">folder</span><span class="hl-1">: </span><span class="hl-2">${{github.workspace}}/build/website</span>
|
||||
</code><button type="button">Copy</button></pre>
|
||||
|
||||
<pre><code class="yaml"><span class="hl-1">---</span><br/><span class="hl-0">install_doxygen_deps</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">runs-on</span><span class="hl-1">: </span><span class="hl-2">ubuntu-latest</span><br/><span class="hl-1"> </span><span class="hl-0">steps</span><span class="hl-1">:</span><br/><span class="hl-1"> - </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">actions/checkout@v4</span><br/><span class="hl-1"> - </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">awalsh128/cache-apt-pkgs-action@latest</span><br/><span class="hl-1"> </span><span class="hl-0">with</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">packages</span><span class="hl-1">: </span><span class="hl-2">dia doxygen doxygen-doc doxygen-gui doxygen-latex graphviz mscgen</span><br/><span class="hl-1"> </span><span class="hl-0">version</span><span class="hl-1">: </span><span class="hl-4">1.0</span>
|
||||
</code><button type="button">Copy</button></pre>
|
||||
|
||||
<h2 id="caveats" class="tsd-anchor-link">Caveats<a href="#caveats" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
||||
<h3 id="non-file-dependencies" class="tsd-anchor-link">Non-file Dependencies<a href="#non-file-dependencies" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>This action is based on the principle that most packages can be cached as a fileset. There are situations though where this is not enough.</p>
|
||||
<ul>
|
||||
<li>Pre and post installation scripts needs to be ran from <code>/var/lib/dpkg/info/{package name}.[preinst, postinst]</code>.</li>
|
||||
<li>The Debian package database needs to be queried for scripts above (i.e. <code>dpkg-query</code>).</li>
|
||||
</ul>
|
||||
<p>The <code>execute_install_scripts</code> argument can be used to attempt to execute the install scripts but they are no guaranteed to resolve the issue.</p>
|
||||
<pre><code class="yaml"><span class="hl-1">- </span><span class="hl-0">uses</span><span class="hl-1">: </span><span class="hl-2">awalsh128/cache-apt-pkgs-action@latest</span><br/><span class="hl-1"> </span><span class="hl-0">with</span><span class="hl-1">:</span><br/><span class="hl-1"> </span><span class="hl-0">packages</span><span class="hl-1">: </span><span class="hl-2">mypackage</span><br/><span class="hl-1"> </span><span class="hl-0">version</span><span class="hl-1">: </span><span class="hl-4">1.0</span><br/><span class="hl-1"> </span><span class="hl-0">execute_install_scripts</span><span class="hl-1">: </span><span class="hl-3">true</span>
|
||||
</code><button type="button">Copy</button></pre>
|
||||
|
||||
<p>If this does not solve your issue, you will need to run <code>apt-get install</code> as a separate step for that particular package unfortunately.</p>
|
||||
<pre><code class="yaml"><span class="hl-0">run</span><span class="hl-1">: </span><span class="hl-2">apt-get install mypackage</span><br/><span class="hl-0">shell</span><span class="hl-1">: </span><span class="hl-2">bash</span>
|
||||
</code><button type="button">Copy</button></pre>
|
||||
|
||||
<p>Please reach out if you have found a workaround for your scenario and it can be generalized. There is only so much this action can do and can't get into the area of reverse engineering Debian package manager. It would be beyond the scope of this action and may result in a lot of extended support and brittleness. Also, it would be better to contribute to Debian packager instead at that point.</p>
|
||||
<p>For more context and information see <a href="https://github.com/awalsh128/cache-apt-pkgs-action/issues/57#issuecomment-1321024283">issue #57</a> which contains the investigation and conclusion.</p>
|
||||
<h3 id="cache-limits" class="tsd-anchor-link">Cache Limits<a href="#cache-limits" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
|
||||
<p>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. To get more information on how to access and manage your actions's caches, see <a href="https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#viewing-cache-entries">GitHub Actions / Using workflows / Cache dependencies</a>.</p>
|
||||
</div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#cache-apt-pkgs-action"><span>cache-<wbr/>apt-<wbr/>pkgs-<wbr/>action</span></a><ul><li><a href="#documentation"><span>Documentation</span></a></li><li><a href="#usage"><span>Usage</span></a></li><li><ul><li><a href="#pre-requisites"><span>Pre-<wbr/>requisites</span></a></li><li><a href="#versions"><span>Versions</span></a></li><li><a href="#inputs"><span>Inputs</span></a></li><li><a href="#outputs"><span>Outputs</span></a></li><li><a href="#security-compliance"><span>Security <wbr/>Compliance</span></a></li><li><ul><li><a href="#features"><span>Features</span></a></li><li><a href="#usage-recommendations"><span>Usage <wbr/>Recommendations</span></a></li></ul></li><li><a href="#cache-scopes"><span>Cache scopes</span></a></li><li><a href="#example-workflow"><span>Example workflow</span></a></li></ul></li><li><a href="#caveats"><span>Caveats</span></a></li><li><ul><li><a href="#non-file-dependencies"><span>Non-<wbr/>file <wbr/>Dependencies</span></a></li><li><a href="#cache-limits"><span>Cache <wbr/>Limits</span></a></li></ul></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">cache-apt-pkgs-action</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
|
||||
6
docs/api/interfaces/action.ActionInputs.html
Normal file
6
docs/api/interfaces/action.ActionInputs.html
Normal file
File diff suppressed because one or more lines are too long
4
docs/api/interfaces/action.ActionOutputs.html
Normal file
4
docs/api/interfaces/action.ActionOutputs.html
Normal file
File diff suppressed because one or more lines are too long
27
docs/api/media/V2_FAQ.MD
Normal file
27
docs/api/media/V2_FAQ.MD
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# cache-apt-pkgs-action - Version 2 FAQ
|
||||
|
||||
## Why did you create a new version
|
||||
|
||||
### Bash Scripts
|
||||
|
||||
Bash shell scripting grew in complexity and became very unreadable. The action needed higher level language idioms like array and map handling, complex pattern matching, and complex text processing.
|
||||
|
||||
### Language Choice
|
||||
|
||||
Languages like Python, Go, Rust, etc. have performance and writeability trade offs that would greatly improve this action, but ultimately Typescript was chosen because:
|
||||
|
||||
- it is the most performant and well supported for GitHub actions;
|
||||
- native strongly types libraries for action args and actions like caching;
|
||||
- provides a balance of code comprehension for contributors and performance; and
|
||||
- allows for better integration, CI, regression testing, and release workflows.
|
||||
|
||||
## Where did all the APT functionality go?
|
||||
|
||||
Since this has been a complex part of the codebase, I decided to separate the concern as its own library. This can now be found in [npm/ts-apt](https://www.npmjs.com/package/ts-apt). For ease of use there is an option to bring in the workspace for inline source so it can be debugged and then committed to the [ts-apt](http://github.com/awalsh128/ts-apt) repository.
|
||||
|
||||
## How do I start using this?
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This is still in beta so use at your own risk!
|
||||
|
||||
For now you can use the `v2.*` release tags (pinning also supported). Once this version has had time to soak it will be released as the latest. `v1.*` will still get updates but in maintenance mode.
|
||||
1
docs/api/modules.html
Normal file
1
docs/api/modules.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/modules/action.html
Normal file
1
docs/api/modules/action.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/modules/index.html
Normal file
1
docs/api/modules/index.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>index | cache-apt-pkgs-action</title><meta name="description" content="Documentation for cache-apt-pkgs-action"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">cache-apt-pkgs-action</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">index</a></li></ul><h1>Module index</h1></div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">cache-apt-pkgs-action</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
|
||||
1
docs/api/modules/io.html
Normal file
1
docs/api/modules/io.html
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/modules/manifest.html
Normal file
1
docs/api/modules/manifest.html
Normal file
File diff suppressed because one or more lines are too long
1301
package-lock.json
generated
1301
package-lock.json
generated
File diff suppressed because it is too large
Load diff
22
package.json
22
package.json
|
|
@ -1,38 +1,38 @@
|
|||
{
|
||||
"name": "cache-apt-pkgs-action",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"description": "GitHub Action to install and cache APT packages",
|
||||
"author": "Andrew Walsh",
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
"node": ">=24"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare:ts-apt": "cd ../ts-apt && npx tsc -p tsconfig.build.json",
|
||||
"postinstall": "npm run prepare:ts-apt",
|
||||
"prelint": "npm run prepare:ts-apt",
|
||||
"pretypecheck": "npm run prepare:ts-apt",
|
||||
"pretest": "npm run prepare:ts-apt",
|
||||
"prebuild": "npm run prepare:ts-apt",
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"clean": "rm -rf dist coverage",
|
||||
"lint": "eslint src test --ext .ts",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"test": "vitest run"
|
||||
"typecoverage": "type-coverage --at-least 95",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"docs:api": "typedoc --entryPointStrategy expand --entryPoints src --out docs/api",
|
||||
"release:preflight": "node ./dev_scripts/release-preflight.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/cache": "^6.1.0",
|
||||
"@actions/core": "^1.11.1",
|
||||
"tar": "^7.4.3",
|
||||
"ts-apt": "file:../ts-apt",
|
||||
"ts-apt": "^0.1.0",
|
||||
"winston": "^3.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.15.30",
|
||||
"@types/node": "^22.20.0",
|
||||
"@typescript-eslint/parser": "^8.46.3",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"eslint": "^9.31.0",
|
||||
"type-coverage": "^2.29.7",
|
||||
"typedoc": "^0.28.19",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.2.4"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import cache from "@actions/cache";
|
||||
import * as cache from "@actions/cache";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import {
|
||||
createPackageManager,
|
||||
type AptPackageManager,
|
||||
type PackageManager,
|
||||
type CommandRunner,
|
||||
DefaultCommandRunner,
|
||||
} from "../../ts-apt/dist/index.js";
|
||||
type PackageManager,
|
||||
} from "../node_modules/ts-apt/dist/index.js";
|
||||
import { type PackageName } from "../node_modules/ts-apt/dist/types.js";
|
||||
import { isAptListsFresh } from "./io.js";
|
||||
import { readManifest, writeManifest } from "./manifest.js";
|
||||
import { readManifestAsCsv, writeManifest } from "./manifest.js";
|
||||
import * as tar from "tar";
|
||||
import winston from "winston";
|
||||
|
||||
|
|
@ -19,6 +19,10 @@ type TarModule = typeof import("tar");
|
|||
|
||||
type EmptyPackageBehavior = "error" | "warn" | "ignore";
|
||||
|
||||
const FORCE_UPDATE_INCREMENT = "4";
|
||||
const CACHE_DIRNAME = "cache-apt-pkgs";
|
||||
const CACHE_PREFIX = "cache-apt-pkgs_";
|
||||
|
||||
export interface ActionInputs {
|
||||
readonly packages: string;
|
||||
readonly version: string;
|
||||
|
|
@ -33,25 +37,24 @@ export interface ActionOutputs {
|
|||
readonly allPackageVersionList: string;
|
||||
}
|
||||
|
||||
export class ActionPackageName implements Comparable<ActionPackageName> {
|
||||
export class ActionPackageName implements PackageName {
|
||||
constructor(
|
||||
readonly name: string,
|
||||
readonly version?: string,
|
||||
readonly distro?: string,
|
||||
) {}
|
||||
|
||||
serialize() {
|
||||
if (this.version) {
|
||||
return this.name + "=" + this.version;
|
||||
}
|
||||
return this.name;
|
||||
serialize(): string {
|
||||
return this.version ? `${this.name}=${this.version}` : this.name;
|
||||
}
|
||||
}
|
||||
|
||||
export function deserializePackageName(text: string): ActionPackageName | null {
|
||||
const [name, version] = text.split("=");
|
||||
function toPackageName(packageSpecifier: string): ActionPackageName {
|
||||
const [name, version] = packageSpecifier.split("=");
|
||||
if (!name) {
|
||||
return null;
|
||||
throw new Error("Package name cannot be empty.");
|
||||
}
|
||||
|
||||
return new ActionPackageName(name, version);
|
||||
}
|
||||
|
||||
|
|
@ -68,9 +71,7 @@ export function parseBoolean(value: string, fieldName: string): boolean {
|
|||
);
|
||||
}
|
||||
|
||||
export function normalizeInputPackages(
|
||||
inputPackages: string,
|
||||
): ActionPackageName[] {
|
||||
export function normalizeInputPackages(inputPackages: string): string[] {
|
||||
return inputPackages
|
||||
.replace(/[,\\]/g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
|
|
@ -78,9 +79,7 @@ export function normalizeInputPackages(
|
|||
.split(" ")
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.map((part) => deserializePackageName(part))
|
||||
.filter((pkg): pkg is ActionPackageName => pkg !== null);
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
export class ActionRunner {
|
||||
|
|
@ -102,7 +101,7 @@ export class ActionRunner {
|
|||
return parseBoolean(value, fieldName);
|
||||
}
|
||||
|
||||
normalizeInputPackages(inputPackages: string): ActionPackageName[] {
|
||||
normalizeInputPackages(inputPackages: string): string[] {
|
||||
return normalizeInputPackages(inputPackages);
|
||||
}
|
||||
|
||||
|
|
@ -110,27 +109,31 @@ export class ActionRunner {
|
|||
packageManager: PackageManager,
|
||||
packageName: string,
|
||||
): Promise<string> {
|
||||
const packageInfo = await packageManager.getPackageInfo([packageName]);
|
||||
const packageInfo = await packageManager.getPackageInfo([
|
||||
toPackageName(packageName),
|
||||
]);
|
||||
const version = packageInfo[0]?.version;
|
||||
if (!version) {
|
||||
throw new Error(
|
||||
`Unable to resolve package version for '${packageName}'.`,
|
||||
);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
async normalizePackagesWithVersions(
|
||||
packageManager: PackageManager,
|
||||
inputPackages: string,
|
||||
): Promise<ActionPackageName[]> {
|
||||
): Promise<string[]> {
|
||||
const raw = this.normalizeInputPackages(inputPackages);
|
||||
const packages = await Promise.all(
|
||||
raw.map(async (pkg) => {
|
||||
if (pkg.version) {
|
||||
return pkg.serialize();
|
||||
if (pkg.includes("=")) {
|
||||
return pkg;
|
||||
}
|
||||
return `${pkg.name}=${await this.resolvePackageVersion(packageManager, pkg.name)}`;
|
||||
|
||||
return `${pkg}=${await this.resolvePackageVersion(packageManager, pkg)}`;
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
@ -165,9 +168,7 @@ export class ActionRunner {
|
|||
normalizedPackages: string[],
|
||||
version: string,
|
||||
): Promise<string> {
|
||||
const architecture = await (
|
||||
await this.commandRunner.run("arch")
|
||||
).stdout.trim();
|
||||
const architecture = (await this.commandRunner.run("arch")).stdout.trim();
|
||||
let value = `${normalizedPackages.join(" ")} @ ${version} ${FORCE_UPDATE_INCREMENT}`;
|
||||
|
||||
if (architecture !== "x86_64") {
|
||||
|
|
@ -209,7 +210,9 @@ export class ActionRunner {
|
|||
packageManager: PackageManager,
|
||||
packageName: string,
|
||||
): Promise<string[]> {
|
||||
const files = (await packageManager.listInstalledFiles(packageName))
|
||||
const files = (
|
||||
await packageManager.listInstalledFiles(toPackageName(packageName))
|
||||
)
|
||||
.filter((filePath) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return false;
|
||||
|
|
@ -251,10 +254,11 @@ export class ActionRunner {
|
|||
packageManager: PackageManager,
|
||||
): Promise<void> {
|
||||
await this.updateAptLists(packageManager);
|
||||
|
||||
writeManifest(path.join(cacheDir, "manifest_main.log"), packages);
|
||||
|
||||
const installedPackages = await packageManager.install(packages);
|
||||
const installedPackages = await packageManager.install(
|
||||
packages.map(toPackageName),
|
||||
);
|
||||
|
||||
const manifestAll: string[] = [];
|
||||
for (const pkg of installedPackages) {
|
||||
|
|
@ -394,10 +398,10 @@ export class ActionRunner {
|
|||
|
||||
return {
|
||||
cacheHit,
|
||||
packageVersionList: readManifest(
|
||||
packageVersionList: readManifestAsCsv(
|
||||
path.join(cacheDir, "manifest_main.log"),
|
||||
),
|
||||
allPackageVersionList: readManifest(
|
||||
allPackageVersionList: readManifestAsCsv(
|
||||
path.join(cacheDir, "manifest_all.log"),
|
||||
),
|
||||
};
|
||||
|
|
@ -408,13 +412,7 @@ export async function runAction(
|
|||
inputs: ActionInputs,
|
||||
logger: winston.Logger,
|
||||
): Promise<ActionOutputs> {
|
||||
const packageManager = (await createPackageManager(
|
||||
true,
|
||||
logger,
|
||||
logger,
|
||||
)) as AptPackageManager;
|
||||
const commandRunner = new DefaultCommandRunner(logger, logger);
|
||||
const actionRunner = new ActionRunner(commandRunner, tar, logger);
|
||||
|
||||
return await actionRunner.runAction(inputs);
|
||||
}
|
||||
|
|
|
|||
52
src/io.ts
52
src/io.ts
|
|
@ -1,15 +1,21 @@
|
|||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as crypto from "crypto";
|
||||
import * as os from "os";
|
||||
import { type CommandRunner } from "../../ts-apt/dist/index.js";
|
||||
import * as crypto from "node:crypto";
|
||||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { type CommandRunner } from "../node_modules/ts-apt/dist/index.js";
|
||||
|
||||
const FORCE_UPDATE_INCREMENT = "4";
|
||||
const CACHE_DIRNAME = "cache-apt-pkgs";
|
||||
const CACHE_PREFIX = "cache-apt-pkgs_";
|
||||
|
||||
export function isAptListsFresh(): boolean {
|
||||
const aptListsPath = "/var/lib/apt/lists";
|
||||
const maxDepth = 5;
|
||||
|
||||
function search(currentPath: string, currentDepth: number): boolean {
|
||||
if (currentDepth > maxDepth) return false;
|
||||
if (currentDepth > maxDepth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const stats = fs.statSync(currentPath);
|
||||
|
|
@ -24,9 +30,10 @@ export function isAptListsFresh(): boolean {
|
|||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore permission errors or inaccessible paths
|
||||
} catch {
|
||||
// Ignore permission errors or inaccessible paths.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -44,22 +51,13 @@ export class Package {
|
|||
}
|
||||
}
|
||||
|
||||
const FORCE_UPDATE_INCREMENT = "4";
|
||||
const CACHE_DIRNAME = "cache-apt-pkgs";
|
||||
const CACHE_PREFIX = "cache-apt-pkgs_";
|
||||
|
||||
export class CacheKey {
|
||||
readonly version: string,
|
||||
constructor(
|
||||
readonly version: string,
|
||||
readonly forceUpdateIncrement: string,
|
||||
readonly arch: string,
|
||||
readonly normalizedPackages: PackageName[],
|
||||
|
||||
constructor(version: string, forceUpdateIncrement: string, arch: string, normalizedPackages: PackageName[]) {
|
||||
this.version = version;
|
||||
this.forceUpdateIncrement = forceUpdateIncrement;
|
||||
this.arch = arch;
|
||||
this.normalizedPackages = normalizedPackages;
|
||||
}
|
||||
readonly normalizedPackages: string[],
|
||||
) {}
|
||||
|
||||
serialize(): string {
|
||||
return `${this.version}|${this.forceUpdateIncrement}|${this.arch}|${this.normalizedPackages.join(",")}`;
|
||||
|
|
@ -71,13 +69,13 @@ export function deserializeCacheKey(serialized: string): CacheKey {
|
|||
if (parts.length !== 4) {
|
||||
throw new Error(`Invalid serialized cache key: ${serialized}`);
|
||||
}
|
||||
|
||||
const [version, forceUpdateIncrement, arch, normalizedPackagesStr] = parts;
|
||||
const normalizedPackages = normalizedPackagesStr!.split(",");
|
||||
return new CacheKey(
|
||||
version!,
|
||||
forceUpdateIncrement!,
|
||||
arch!,
|
||||
normalizedPackages,
|
||||
normalizedPackagesStr!.split(","),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,10 +88,12 @@ export class Cache {
|
|||
this.commandRunner = commandRunner;
|
||||
}
|
||||
|
||||
get path(): string {
|
||||
return this.cachePath;
|
||||
}
|
||||
|
||||
async getKey(normalizedPackages: string[], version: string): Promise<string> {
|
||||
const architecture = await (
|
||||
await this.commandRunner.run("arch")
|
||||
).stdout.trim();
|
||||
const architecture = (await this.commandRunner.run("arch")).stdout.trim();
|
||||
let value = `${normalizedPackages.join(" ")} @ ${version} ${FORCE_UPDATE_INCREMENT}`;
|
||||
|
||||
if (architecture !== "x86_64") {
|
||||
|
|
|
|||
|
|
@ -1,35 +1,21 @@
|
|||
import { ActionPackageName } from "./action.js";
|
||||
import fs from "fs";
|
||||
import { CacheKey, deserializeCacheKey } from "./io.js";
|
||||
import fs from "node:fs";
|
||||
|
||||
class ManifestEntry {
|
||||
readonly packageName: ActionPackageName;
|
||||
readonly filepaths: string[];
|
||||
|
||||
constructor(packageName: ActionPackageName, filepaths: string[]) {
|
||||
this.packageName = packageName;
|
||||
this.filepaths = filepaths;
|
||||
}
|
||||
export function writeManifest(filePath: string, entries: string[]): void {
|
||||
const normalized = [...entries]
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
fs.writeFileSync(filePath, normalized.join("\n"), "utf8");
|
||||
}
|
||||
|
||||
class Manifest {
|
||||
readonly cacheTimestamp: string;
|
||||
readonly cacheTimestampMs: string;
|
||||
readonly cacheKey: CacheKey;
|
||||
readonly entries: ManifestEntry[];
|
||||
|
||||
constructor(cacheDate: Date, cacheKey: CacheKey, entries: ManifestEntry[]) {
|
||||
this.cacheTimestamp = cacheDate.toISOString();
|
||||
this.cacheTimestampMs = new Date(this.cacheTimestamp).getTime().toString();
|
||||
this.cacheKey = cacheKey;
|
||||
this.entries = entries;
|
||||
export function readManifestAsCsv(filePath: string): string {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
readFromFile(filepath: string): Manifest | null {
|
||||
fs.readFileSync(file, JSON.parse())
|
||||
}
|
||||
|
||||
writeToFile(filePath: string): void {
|
||||
fs.writeFileSync(filePath, JSON.stringify(this, null, 2), "utf-8");
|
||||
}
|
||||
return fs
|
||||
.readFileSync(filePath, "utf8")
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.join(",");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,5 +6,10 @@ export default defineConfig({
|
|||
environment: "node",
|
||||
include: ["test/**/*.test.ts"],
|
||||
testTimeout: 120000,
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
reporter: ["text", "lcov", "json"],
|
||||
reportsDirectory: "coverage",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue