清除 GitHub Actions 中的缓存

111

我正在开发一个R包,并使用GitHub Action (GHA)作为持续集成 (CI) 提供者。我通过使用actions/cache缓存R包(依赖项)。现在我想清除所有缓存,我该如何做到这一点?


我使用的GHA Workflow的一部分:
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}

https://github.community/t/how-to-clear-cache-in-github-actions/129038/3 - GegznaV
3
清除缓存现在(2022年6月)已经成为可能。 - VonC
10个回答

156

更新(2023年7月11日)

正如VonC的回答中已经描述的那样,GitHub CLI现在有一个专门的cache顶级命令:

当前仓库的缓存列表: ``` $ gh cache list ```
通过缓存ID删除当前仓库的缓存: ``` $ gh cache delete ```

更新(2022年10月20日)

您现在可以通过用户界面管理缓存

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

更新(2022年6月27日)

现在您可以通过GitHub Actions缓存API管理缓存

获取存储库的缓存列表: ``` $ curl \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token " \ https://api.github.com/repos///actions/caches ```
通过缓存ID删除存储库的缓存: ``` $ curl \ -X DELETE \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token " \ https://api.github.com/repos///actions/caches/ ```
或者,您还可以使用GitHub CLI与API进行交互,使用gh-actions-cache扩展。
原始帖子(2020年11月13日)
正如在相应问题中指出的那样,有两种实用的解决方法可以强制使用新的缓存。这与清除当前缓存(关于缓存使用限制)不完全相同,但它可以完成工作。
为了做到这一点,您必须更改缓存键(和任何恢复键)。因为如果键是不同的,这被视为缓存未命中,您将从新的缓存开始。
您可以通过直接修改工作流文件来更改缓存键,例如,通过添加版本号:
key: ${{ runner.os }}-mycache-v1-${{ hashFiles(...) }}

如果你现在想使用一个新的缓存,你只需要提交一个不同的版本号即可。
key: ${{ runner.os }}-mycache-v2-${{ hashFiles(...) }}

如果您不想修改工作流文件,而更喜欢使用用户界面,您可以滥用secrets
key: ${{ runner.os }}-mycache-${{ secrets.CACHE_VERSION }}-${{ hashFiles(...) }}

每当密码更改时,将使用新的缓存。
⚠️ 警告:用于缓存密钥的密码在用户界面中被揭示。

似乎,如果您在相同的缓存上重新运行不同的工作流程,则会更新该缓存。 - red-isso
2
@beatngu13,这是一个非常巧妙的使用密钥来破解缓存的方法!谢谢你! - James
感谢您的回答。我想另一个选择是使用构建参数,通过 on/workflow_dispatch/CACHE_VERSION,这样当手动发起构建时,就可以设置一个新版本。 - zakmck
1
@zakmck 基本上是的,但当构建不是手动触发且缓存版本输入为空(或默认为某个值)时,旧/损坏的缓存会再次使用;至少直到它被实际驱逐。因此,可以使用这种方法快速测试缓存是否会导致构建问题。如果是这种情况,则仍然必须永久更改密钥。 - beatngu13
再次感谢。我认为需要一个无效选项或过期时间。 - zakmck
显示剩余2条评论

17

这也可以通过 GH Actions 完成。

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")

确保它已合并到HEAD分支,并从Actions手动触发或添加您自己的自定义触发器。


1
谢谢,它有效。但是,如果我理解正确的话,这个工作流必须在主分支中才能在“Actions”选项卡中可见,并且可以第一次运行。 - lorenzo-bettini
是的,这就是 workflow_dispatch 的工作原理。 也可以使用其他触发器,但只有 workflow_dispatch 具有手动触发的能力。现在有一个本地 UI 可用于手动缓存管理:https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#managing-caches - lukee
我该如何基于“created_at”键删除缓存?基本上,如果缓存是上周创建的,我想要将其删除。 - Özer Özdal
@ÖzerÖzdal 在 for 循环中添加 if,并按照 cache.created_at 进行过滤。请参阅 https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#list-github-actions-caches-for-a-repository 了解详细信息。但是为什么要这样做呢?GitHub 将自动在未使用 7 天后将它们删除:https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy - lukee
@lukee 是的,我是通过在cache.created_at上运行if和for循环来完成的。因为我有一个包,每周会生成缓存以供下周使用。所以我通过运行一个每天都运行的工作流来删除上周未使用的旧缓存。 - Özer Özdal

11
基于 @beatngu13 的 answer,我创建了一个 Makefile 目标,用于从 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

首先需要安装Github CLIjq工具。安装完Github CLI后,您需要进行授权:

gh auth login

1
在删除所有缓存而不仅仅是前30个时,请添加“--paginate”:gh api --paginate -H ... - Hugo

11

目前你无法强制清除缓存,看起来目前有一个开放的功能请求在进行中 https://github.com/actions/cache/issues/2。如果我是你,我会在那里发布请求,以便他们知道更多的人想要实现此功能。

关于操作的几点说明:

该操作没有参数,甚至在该操作构建的工具包中也没有参数。

深入了解工具包代码,他们使用缓存API URL来完成所有好的事情。这意味着我们甚至不知道该API是否支持它,假设我们尝试直接调用它以查看它提供了什么其他内容。以下是api调用的行,其基本URL取自env ACTIONS_CACHE_URL

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

NPM包作为参考 https://www.npmjs.com/package/@actions/cache

如果我们暂时退后一步,回到github文档,现在我们已经深入了解了操作/缓存代码及其工作原理,

根据github文档 https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows

有两点需要注意:

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.

6

另一种简便直接的清除Actions缓存的方法是使用Purge cache GH Action。

该操作允许根据最后一次使用和配置的TTL(默认为7天)自动清除GitHub Actions的缓存。

示例:

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)

上述工作流将每天运行一次,并删除所有使用时间超过7天的缓存。


如果我设置max-age: 1,那么MyAlbum/purge-cache@v1会立即清除存储在GitHub中的缓存吗? - bekanur98
@bekanur98 它应该清除所有早于1秒的缓存。 - Andrii Bodnar

4

由于您可以在GitHub Actions中使用GitHub CLI gh, 您现在(2023年7月)可以使用gh v2.32.0命令的新特性gh cache delete:

# Delete a cache by id
$ gh cache delete 1234

# Delete a cache by key
$ gh cache delete cache-key

# Delete a cache by id in a specific repo
$ gh cache delete 1234 --repo cli/cli

# Delete all caches
$ gh cache delete --all

2

@GegznaV,您可以使用类似tmate的工具,并通过ssh登录到runner手动清除缓存。


请分享更多细节。那会是如何运作的? - Nico Haase

1

对于任何寻找简单命令行解决方案的人,以下shell命令也可以实现。它需要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'

在这种情况下,我使用sed来URL编码密钥中的特殊字符。我只需要处理|、[和]。其他内容可以根据需要添加。例如,请参见https://gist.github.com/jaytaylor/5a90c49e0976aadfe0726a847ce58736#file-url_encode-sh-L11


0

这里有另一种类似于@beatngu13的缓存键失效方法的自动化解决方案。它使用一个生成的时间戳文件,该文件被提交并在hashFiles(...)前缀中使用作为缓存键。

附带了一组GNU Makefile目标,使使用此方法非常容易:make clear-github-cache

注意:确保每个Makefile“recipe”部分都缩进1个制表符! StackOverflow会将制表符转换为空格。

.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

然后,在GitHub Actions工作流程YAML文件中,添加一个缓存键前缀,该前缀使用此文件的哈希值:

      - 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') }}-

现在只需运行:

make clear-github-cache

这将生成并提交一个文件,即.github/clear_github_actions_cache,其中包含Unix时间戳作为内容。 hashFiles(...)缓存键前缀使用此文件,并将生成该文件的唯一哈希作为其余缓存/ restore-key的前缀。

下次使用git push时,缓存键将被使无效...,从而以空缓存运行GitHub Actions。


0

保留最后的缓存 使用这个bash函数(将其添加到你的.bashrc文件中)

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 
 }

名称完成也适用于bash函数:

gh_<tab>

这个新增的部分是 jq 首先按照 id 进行排序 (假设最近的一个具有最大值)。

[:-1] 表示除了最后一个 id 之外的每个 id。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接