This commit is contained in:
Ian Butterworth
2023-11-27 10:05:33 -05:00
committed by GitHub
parent 3466649946
commit 67f1f75048
4 changed files with 59 additions and 9 deletions

View File

@@ -14,6 +14,11 @@ on:
- 'handle_caches.jl' - 'handle_caches.jl'
- '.github/**' - '.github/**'
# needed to allow julia-actions/cache to delete old caches that it has created
permissions:
actions: write
contents: read
jobs: jobs:
generate-key: generate-key:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -11,6 +11,11 @@ name: CI
on: [push, pull_request] on: [push, pull_request]
# needed to allow julia-actions/cache to delete old caches that it has created
permissions:
actions: write
contents: read
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -34,7 +39,7 @@ However note that caching the registries may mean that the registry will not be
### Optional Inputs ### Optional Inputs
- `cache-name` - The cache key prefix. Defaults to `julia-cache`. The key body automatically includes matrix vars and the OS. Include any other parameters/details in this prefix to ensure one unique cache key per concurrent job type. - `cache-name` - The cache key prefix. Defaults to `julia-cache-${{ github.workflow }}-${{ github.job }}`. The key body automatically includes matrix vars and the OS. Include any other parameters/details in this prefix to ensure one unique cache key per concurrent job type.
- `include-matrix` - Whether to include the matrix values when constructing the cache key. Defaults to `true`. - `include-matrix` - Whether to include the matrix values when constructing the cache key. Defaults to `true`.
- `cache-artifacts` - Whether to cache `~/.julia/artifacts/`. Defaults to `true`. - `cache-artifacts` - Whether to cache `~/.julia/artifacts/`. Defaults to `true`.
- `cache-packages` - Whether to cache `~/.julia/packages/`. Defaults to `true`. - `cache-packages` - Whether to cache `~/.julia/packages/`. Defaults to `true`.
@@ -43,6 +48,7 @@ However note that caching the registries may mean that the registry will not be
- `cache-scratchspaces` - Whether to cache `~/.julia/scratchspaces/`. Defaults to `true`. - `cache-scratchspaces` - Whether to cache `~/.julia/scratchspaces/`. Defaults to `true`.
- `cache-log` - Whether to cache `~/.julia/logs/`. Defaults to `true`. Helps auto-`Pkg.gc()` keep the cache small. - `cache-log` - Whether to cache `~/.julia/logs/`. Defaults to `true`. Helps auto-`Pkg.gc()` keep the cache small.
- `delete-old-caches` - Whether to delete old caches for the given key. Defaults to `true` - `delete-old-caches` - Whether to delete old caches for the given key. Defaults to `true`
- `token` - A github PAT. Defaults to `github.token`. Requires `repo` scope to enable the deletion of old caches.
### Outputs ### Outputs
@@ -79,6 +85,18 @@ This action automatically deletes old caches that match the first 4 fields of th
Which means your caches files will not grow needlessly. Github also deletes cache files after Which means your caches files will not grow needlessly. Github also deletes cache files after
[90 days which can be increased in private repos to up to 400 days](https://docs.github.com/en/organizations/managing-organization-settings/configuring-the-retention-period-for-github-actions-artifacts-and-logs-in-your-organization) [90 days which can be increased in private repos to up to 400 days](https://docs.github.com/en/organizations/managing-organization-settings/configuring-the-retention-period-for-github-actions-artifacts-and-logs-in-your-organization)
> [!NOTE]
> To allow deletion of caches you will likely need to grant the following to the default
> `GITHUB_TOKEN` by adding this to your yml:
> ```
> permissions:
> actions: write
> contents: read
> ```
> (Note this won't work for fork PRs but should once merged)
> Or provide a token with `repo` scope via the `token` input option.
> See https://cli.github.com/manual/gh_cache_delete
To disable deletion set input `delete-old-caches: 'false'`. To disable deletion set input `delete-old-caches: 'false'`.
### Cache Garbage Collection ### Cache Garbage Collection

View File

@@ -9,7 +9,7 @@ branding:
inputs: inputs:
cache-name: cache-name:
description: 'The cache key prefix. Unless disabled the key body automatically includes matrix vars, and the OS. Include any other parameters/details in this prefix to ensure one unique cache key per concurrent job type.' description: 'The cache key prefix. Unless disabled the key body automatically includes matrix vars, and the OS. Include any other parameters/details in this prefix to ensure one unique cache key per concurrent job type.'
default: 'julia-cache' default: 'julia-cache-${{ github.workflow }}-${{ github.job }}'
include-matrix: include-matrix:
description: 'Whether to include the matrix values when constructing the cache key' description: 'Whether to include the matrix values when constructing the cache key'
default: 'true' default: 'true'
@@ -34,6 +34,9 @@ inputs:
delete-old-caches: delete-old-caches:
description: 'Whether to delete old caches for the given key' description: 'Whether to delete old caches for the given key'
default: 'true' default: 'true'
token:
description: 'A github PAT. Requires `repo` scope to enable the deletion of old caches'
default: '${{ github.token }}'
outputs: outputs:
cache-hit: cache-hit:
@@ -65,7 +68,7 @@ runs:
# with a matrix. # with a matrix.
- id: keys - id: keys
run: | run: |
MATRIX_STRING="${{ join(matrix.*, '-') }}" [ "${{ inputs.include-matrix }}" == "true" ] && MATRIX_STRING="${{ join(matrix.*, '-') }}"
[ -n "$MATRIX_STRING" ] && MATRIX_STRING="-${MATRIX_STRING}" [ -n "$MATRIX_STRING" ] && MATRIX_STRING="-${MATRIX_STRING}"
RESTORE_KEY="${{ inputs.cache-name }}-${{ runner.os }}${MATRIX_STRING}_" RESTORE_KEY="${{ inputs.cache-name }}-${{ runner.os }}${MATRIX_STRING}_"
echo "restore-key=${RESTORE_KEY}" >> $GITHUB_OUTPUT echo "restore-key=${RESTORE_KEY}" >> $GITHUB_OUTPUT
@@ -87,6 +90,10 @@ runs:
restore-keys: ${{ steps.keys.outputs.restore-key }} restore-keys: ${{ steps.keys.outputs.restore-key }}
enableCrossOsArchive: false enableCrossOsArchive: false
- name: list restored depot directory sizes
run: du -shc ~/.julia/* || true
shell: bash
# github and actions/cache doesn't provide a way to update a cache at a given key, so we delete any # github and actions/cache doesn't provide a way to update a cache at a given key, so we delete any
# that match the restore key just before saving the new cache # that match the restore key just before saving the new cache
- uses: pyTooling/Actions/with-post-step@adef08d3bdef092282614f3b683897cefae82ee3 - uses: pyTooling/Actions/with-post-step@adef08d3bdef092282614f3b683897cefae82ee3
@@ -94,10 +101,10 @@ runs:
with: with:
# seems like there has to be a `main` step in this action. Could list caches for info if we wanted # seems like there has to be a `main` step in this action. Could list caches for info if we wanted
# main: julia ${{ github.action_path }}/handle_caches.jl "${{ github.repository }}" "list" # main: julia ${{ github.action_path }}/handle_caches.jl "${{ github.repository }}" "list"
main: du -shc ~/.julia/* || true main: echo ""
post: julia ${{ github.action_path }}/handle_caches.jl "${{ github.repository }}" "rm" "${{ steps.keys.outputs.restore-key }}" post: julia ${{ github.action_path }}/handle_caches.jl "${{ github.repository }}" "rm" "${{ steps.keys.outputs.restore-key }}"
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ inputs.token }}
- id: hit - id: hit
run: echo "cache-hit=$CACHE_HIT" >> $GITHUB_OUTPUT run: echo "cache-hit=$CACHE_HIT" >> $GITHUB_OUTPUT

View File

@@ -9,6 +9,7 @@ function handle_caches()
run(`gh cache list --limit 100 --repo $repo`) run(`gh cache list --limit 100 --repo $repo`)
elseif func == "rm" elseif func == "rm"
caches = String[] caches = String[]
failed = String[]
for _ in 1:5 # limit to avoid accidental rate limiting for _ in 1:5 # limit to avoid accidental rate limiting
hits = split(strip(read(`gh cache list --limit 100 --repo $repo`, String)), keepempty=false) hits = split(strip(read(`gh cache list --limit 100 --repo $repo`, String)), keepempty=false)
search_again = length(hits) == 100 search_again = length(hits) == 100
@@ -18,18 +19,37 @@ function handle_caches()
for c in hits for c in hits
try try
run(`gh cache delete $(split(c)[1]) --repo $repo`) run(`gh cache delete $(split(c)[1]) --repo $repo`)
push!(caches, c)
catch e catch e
@error e @error e
push!(failed, c)
end end
end end
append!(caches, hits)
search_again || break search_again || break
end end
if isempty(caches) if isempty(failed) && isempty(caches)
println("No existing caches found for restore key `$restore_key`") println("No existing caches found for restore key `$restore_key`")
else else
println("$(length(caches)) existing caches deleted that match restore key `$restore_key`:") if !isempty(failed)
println.(caches) println("Failed to delete $(length(failed)) existing caches for restore key `$restore_key`")
println.(failed)
@info """
To delete caches you need to grant the following to the default `GITHUB_TOKEN` by adding
this to your yml:
```
permissions:
actions: write
contents: read
```
(Note this won't work for fork PRs but should once merged)
Or provide a token with `repo` scope via the `token` input option.
See https://cli.github.com/manual/gh_cache_delete
"""
end
if !isempty(caches)
println("$(length(caches)) existing caches deleted that match restore key `$restore_key`:")
println.(caches)
end
end end
else else
throw(ArgumentError("Unexpected second argument: $func")) throw(ArgumentError("Unexpected second argument: $func"))