155

I am working on an R package and using GitHub Action (GHA) as a Continuous Integration (CI) provider. I cache R packages (dependencies) by using actions/cache. And now I want to clear all cache. How can I do that?


A part of GHA Workflow I use:
on: push name: R-CMD-check jobs: R-CMD-check: runs-on: ${{ matrix.config.os }} name: ${{ matrix.config.os }} (${{ matrix.config.r }}) strategy: fail-fast: false matrix: config: # - {os: windows-latest, r: 'devel'} - {os: macOS-latest, r: 'release'} env: R_REMOTES_NO_ERRORS_FROM_WARNINGS: true RSPM: ${{ matrix.config.rspm }} GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 - uses: r-lib/actions/setup-r@master - name: Query dependencies run: | repos <- c("https://r-hyperspec.github.io/hySpc.pkgs/", getOption("repos")) saveRDS("remotes::dev_package_deps(dependencies = TRUE)", ".github/depends.Rds", version = 2) writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") shell: Rscript {0} - name: Cache R packages if: runner.os != 'Windows' uses: actions/cache@v1 with: path: ${{ env.R_LIBS_USER }} key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- - name: Install dependencies run: remotes::install_deps(dependencies = TRUE) shell: Rscript {0} - name: Session info run: | options(width = 100) pkgs <- installed.packages()[, "Package"] sessioninfo::session_info(pkgs, include_base = TRUE) shell: Rscript {0} 
2

10 Answers 10

237

CLI (Update July 11, 2023)

As already described in VonC's comment, the GitHub CLI now has a dedicated cache top-level command:

  • List of caches for the current repository:

    $ gh cache list 
  • Delete a cache for the current repository by cache ID:

    $ gh cache delete <CACHE_ID> 

UI (Update October 20, 2022)

You can now manage caches via the UI:

https://github.com/<OWNER>/<REPO>/actions/caches 

REST API (Update June 27, 2022)

You can now manage caches via the GitHub Actions Cache API:

  • GET list of caches for a repository:

    $ curl \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token <TOKEN>" \ https://api.github.com/repos/<OWNER>/<REPO>/actions/caches 
  • DELETE a cache for a repository by cache ID:

    $ curl \ -X DELETE \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token <TOKEN>" \ https://api.github.com/repos/<OWNER>/<REPO>/actions/caches/<CACHE_ID> 

Alternatively, you can also use the GitHub CLI to interact with the API, using the gh-actions-cache extension.

Cache Key (Original Post November 13, 2020)

As pointed out in the corresponding issue, two practical workarounds can be used to force the use of a new cache. This is not exactly the same as clearing the current cache (with regards to the cache usage limits), but it does the job.

In order to do so, you have to change the cache key (and any restore-keys). Because if the key(s) is/are different, this is considered a cache miss and you start with a new one.

You can change the cache key either by modifying the workflow file directly, e.g., by adding a version number:

key: ${{ runner.os }}-mycache-v1-${{ hashFiles(...) }} 

If you now want to use a new cache, all you have to do is to commit a different version number:

key: ${{ runner.os }}-mycache-v2-${{ hashFiles(...) }} 

If you don't want to modify the workflow file and prefer using the UI, you can abuse secrets:

key: ${{ runner.os }}-mycache-${{ secrets.CACHE_VERSION }}-${{ hashFiles(...) }} 

Whenever the secret changes, a new cache will be used.

⚠️ WARNING: Secrets used for cache keys are "revealed" in the UI.

Sign up to request clarification or add additional context in comments.

7 Comments

It also seems like, if you re-run a different workflow on the same cache it get's updated.
@red-isso what exactly do you mean? If two (or more) different workflows share the same cache?
@beatngu13 that is a beautifully clever use of secrets for busting caches! Thank you!
Thanks for the answer. I guess yet another option would be using build parameters, via on/workflow_dispatch/CACHE_VERSION, so that one could set a new version when issuing a build manually.
@zakmck basically yes, but when the build isn't triggered manually and the cache version input is empty (or defaults to a certain value), then the old/corrupt cache is used again; at least until it is actually evicted. So, one could use this approach to make a quick test if the cache causes build issues. If that is the case, one still has to change the key(s) permanently.
|
27

You can clear all cache using the GitHub CLI with the following command, execute this from within the local directory where you cloned the repository:

gh cache delete --all 

The --all flag is documented in the manual for the CLI

-a, --all Delete all caches

Comments

26

This can be done from GH Actions as well.

name: Clear cache on: workflow_dispatch: permissions: actions: write jobs: clear-cache: runs-on: ubuntu-latest steps: - name: Clear cache uses: actions/github-script@v6 with: script: | console.log("About to clear") const caches = await github.rest.actions.getActionsCacheList({ owner: context.repo.owner, repo: context.repo.repo, }) for (const cache of caches.data.actions_caches) { console.log(cache) github.rest.actions.deleteActionsCacheById({ owner: context.repo.owner, repo: context.repo.repo, cache_id: cache.id, }) } console.log("Clear completed") 

Make sure it's merged to HEAD branch and trigger it manually from Actions or add your custom triggers.

5 Comments

Thanks, it works. However, if I understand correctly, this workflow must be in the main branch to be visible in the "Actions" tab to be run the first time.
Yes, that's how workflow_dispatch works. Any other trigger can be used as well, but only workflow_dispatch gives ability to trigger manually. For manual cache management there is a native UI available now: docs.github.com/en/actions/using-workflows/…
How can I remove caches based on 'created_at' key? Basically, I'm trying to remove the cache if it was created last week.
@ÖzerÖzdal Add if in the for loop and filter by cache.created_at. See docs.github.com/en/rest/actions/… for details. But why would you do that? GitHub will automatically remove them after 7 days of being unused: docs.github.com/en/actions/using-workflows/…
@lukee yes, I did it by running an if and for loop over cache.created_at. Because I have a package that I generate caches on weekly basis for the following week. So I remove old unused caches from the previous week by running a workflow that runs on daily basis.
11

You cannot force a clear cache currently and it seems there is an open feature request for it at the moment https://github.com/actions/cache/issues/2. If I were you, I would post the request there as well so that they know that more people want the feature implemented.

A few things to note about the action:

There are not parameters in the action and not even in the toolkit package that this action is build on top of.

Getting deep into the toolkit code they use a cache api url to do all the good stuff. This means we don't even know if that api supports it with the assumption that we try to test it out and see what else it provides by hitting it directly. Here is the line for the api call for which the base url is taken from env ACTIONS_CACHE_URL

https://github.com/actions/toolkit/blob/c2bc747506bf562195a02bd4fdb1ff2a95d8b7ed/packages/cache/src/internal/cacheHttpClient.ts#L44

npm package as reference https://www.npmjs.com/package/@actions/cache

If we take a step back for a moment and go back to the github docs now that we have looked deep into the action/cache code and how it works,

Per the github docs https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows

There are two things to note,

Once you create a cache, you cannot change the contents of an existing cache but you can create a new cache with a new key. 
GitHub will remove any cache entries that have not been accessed in over 7 days. 

Comments

11

Based @beatngu13 answer I've created Makefile target that remove all cache from Github Actions:

GH_REPO ?= ALLATRA-IT/ephyr # replace with your `org/repo` # Clear Github Acions usage cache. # # Need to install github cli first [https://cli.github.com/] and authorize # # Usage: # make gh.clear gh.clear: gh api --paginate -H "Accept: application/vnd.github+json" \ /repos/$(GH_REPO)/actions/caches \ | for ID in `jq '.actions_caches[].id'`; \ do echo "Deleting $$ID"; \ gh api --method DELETE /repos/$(GH_REPO)/actions/caches/$$ID | echo; done 

Need to install Github CLI and jq tool tools first. After install Github CLI you need to authorize with:

gh auth login 

1 Comment

Add --paginate to delete all caches, not just the first 30: gh api --paginate -H ...
8

One more easy and straightforward way to remove Actions' cache - Purge cache GH Action.

This action allows the cache of GitHub Actions to be automatically purged based on the last usage and configured TTL (default - 7 days).

Example:

name: Clear Cache on: schedule: - cron: '0 0 * * *' # Runs once a day (https://crontab.guru/once-a-day) jobs: clear: name: Clear cache runs-on: ubuntu-latest steps: - uses: MyAlbum/purge-cache@v1 with: max-age: 604800 # Cache max 7 days since last use (this is the default) 

The workflow above will run once a day and remove all the cache that was last used more than 7 days ago.

2 Comments

If I set max-age: 1 will MyAlbum/purge-cache@v1 purge the cache that is stored in GitHub immediately?
@bekanur98 it should purge all the cache that is older than 1 second
2

@GegznaV you can use something like tmate, and manually clear cache by sshing into a runner.

1 Comment

Please share more details. How exactly would that work?
2

keep the last cache with this bash function (add it to your .bashrc file)

function gh_clear_old_caches(){ GH_REPO='your_github_user/your_repository' echo "deleting all caches, except the last" gh api --paginate -H "Accept: application/vnd.github+json" \ "/repos/${GH_REPO}/actions/caches" \ | for ID in `jq '.actions_caches | sort_by(.id) | .[:-1][] | .id '`; \ do echo "Deleting cache id ${ID}"; \ gh api --method DELETE -H "Accept: application/vnd.github+json" "/repos/${GH_REPO}/actions/caches/${ID}" | echo; \ done } 

name completion works with bash functions as well:

gh_<tab> 

the addition in this one is that jq first sorts the result by id (assuming that the most recent one has the largest).

[:-1] means every id, except the last.

1 Comment

this good, leaving latest cache only. thanks bro
1

For anyone looking for a simple commandline solution, the following shell command will also do it. It requires the Github CLI + JQ:

gh api -H 'Accept: application/vnd.github+json' /repos/realm/realm-kotlin/actions/caches --paginate | jq -r '.actions_caches | .[].key' | sed -e 's/|/%7c/g' -e 's/\[/%5b/g' -e 's/\]/%5d/g' | xargs -I {} sh -c 'gh api --method DELETE -H "Accept: application/vnd.github+json" /repos/<OWNER>/<REPO>/actions/caches?key={} --silent'

In this case, I'm using sed to URL encode special characters in the key. I just needed to handle |, [ and ]. Others can be added as needed. See e.g. https://gist.github.com/jaytaylor/5a90c49e0976aadfe0726a847ce58736#file-url_encode-sh-L11

Comments

0

Here's another automated solution similar to @beatngu13's cache key invalidation method. This one uses a generated timestamp file that gets committed and then used in a hashFiles(...) prefix to the cache key.

Included is a set of GNU Makefile targets to make using this method very easy: make clear-github-cache

Note: Make sure each Makefile "recipe" section is indented with 1 tab character! StackOverflow converts tabs to spaces in the code block.

.github/clear_github_actions_cache: date +%s > .github/clear_github_actions_cache .PHONY: clean-github-cache-file clear-github-cache clear-github-cache: clean-github-cache-file .github/clear_github_actions_cache ## Force GitHub Actions Cache key to change for fresh CI run git add .github/clear_github_actions_cache git commit -m "Clear GitHub Actions Cache @ $$(cat .github/clear_github_actions_cache)" clean-github-cache-file: ## Remove GitHub Actions Cache timestamp invalidator file. [ -f '.github/clear_github_actions_cache' ] && rm -f '.github/clear_github_actions_cache' || true 

Then, inside the GitHub Actions workflow YAML, add a cache key prefix that uses the hash of this file:

 - name: Cache R packages if: runner.os != 'Windows' uses: actions/cache@v2 with: path: ${{ env.R_LIBS_USER }} key: ${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.github/clear_github_actions_cache') }}-${{ hashFiles('.github/R-version') }}-${{ hashFiles('.github/depends.Rds') }} restore-keys: | ${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.github/clear_github_actions_cache') }}-${{ hashFiles('.github/R-version') }}-${{ hashFiles('.github/depends.Rds') }} ${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.github/clear_github_actions_cache') }}-${{ hashFiles('.github/R-version') }}- ${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.github/clear_github_actions_cache') }}- 

Now just run:

make clear-github-cache 

This generates and commits a file, .github/clear_github_actions_cache, with Unix timestamp as contents. The hashFiles(...) cache key prefix uses this and will generate a unique hash of this file as a prefix to the rest of the cache / restore-key.

Next time you use git push, the cache key will be invalidated... effectively running GitHub Actions with an empty cache.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.