GitHub Actions文件大小检查工作流未正常终止原因排查
问题:GitHub Actions文件大小检查脚本返回exit 1但工作流仍通过?
用户的GitHub Actions脚本意图是在推送main分支或发起PR时检查文件大小,超过15MB则让检查失败,但实际文件超限时工作流仍通过。脚本如下:
name: File Size Limit Check on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: check_file_size: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Check file size run: | MAX_FILE_SIZE=15000000 # Get the list of modified files in the commit or pull request git diff-tree --no-commit-id --name-only -r ${{ github.sha }} | while read file; do file_size=$(wc -c < "$file") if [ $file_size -gt $MAX_FILE_SIZE ]; then echo "File '$file' exceeds the maximum allowed size of $MAX_FILE_SIZE bytes." exit 1 fi done
原因分析
问题核心在于管道(|)创建的子shell:while read file循环运行在管道生成的子shell中,当你在循环内执行exit 1时,只会终止这个子shell,不会影响执行整个run命令的父shell。父shell的退出状态仍为0,因此GitHub Actions判定该步骤执行成功,工作流自然通过。
解决方案
方案1:用进程替换避免子shell
将管道替换为进程替换(< <(command)),让while循环在父shell中执行,此时exit 1会直接终止整个步骤:
- name: Check file size run: | MAX_FILE_SIZE=15000000 # 使用进程替换让while循环在父shell执行 while read file; do if [ -f "$file" ]; then # 额外检查文件是否存在,避免处理已删除文件报错 file_size=$(wc -c < "$file") if [ $file_size -gt $MAX_FILE_SIZE ]; then echo "File '$file' exceeds the maximum allowed size of $MAX_FILE_SIZE bytes." exit 1 fi fi done < <(git diff-tree --no-commit-id --name-only -r ${{ github.sha }})
方案2:开启pipefail选项
在脚本开头添加set -o pipefail,该选项会让管道的退出状态等于管道中第一个非零退出状态的命令。当子shell内触发exit 1后,整个管道的退出状态变为1,父shell继承该状态,从而让步骤失败:
- name: Check file size run: | set -o pipefail MAX_FILE_SIZE=15000000 git diff-tree --no-commit-id --name-only -r ${{ github.sha }} | while read file; do if [ -f "$file" ]; then file_size=$(wc -c < "$file") if [ $file_size -gt $MAX_FILE_SIZE ]; then echo "File '$file' exceeds the maximum allowed size of $MAX_FILE_SIZE bytes." exit 1 fi fi done
额外优化:PR事件的文件检查准确性
在pull_request事件中,${{ github.sha }}指向合并后的临时提交SHA,git diff-tree可能无法准确获取PR的变更文件。若要精准检查PR中新增/修改的文件,可将git diff-tree命令替换为:
git diff --name-only origin/main...HEAD
内容的提问来源于stack exchange,提问作者Rogith
相关产品推荐
相关产品推荐

