上回已经谈到在使用 GitHub+jsDelivr 作为 OSS 的时候,还可以配合 GitHub Actions 实现缓存的自动刷新,详情参考:
但这个解决方案并不够好。不难发现,每次我们 push 上去新的文件,Action 将全量刷新缓存。这有什么问题呢?
最直观的一点就是随着文件数量的增加,单次 Action 的执行时间将不断变长,最终达到一个你无法接受且 GitHub 也不支持的超长运行时间;除此之外,它做的无用功非常多,它的大部分时间都用在本不需要处理的已有文件上,而只有很少的时间在处理真正需要处理的新增文件。
这里的优化空间是非常大的,而且思路也很简单:将全量刷新改为增量刷新即可。预先处理出本次 commit 涉及的文件,在请求时只请求这一部分就可以了。
实际实现起来还需要一定技巧。幸运的是,GitHub Actions 市场中有相关的“获取 commit 涉及文件”的现成轮子,这里采用 lots0logs/gh-action-get-changed-files。从输出中可以获取的共有五种类型,考虑到我们的需求,只关注 added
、renamed
和 modified
即可。依次请求这三类文件中的所有文件。
# Auto release and force cache
name: Auto release and force cache
# Controls when the action will run. Triggers the workflow only on push
# events but only for the master branch
on:
push:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-18.04
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Get changed files
- id: files
name: Get changed files
uses: lots0logs/[email protected]
with:
token: ${{ secrets.GITHUB_TOKEN }}
# Check files
- id: check
name: Check files
run: |
# Check files
readarray -t added_files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.added }}')"
readarray -t renamed_files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.renamed }}')"
readarray -t modified_files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.modified }}')"
for file in ${added_files[@]}; do
if [[ $file != .github* ]]; then
echo "::set-output name=continue::1"
exit
fi
done
for file in ${renamed_files[@]}; do
if [[ $file != .github* ]]; then
echo "::set-output name=continue::1"
exit
fi
done
for file in ${modified_files[@]}; do
if [[ $file != .github* ]]; then
echo "::set-output name=continue::1"
exit
fi
done
echo "::set-output name=continue::0"
# Auto release
- name: Auto release
if: steps.check.outputs.continue == 1
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
automatic_release_tag: ${{ github.run_id }}
prerelease: false
title: ${{ github.run_id }}
# Force cache
- name: Force cache
if: steps.check.outputs.continue == 1
run: |
# Force cache
function uriencode {
uri=`jq -nr --arg v "$1" '$v|@uri'`
echo ${uri//%2[Ff]//}
}
function force_cache() {
curl -s -o /dev/null --retry 5 "https://cdn.jsdelivr.net/gh/wuxianucw/ucw-desu@master/"$1
url="https://cdn.jsdelivr.net/gh/wuxianucw/ucw-desu@${{ github.run_id }}/"$1
code=`curl -s -o /dev/null --retry 5 -w %{http_code} $url`
echo "Force cache "$url" [ "$code" ]"
if [ $code != "200" ]
then
url="https://cdn.jsdelivr.net/gh/wuxianucw/ucw-desu@master/"$1
echo " - Try master "$url" [ `curl -s -o /dev/null --retry 5 -w %{http_code} $url` ]"
url="https://cdn.jsdelivr.net/gh/wuxianucw/ucw-desu@${{ github.run_id }}/"$1
echo " - Retry "$url" [ `curl -s -o /dev/null --retry 5 -w %{http_code} $url` ]"
fi
url="https://cdn.jsdelivr.net/gh/wuxianucw/ucw-desu/"$1
echo " -> "$url" [ `curl -s -o /dev/null --retry 5 -w %{http_code} $url` ]"
}
readarray -t added_files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.added }}')"
readarray -t renamed_files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.renamed }}')"
readarray -t modified_files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.modified }}')"
for file in ${added_files[@]}; do
if [[ $file != .github* ]]; then
force_cache `uriencode $file`
fi
done
for file in ${renamed_files[@]}; do
if [[ $file != .github* ]]; then
force_cache `uriencode $file`
fi
done
for file in ${modified_files[@]}; do
if [[ $file != .github* ]]; then
force_cache `uriencode $file`
fi
done
代码长了不少,但至少实现了增量更新,节约了我们的时间和 GitHub Actions 的运行资源。
版权声明:本文是原创文章,版权归 无限UCW 所有。
本文链接:https://ucw.moe/archives/optimized-gh-actions.html
本站所有原创文章采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
您可以自由地转载和修改,但请务必注明文章来源并且不可用于商业目的。