在 GitHub 操作工作流程中缓存 APT 包
Caching APT packages in GitHub Actions workflow
我为我的 C 项目使用以下 Github Actions 工作流。工作流程在大约 40 秒内完成,但一半以上的时间用于安装 valgrind
包及其依赖项。
我相信缓存可以帮助我加快工作流程。我不介意多等几秒钟,但这似乎是对 GitHub 资源的毫无意义的浪费。
name: C Workflow
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: make
run: make
- name: valgrind
run: |
sudo apt-get install -y valgrind
valgrind -v --leak-check=full --show-leak-kinds=all ./bin
运行 sudo apt-get install -y valgrind
安装以下软件包:
gdb
gdbserver
libbabeltrace1
libc6-dbg
libipt1
valgrind
我知道 Actions 支持特定目录的缓存(并且已经有几个已回答的 SO 问题和关于此的文章),但我不确定 apt 安装的所有不同包最终在哪里。我假设 /bin/
或 /usr/bin/
不是唯一受安装包影响的目录。
是否有一种优雅的方式来缓存已安装的系统包以供将来的工作流程运行?
此答案的目的是展示如何使用 github 操作进行缓存,而不一定展示如何缓存 valgrind
(它确实如此)。我还尝试解释为什么不缓存所有内容 can/should,因为需要考虑缓存和恢复缓存与重新安装依赖项的成本(时间)。
您将使用 actions/cache
操作来执行此操作。
将其添加为一个步骤(在您需要使用 valgrind 之前):
- name: Cache valgrind
uses: actions/cache@v2
id: cache-valgrind
with:
path: "~/valgrind"
key: ${{secrets.VALGRIND_VERSION}}
下一步应尝试安装缓存版本(如果有)或从存储库安装:
- name: Install valgrind
env:
CACHE_HIT: ${{steps.cache-valgrind.outputs.cache-hit}}
VALGRIND_VERSION: ${{secrets.VALGRIND_VERSION}}
run: |
if [[ "$CACHE_HIT" == 'true' ]]; then
sudo cp --verbose --force --recursive ~/valgrind/* /
else
sudo apt-get install --yes valgrind="$VALGRIND_VERSION"
mkdir -p ~/valgrind
sudo dpkg -L valgrind | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
fi
说明
将 VALGRIND_VERSION
secret 设置为输出:
apt-cache policy valgrind | grep -oP '(?<=Candidate:\s)(.+)'
这将允许您在发布新版本时通过更改密钥值使缓存失效。
dpkg -L valgrind
用于列出使用sudo apt-get install valgrind
时安装的所有文件。
我们现在可以用这个命令做的是将所有依赖项复制到我们的缓存文件夹中:
dpkg -L valgrind | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
此外
除了复制valgrind
的所有组件外,可能还需要复制依赖(比如本例中的libc
),但是我没有'不建议继续沿着这条路走,因为依赖链就是从那里开始增长的。准确的说,最终要有一个适合valgrind的环境到运行中需要复制的依赖如下:
- libc6
- libgcc1
- gcc-8-base
要复制所有这些依赖项,您可以使用与上面相同的语法:
for dep in libc6 libgcc1 gcc-8-base; do
dpkg -L $dep | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
done
当安装 valgrind
所需的只是 运行 sudo apt-get install valgrind
时,所有这些工作真的值得吗?如果您的目标是加快构建过程,那么您还必须考虑恢复(下载和提取)缓存所花费的时间与简单地 运行 再次执行命令以安装 valgrind
.
最后要恢复缓存,假设它存储在/tmp/valgrind
,你可以使用命令:
cp --force --recursive /tmp/valgrind/* /
这基本上会将所有文件从缓存复制到根分区。
除了上面的过程,我还有一个example的“caching valgrind”,通过源码安装和编译。缓存现在大约有 63MB(压缩后)大小,仍然需要单独安装 libc
这样就达不到目的了。
注意:这个问题的另一个 提出了我可以认为是一种更安全的缓存依赖项的方法,即使用预装依赖项的容器。最好的部分是您可以使用操作来使这些容器保持最新状态。
参考文献:
您可以创建一个 docker 预装 valgrind
的图像,并 运行 您的工作流程。
创建一个 Dockerfile
,内容如下:
FROM ubuntu
RUN apt-get install -y valgrind
构建并推送到 dockerhub:
docker build -t natiiix/valgrind .
docker push natiiix/valgrind
然后使用类似以下内容作为您的工作流程:
name: C Workflow
on: [push, pull_request]
jobs:
build:
container: natiiix/valgrind
steps:
- uses: actions/checkout@v1
- name: make
run: make
- name: valgrind
run: valgrind -v --leak-check=full --show-leak-kinds=all ./bin
完全未经测试,但你明白了。
Updated:
I created a GitHub action which work as this solution, less code and better optimizations. Cache Anything New
此解决方案与投票最多的解决方案相似。我尝试了建议的解决方案,但它对我不起作用,因为我正在安装 texlive-latex
和 pandoc
,它们具有许多依赖项和子依赖项。
我创建了一个应该可以帮助很多人的解决方案。一种情况是你安装了几个包 (apt install
),另一种情况是你 make
一个程序,它需要一段时间。
解法:
- 具有所有逻辑的步骤,它将缓存。
- 使用
find
创建容器中所有文件的列表。
- 安装所有软件包或
make
程序,无论您要缓存什么。
- 使用
find
创建容器中所有文件的列表。
- 使用
diff
获取新创建的文件。
- 将这些新文件添加到缓存目录。这个目录会自动存放
actions/cache@v2
.
- 加载创建的缓存的步骤。
- 将缓存目录中的所有文件复制到主路径
/
。
- 将受益于缓存的步骤和您需要的其他步骤。
什么时候用这个?
- 我没有使用缓存,安装软件包大约需要 2 分钟即可完成所有过程。
- 有了缓存,第一次创建需要7~10分钟。
- 使用缓存大约需要 1 分钟来完成所有过程。
- 仅当您的主进程花费大量时间时它才有用,如果您经常部署它也很方便。
执行:
-
我的操作的着陆页:workflows。
release.yml
name: CI - Release books
on:
release:
types: [ released ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-packages
with:
path: ${{ runner.temp }}/cache-linux
key: ${{ runner.os }}-cache-packages-v2.1
- name: Install packages
if: steps.cache-packages.outputs.cache-hit != 'true'
env:
SOURCE: ${{ runner.temp }}/cache-linux
run: |
set +xv
echo "# --------------------------------------------------------"
echo "# Action environment variables"
echo "github.workspace: ${{ github.workspace }}"
echo "runner.workspace: ${{ runner.workspace }}"
echo "runner.os: ${{ runner.os }}"
echo "runner.temp: ${{ runner.temp }}"
echo "# --------------------------------------------------------"
echo "# Where am I?"
pwd
echo "SOURCE: ${SOURCE}"
ls -lha /
sudo du -h -d 1 / 2> /dev/null || true
echo "# --------------------------------------------------------"
echo "# APT update"
sudo apt update
echo "# --------------------------------------------------------"
echo "# Set up snapshot"
mkdir -p "${{ runner.temp }}"/snapshots/
echo "# --------------------------------------------------------"
echo "# Install tools"
sudo rm -f /var/lib/apt/lists/lock
#sudo apt install -y vim bash-completion
echo "# --------------------------------------------------------"
echo "# Take first snapshot"
sudo find / \
-type f,l \
-not \( -path "/sys*" -prune \) \
-not \( -path "/proc*" -prune \) \
-not \( -path "/mnt*" -prune \) \
-not \( -path "/dev*" -prune \) \
-not \( -path "/run*" -prune \) \
-not \( -path "/etc/mtab*" -prune \) \
-not \( -path "/var/cache/apt/archives*" -prune \) \
-not \( -path "/tmp*" -prune \) \
-not \( -path "/var/tmp*" -prune \) \
-not \( -path "/var/backups*" \) \
-not \( -path "/boot*" -prune \) \
-not \( -path "/vmlinuz*" -prune \) \
> "${{ runner.temp }}"/snapshots/snapshot_01.txt 2> /dev/null \
|| true
echo "# --------------------------------------------------------"
echo "# Install pandoc and dependencies"
sudo apt install -y texlive-latex-extra wget
wget -q https://github.com/jgm/pandoc/releases/download/2.11.2/pandoc-2.11.2-1-amd64.deb
sudo dpkg -i pandoc-2.11.2-1-amd64.deb
rm -f pandoc-2.11.2-1-amd64.deb
echo "# --------------------------------------------------------"
echo "# Take second snapshot"
sudo find / \
-type f,l \
-not \( -path "/sys*" -prune \) \
-not \( -path "/proc*" -prune \) \
-not \( -path "/mnt*" -prune \) \
-not \( -path "/dev*" -prune \) \
-not \( -path "/run*" -prune \) \
-not \( -path "/etc/mtab*" -prune \) \
-not \( -path "/var/cache/apt/archives*" -prune \) \
-not \( -path "/tmp*" -prune \) \
-not \( -path "/var/tmp*" -prune \) \
-not \( -path "/var/backups*" \) \
-not \( -path "/boot*" -prune \) \
-not \( -path "/vmlinuz*" -prune \) \
> "${{ runner.temp }}"/snapshots/snapshot_02.txt 2> /dev/null \
|| true
echo "# --------------------------------------------------------"
echo "# Filter new files"
diff -C 1 \
--color=always \
"${{ runner.temp }}"/snapshots/snapshot_01.txt \
"${{ runner.temp }}"/snapshots/snapshot_02.txt \
| grep -E "^\+" \
| sed -E s/..// \
> "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
< "${{ runner.temp }}"/snapshots/snapshot_new_files.txt wc -l
ls -lha "${{ runner.temp }}"/snapshots/
echo "# --------------------------------------------------------"
echo "# Make cache directory"
rm -fR "${SOURCE}"
mkdir -p "${SOURCE}"
while IFS= read -r LINE
do
sudo cp -a --parent "${LINE}" "${SOURCE}"
done < "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
ls -lha "${SOURCE}"
echo ""
sudo du -sh "${SOURCE}" || true
echo "# --------------------------------------------------------"
- name: Copy cached packages
if: steps.cache-packages.outputs.cache-hit == 'true'
env:
SOURCE: ${{ runner.temp }}/cache-linux
run: |
echo "# --------------------------------------------------------"
echo "# Using Cached packages"
ls -lha "${SOURCE}"
sudo cp --force --recursive "${SOURCE}"/. /
echo "# --------------------------------------------------------"
- name: Generate release files and commit in GitHub
run: |
echo "# --------------------------------------------------------"
echo "# Generating release files"
git fetch --all
git pull --rebase origin main
git checkout main
cd ./src/programming-from-the-ground-up
./make.sh
cd ../../
ls -lha release/
git config --global user.name 'Israel Roldan'
git config --global user.email 'israel.alberto.rv@gmail.com'
git add .
git status
git commit -m "Automated Release."
git push
git status
echo "# --------------------------------------------------------"
解释部分代码:
这里是动作缓存,表示一个key
,会生成一次,在后面的执行中比较。 path
是生成缓存压缩文件的文件目录。
- uses: actions/cache@v2
id: cache-packages
with:
path: ${{ runner.temp }}/cache-linux
key: ${{ runner.os }}-cache-packages-v2.1
这个条件搜索key
缓存,如果退出cache-hit
就是'true'.
if: steps.cache-packages.outputs.cache-hit != 'true'
if: steps.cache-packages.outputs.cache-hit == 'true'
这并不重要,但是当du
命令第一次执行时,Linux索引了所有文件(5~8分钟),然后我们将使用find
,只需约 50 秒即可获取所有文件。如果需要,您可以删除此行。
后缀命令 || true
可防止 2> /dev/null
return 错误,否则操作将停止,因为它会检测到您的脚本有错误输出。您将在脚本中看到一些论文。
sudo du -h -d 1 / 2> /dev/null || true
这是神奇的部分,使用find
生成实际文件的列表,排除一些目录以优化缓存文件夹。它还将在安装和 make
程序之后执行。在下一个快照中,文件名应该不同 snapshot_02.txt
.
sudo find / \
-type f,l \
-not \( -path "/sys*" -prune \) \
-not \( -path "/proc*" -prune \) \
-not \( -path "/mnt*" -prune \) \
-not \( -path "/dev*" -prune \) \
-not \( -path "/run*" -prune \) \
-not \( -path "/etc/mtab*" -prune \) \
-not \( -path "/var/cache/apt/archives*" -prune \) \
-not \( -path "/tmp*" -prune \) \
-not \( -path "/var/tmp*" -prune \) \
-not \( -path "/var/backups*" \) \
-not \( -path "/boot*" -prune \) \
-not \( -path "/vmlinuz*" -prune \) \
> "${{ runner.temp }}"/snapshots/snapshot_01.txt 2> /dev/null \
|| true
安装一些包和pandoc
。
sudo apt install -y texlive-latex-extra wget
wget -q https://github.com/jgm/pandoc/releases/download/2.11.2/pandoc-2.11.2-1-amd64.deb
sudo dpkg -i pandoc-2.11.2-1-amd64.deb
rm -f pandoc-2.11.2-1-amd64.deb
生成添加了新文件的文本文件,文件也可以是符号文件。
diff -C 1 \
"${{ runner.temp }}"/snapshots/snapshot_01.txt \
"${{ runner.temp }}"/snapshots/snapshot_02.txt \
| grep -E "^\+" \
| sed -E s/..// \
> "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
最后将所有文件复制到缓存目录中作为存档,以保留原始信息。
while IFS= read -r LINE
do
sudo cp -a --parent "${LINE}" "${SOURCE}"
done < "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
将所有缓存文件复制到主路径的步骤/
。
- name: Copy cached packages
if: steps.cache-packages.outputs.cache-hit == 'true'
env:
SOURCE: ${{ runner.temp }}/cache-linux
run: |
echo "# --------------------------------------------------------"
echo "# Using Cached packages"
ls -lha "${SOURCE}"
sudo cp --force --recursive "${SOURCE}"/. /
echo "# --------------------------------------------------------"
这一步是我使用缓存生成的已安装包的地方,./make.sh
脚本使用 pandoc
进行一些转换。正如我提到的,您可以创建其他使用缓存优势的步骤或其他不使用缓存的步骤。
- name: Generate release files and commit in GitHub
run: |
echo "# --------------------------------------------------------"
echo "# Generating release files"
cd ./src/programming-from-the-ground-up
./make.sh
我为我的 C 项目使用以下 Github Actions 工作流。工作流程在大约 40 秒内完成,但一半以上的时间用于安装 valgrind
包及其依赖项。
我相信缓存可以帮助我加快工作流程。我不介意多等几秒钟,但这似乎是对 GitHub 资源的毫无意义的浪费。
name: C Workflow
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: make
run: make
- name: valgrind
run: |
sudo apt-get install -y valgrind
valgrind -v --leak-check=full --show-leak-kinds=all ./bin
运行 sudo apt-get install -y valgrind
安装以下软件包:
gdb
gdbserver
libbabeltrace1
libc6-dbg
libipt1
valgrind
我知道 Actions 支持特定目录的缓存(并且已经有几个已回答的 SO 问题和关于此的文章),但我不确定 apt 安装的所有不同包最终在哪里。我假设 /bin/
或 /usr/bin/
不是唯一受安装包影响的目录。
是否有一种优雅的方式来缓存已安装的系统包以供将来的工作流程运行?
此答案的目的是展示如何使用 github 操作进行缓存,而不一定展示如何缓存 valgrind
(它确实如此)。我还尝试解释为什么不缓存所有内容 can/should,因为需要考虑缓存和恢复缓存与重新安装依赖项的成本(时间)。
您将使用 actions/cache
操作来执行此操作。
将其添加为一个步骤(在您需要使用 valgrind 之前):
- name: Cache valgrind
uses: actions/cache@v2
id: cache-valgrind
with:
path: "~/valgrind"
key: ${{secrets.VALGRIND_VERSION}}
下一步应尝试安装缓存版本(如果有)或从存储库安装:
- name: Install valgrind
env:
CACHE_HIT: ${{steps.cache-valgrind.outputs.cache-hit}}
VALGRIND_VERSION: ${{secrets.VALGRIND_VERSION}}
run: |
if [[ "$CACHE_HIT" == 'true' ]]; then
sudo cp --verbose --force --recursive ~/valgrind/* /
else
sudo apt-get install --yes valgrind="$VALGRIND_VERSION"
mkdir -p ~/valgrind
sudo dpkg -L valgrind | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
fi
说明
将 VALGRIND_VERSION
secret 设置为输出:
apt-cache policy valgrind | grep -oP '(?<=Candidate:\s)(.+)'
这将允许您在发布新版本时通过更改密钥值使缓存失效。
dpkg -L valgrind
用于列出使用sudo apt-get install valgrind
时安装的所有文件。
我们现在可以用这个命令做的是将所有依赖项复制到我们的缓存文件夹中:
dpkg -L valgrind | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
此外
除了复制valgrind
的所有组件外,可能还需要复制依赖(比如本例中的libc
),但是我没有'不建议继续沿着这条路走,因为依赖链就是从那里开始增长的。准确的说,最终要有一个适合valgrind的环境到运行中需要复制的依赖如下:
- libc6
- libgcc1
- gcc-8-base
要复制所有这些依赖项,您可以使用与上面相同的语法:
for dep in libc6 libgcc1 gcc-8-base; do
dpkg -L $dep | while IFS= read -r f; do if test -f $f; then echo $f; fi; done | xargs cp --parents --target-directory ~/valgrind/
done
当安装 valgrind
所需的只是 运行 sudo apt-get install valgrind
时,所有这些工作真的值得吗?如果您的目标是加快构建过程,那么您还必须考虑恢复(下载和提取)缓存所花费的时间与简单地 运行 再次执行命令以安装 valgrind
.
最后要恢复缓存,假设它存储在/tmp/valgrind
,你可以使用命令:
cp --force --recursive /tmp/valgrind/* /
这基本上会将所有文件从缓存复制到根分区。
除了上面的过程,我还有一个example的“caching valgrind”,通过源码安装和编译。缓存现在大约有 63MB(压缩后)大小,仍然需要单独安装 libc
这样就达不到目的了。
注意:这个问题的另一个
参考文献:
您可以创建一个 docker 预装 valgrind
的图像,并 运行 您的工作流程。
创建一个 Dockerfile
,内容如下:
FROM ubuntu
RUN apt-get install -y valgrind
构建并推送到 dockerhub:
docker build -t natiiix/valgrind .
docker push natiiix/valgrind
然后使用类似以下内容作为您的工作流程:
name: C Workflow
on: [push, pull_request]
jobs:
build:
container: natiiix/valgrind
steps:
- uses: actions/checkout@v1
- name: make
run: make
- name: valgrind
run: valgrind -v --leak-check=full --show-leak-kinds=all ./bin
完全未经测试,但你明白了。
Updated: I created a GitHub action which work as this solution, less code and better optimizations. Cache Anything New
此解决方案与投票最多的解决方案相似。我尝试了建议的解决方案,但它对我不起作用,因为我正在安装 texlive-latex
和 pandoc
,它们具有许多依赖项和子依赖项。
我创建了一个应该可以帮助很多人的解决方案。一种情况是你安装了几个包 (apt install
),另一种情况是你 make
一个程序,它需要一段时间。
解法:
- 具有所有逻辑的步骤,它将缓存。
- 使用
find
创建容器中所有文件的列表。 - 安装所有软件包或
make
程序,无论您要缓存什么。 - 使用
find
创建容器中所有文件的列表。 - 使用
diff
获取新创建的文件。 - 将这些新文件添加到缓存目录。这个目录会自动存放
actions/cache@v2
.
- 使用
- 加载创建的缓存的步骤。
- 将缓存目录中的所有文件复制到主路径
/
。
- 将缓存目录中的所有文件复制到主路径
- 将受益于缓存的步骤和您需要的其他步骤。
什么时候用这个?
- 我没有使用缓存,安装软件包大约需要 2 分钟即可完成所有过程。
- 有了缓存,第一次创建需要7~10分钟。
- 使用缓存大约需要 1 分钟来完成所有过程。
- 仅当您的主进程花费大量时间时它才有用,如果您经常部署它也很方便。
执行:
我的操作的着陆页:workflows。
release.yml
name: CI - Release books
on:
release:
types: [ released ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
id: cache-packages
with:
path: ${{ runner.temp }}/cache-linux
key: ${{ runner.os }}-cache-packages-v2.1
- name: Install packages
if: steps.cache-packages.outputs.cache-hit != 'true'
env:
SOURCE: ${{ runner.temp }}/cache-linux
run: |
set +xv
echo "# --------------------------------------------------------"
echo "# Action environment variables"
echo "github.workspace: ${{ github.workspace }}"
echo "runner.workspace: ${{ runner.workspace }}"
echo "runner.os: ${{ runner.os }}"
echo "runner.temp: ${{ runner.temp }}"
echo "# --------------------------------------------------------"
echo "# Where am I?"
pwd
echo "SOURCE: ${SOURCE}"
ls -lha /
sudo du -h -d 1 / 2> /dev/null || true
echo "# --------------------------------------------------------"
echo "# APT update"
sudo apt update
echo "# --------------------------------------------------------"
echo "# Set up snapshot"
mkdir -p "${{ runner.temp }}"/snapshots/
echo "# --------------------------------------------------------"
echo "# Install tools"
sudo rm -f /var/lib/apt/lists/lock
#sudo apt install -y vim bash-completion
echo "# --------------------------------------------------------"
echo "# Take first snapshot"
sudo find / \
-type f,l \
-not \( -path "/sys*" -prune \) \
-not \( -path "/proc*" -prune \) \
-not \( -path "/mnt*" -prune \) \
-not \( -path "/dev*" -prune \) \
-not \( -path "/run*" -prune \) \
-not \( -path "/etc/mtab*" -prune \) \
-not \( -path "/var/cache/apt/archives*" -prune \) \
-not \( -path "/tmp*" -prune \) \
-not \( -path "/var/tmp*" -prune \) \
-not \( -path "/var/backups*" \) \
-not \( -path "/boot*" -prune \) \
-not \( -path "/vmlinuz*" -prune \) \
> "${{ runner.temp }}"/snapshots/snapshot_01.txt 2> /dev/null \
|| true
echo "# --------------------------------------------------------"
echo "# Install pandoc and dependencies"
sudo apt install -y texlive-latex-extra wget
wget -q https://github.com/jgm/pandoc/releases/download/2.11.2/pandoc-2.11.2-1-amd64.deb
sudo dpkg -i pandoc-2.11.2-1-amd64.deb
rm -f pandoc-2.11.2-1-amd64.deb
echo "# --------------------------------------------------------"
echo "# Take second snapshot"
sudo find / \
-type f,l \
-not \( -path "/sys*" -prune \) \
-not \( -path "/proc*" -prune \) \
-not \( -path "/mnt*" -prune \) \
-not \( -path "/dev*" -prune \) \
-not \( -path "/run*" -prune \) \
-not \( -path "/etc/mtab*" -prune \) \
-not \( -path "/var/cache/apt/archives*" -prune \) \
-not \( -path "/tmp*" -prune \) \
-not \( -path "/var/tmp*" -prune \) \
-not \( -path "/var/backups*" \) \
-not \( -path "/boot*" -prune \) \
-not \( -path "/vmlinuz*" -prune \) \
> "${{ runner.temp }}"/snapshots/snapshot_02.txt 2> /dev/null \
|| true
echo "# --------------------------------------------------------"
echo "# Filter new files"
diff -C 1 \
--color=always \
"${{ runner.temp }}"/snapshots/snapshot_01.txt \
"${{ runner.temp }}"/snapshots/snapshot_02.txt \
| grep -E "^\+" \
| sed -E s/..// \
> "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
< "${{ runner.temp }}"/snapshots/snapshot_new_files.txt wc -l
ls -lha "${{ runner.temp }}"/snapshots/
echo "# --------------------------------------------------------"
echo "# Make cache directory"
rm -fR "${SOURCE}"
mkdir -p "${SOURCE}"
while IFS= read -r LINE
do
sudo cp -a --parent "${LINE}" "${SOURCE}"
done < "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
ls -lha "${SOURCE}"
echo ""
sudo du -sh "${SOURCE}" || true
echo "# --------------------------------------------------------"
- name: Copy cached packages
if: steps.cache-packages.outputs.cache-hit == 'true'
env:
SOURCE: ${{ runner.temp }}/cache-linux
run: |
echo "# --------------------------------------------------------"
echo "# Using Cached packages"
ls -lha "${SOURCE}"
sudo cp --force --recursive "${SOURCE}"/. /
echo "# --------------------------------------------------------"
- name: Generate release files and commit in GitHub
run: |
echo "# --------------------------------------------------------"
echo "# Generating release files"
git fetch --all
git pull --rebase origin main
git checkout main
cd ./src/programming-from-the-ground-up
./make.sh
cd ../../
ls -lha release/
git config --global user.name 'Israel Roldan'
git config --global user.email 'israel.alberto.rv@gmail.com'
git add .
git status
git commit -m "Automated Release."
git push
git status
echo "# --------------------------------------------------------"
解释部分代码:
这里是动作缓存,表示一个key
,会生成一次,在后面的执行中比较。 path
是生成缓存压缩文件的文件目录。
- uses: actions/cache@v2
id: cache-packages
with:
path: ${{ runner.temp }}/cache-linux
key: ${{ runner.os }}-cache-packages-v2.1
这个条件搜索key
缓存,如果退出cache-hit
就是'true'.
if: steps.cache-packages.outputs.cache-hit != 'true'
if: steps.cache-packages.outputs.cache-hit == 'true'
这并不重要,但是当du
命令第一次执行时,Linux索引了所有文件(5~8分钟),然后我们将使用find
,只需约 50 秒即可获取所有文件。如果需要,您可以删除此行。
后缀命令 || true
可防止 2> /dev/null
return 错误,否则操作将停止,因为它会检测到您的脚本有错误输出。您将在脚本中看到一些论文。
sudo du -h -d 1 / 2> /dev/null || true
这是神奇的部分,使用find
生成实际文件的列表,排除一些目录以优化缓存文件夹。它还将在安装和 make
程序之后执行。在下一个快照中,文件名应该不同 snapshot_02.txt
.
sudo find / \
-type f,l \
-not \( -path "/sys*" -prune \) \
-not \( -path "/proc*" -prune \) \
-not \( -path "/mnt*" -prune \) \
-not \( -path "/dev*" -prune \) \
-not \( -path "/run*" -prune \) \
-not \( -path "/etc/mtab*" -prune \) \
-not \( -path "/var/cache/apt/archives*" -prune \) \
-not \( -path "/tmp*" -prune \) \
-not \( -path "/var/tmp*" -prune \) \
-not \( -path "/var/backups*" \) \
-not \( -path "/boot*" -prune \) \
-not \( -path "/vmlinuz*" -prune \) \
> "${{ runner.temp }}"/snapshots/snapshot_01.txt 2> /dev/null \
|| true
安装一些包和pandoc
。
sudo apt install -y texlive-latex-extra wget
wget -q https://github.com/jgm/pandoc/releases/download/2.11.2/pandoc-2.11.2-1-amd64.deb
sudo dpkg -i pandoc-2.11.2-1-amd64.deb
rm -f pandoc-2.11.2-1-amd64.deb
生成添加了新文件的文本文件,文件也可以是符号文件。
diff -C 1 \
"${{ runner.temp }}"/snapshots/snapshot_01.txt \
"${{ runner.temp }}"/snapshots/snapshot_02.txt \
| grep -E "^\+" \
| sed -E s/..// \
> "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
最后将所有文件复制到缓存目录中作为存档,以保留原始信息。
while IFS= read -r LINE
do
sudo cp -a --parent "${LINE}" "${SOURCE}"
done < "${{ runner.temp }}"/snapshots/snapshot_new_files.txt
将所有缓存文件复制到主路径的步骤/
。
- name: Copy cached packages
if: steps.cache-packages.outputs.cache-hit == 'true'
env:
SOURCE: ${{ runner.temp }}/cache-linux
run: |
echo "# --------------------------------------------------------"
echo "# Using Cached packages"
ls -lha "${SOURCE}"
sudo cp --force --recursive "${SOURCE}"/. /
echo "# --------------------------------------------------------"
这一步是我使用缓存生成的已安装包的地方,./make.sh
脚本使用 pandoc
进行一些转换。正如我提到的,您可以创建其他使用缓存优势的步骤或其他不使用缓存的步骤。
- name: Generate release files and commit in GitHub
run: |
echo "# --------------------------------------------------------"
echo "# Generating release files"
cd ./src/programming-from-the-ground-up
./make.sh