You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需手动操作自动更新GitHub Actions工具链缓存?

解决GitHub Actions缓存工具链版本自动更新的问题

我编写了一段Shell脚本,用于下载并安装GitHub发布的.tar.gz格式工具链,希望将最新版本的工件保存到GitHub Actions缓存目录中,当有新版本发布时自动更新缓存。但实际使用中发现缓存无法修改,旧缓存一旦生成就会一直存在,导致脚本每次都需要重新下载包,缓存失去作用,只能手动删除。现有代码可正常获取最新版本,无更新时不会重复下载,当前仅需解决自动替换旧缓存的问题。

当前Shell脚本

#!/bin/sh

LATEST_API_URL="https://api.github.com/repos/.../.../releases/latest"

LATEST_TOOLCHAINS_TAG=$(curl -s "$LATEST_API_URL" | grep "tag_name.*" | cut -d: -f2 | cut -d\" -f2)

TOOLCHAINS_PACKED_SAVE_DIR="../toolchains_packed"
ROOT_DIR="$(dirname "$(readlink -f "$0")")"

cd "$TOOLCHAINS_PACKED_SAVE_DIR"

if [ ! -f "./toolchains_tag.metadata" ]; then
    echo 'NEW FILE' > "./toolchains_tag.metadata"
fi

if [ "$LATEST_TOOLCHAINS_TAG" != "$(cat "./toolchains_tag.metadata")" ]; then
    DOWNLOADS_URLS=$(curl -s "$LATEST_API_URL" | grep "browser_download_url.*tar.gz" | cut -d: -f2,3 | tr -d \")

    wget $DOWNLOADS_URLS || { printf "wget failed: Please read above errors.\nExiting!\n"; exit 1; }

    echo "$LATEST_TOOLCHAINS_TAG" > "./toolchains_tag.metadata"
fi

for tar_pkg in *.tar.gz; do
    [ ! -f "$tar_pkg" ] && { printf "No *.tar.gz found.\nExiting\n"; exit 1; }

    CURR_COMP=$(echo "$tar_pkg" | cut -d. -f1)
    COMPILERS_LIST="$COMPILERS_LIST$CURR_COMP\n"

    sudo tar -xzvf "$tar_pkg" -C /
done

printf "$COMPILERS_LIST" > "./compilers_list.metadata"

cd $ROOT_DIR

当前GitHub Actions工作流

...
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Create toolchains Directory
      run: mkdir ../toolchains_packed
    - name: Get Cached toolchains Directory
      uses: actions/cache@v3.2.3
      with:
        path: ../toolchains_packed
        key: toolchains_packed
    - name: Setup toolchains
      run: ./path/to/the_script.sh
...

我的思路是用缓存中的tag命名缓存key,但该文件存储在缓存内,无法直接实现。


解决方案

核心逻辑是提前获取最新工具链版本tag,将其作为缓存key的一部分,新版本发布时tag变化会生成新的缓存key,自动创建新缓存条目,旧缓存会在仓库缓存容量达上限时自动清理。

1. 修改GitHub Actions工作流

将获取最新tag的步骤移到缓存操作之前,用tag生成动态缓存key:

...
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    # 第一步:获取最新工具链tag并输出为工作流变量
    - name: Fetch latest toolchain tag
      id: fetch_tag
      run: |
        LATEST_API_URL="https://api.github.com/repos/.../.../releases/latest"
        LATEST_TAG=$(curl -s "$LATEST_API_URL" | grep "tag_name.*" | cut -d: -f2 | cut -d\" -f2)
        echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
    # 创建目录(缓存不存在时需要)
    - name: Create toolchains Directory
      run: mkdir -p ../toolchains_packed
    # 第二步:用动态tag作为缓存key的一部分
    - name: Get Cached toolchains Directory
      uses: actions/cache@v3.2.3
      with:
        path: ../toolchains_packed
        key: toolchains_packed-${{ steps.fetch_tag.outputs.tag }}
        # 可选:如果需要兼容旧tag格式,可添加回退key
        # restore-keys: |
        #   toolchains_packed-
    # 第三步:执行脚本并传递最新tag环境变量
    - name: Setup toolchains
      run: ./path/to/the_script.sh
      env:
        TOOLCHAIN_LATEST_TAG: ${{ steps.fetch_tag.outputs.tag }}
...

2. 优化Shell脚本

利用工作流传递的tag变量,减少重复API请求,并增加旧包清理逻辑:

#!/bin/sh

# 从工作流环境变量获取最新tag
LATEST_TOOLCHAINS_TAG="${TOOLCHAIN_LATEST_TAG}"

TOOLCHAINS_PACKED_SAVE_DIR="../toolchains_packed"
ROOT_DIR="$(dirname "$(readlink -f "$0")")"

cd "$TOOLCHAINS_PACKED_SAVE_DIR"

if [ ! -f "./toolchains_tag.metadata" ]; then
    # 首次运行或缓存不存在,直接下载最新版本
    DOWNLOADS_URLS=$(curl -s "https://api.github.com/repos/.../.../releases/latest" | grep "browser_download_url.*tar.gz" | cut -d: -f2,3 | tr -d \")
    wget $DOWNLOADS_URLS || { printf "wget failed: Please read above errors.\nExiting!\n"; exit 1; }
    echo "$LATEST_TOOLCHAINS_TAG" > "./toolchains_tag.metadata"
else
    # 对比缓存tag与最新tag,不一致则更新
    if [ "$LATEST_TOOLCHAINS_TAG" != "$(cat "./toolchains_tag.metadata")" ]; then
        # 删除旧包避免版本混杂
        rm -f *.tar.gz
        DOWNLOADS_URLS=$(curl -s "https://api.github.com/repos/.../.../releases/latest" | grep "browser_download_url.*tar.gz" | cut -d: -f2,3 | tr -d \")
        wget $DOWNLOADS_URLS || { printf "wget failed: Please read above errors.\nExiting!\n"; exit 1; }
        echo "$LATEST_TOOLCHAINS_TAG" > "./toolchains_tag.metadata"
    fi
fi

for tar_pkg in *.tar.gz; do
    [ ! -f "$tar_pkg" ] && { printf "No *.tar.gz found.\nExiting\n"; exit 1; }

    CURR_COMP=$(echo "$tar_pkg" | cut -d. -f1)
    COMPILERS_LIST="$COMPILERS_LIST$CURR_COMP\n"

    sudo tar -xzvf "$tar_pkg" -C /
done

printf "$COMPILERS_LIST" > "./compilers_list.metadata"

cd $ROOT_DIR

原理说明

  • GitHub Actions缓存基于key的精确匹配,当tag更新时,缓存keytoolchains_packed-${tag}会变化,自动触发新缓存的创建。
  • 旧缓存会保留直到仓库缓存容量达到上限,GitHub会自动清理最早的缓存条目。
  • 脚本中增加旧包删除逻辑,确保缓存目录内只存在当前最新版本的工具链包。

内容的提问来源于stack exchange,提问作者Lakshay Rohila

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:50:37