GitHub Actions中Python脚本获取推送提交文件列表失败求助
问题:GitHub Actions中无法通过Git命令获取推送提交的文件列表
我在推送提交触发GitHub Action时,尝试用Python的subprocess.getoutput()方法获取最后一次提交的推送文件列表。本地运行以下命令完全正常:
git_diff = subprocess.getoutput('git diff-tree --no-commit-id --name-only -r $GITHUB_SHA')
但在GitHub Actions的Ubuntu服务器上执行时返回错误:
git_diff: fatal: ambiguous argument 'zag2b54s': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]'
已确认环境依赖安装正常,本地测试无问题,但在GitHub Actions中出现提交哈希无法识别的情况,不确定是Git用法问题还是GitHub Actions配置问题。附上相关Workflow配置和Python脚本,求告知在GitHub Actions服务器的Python脚本中,获取最后一次推送提交文件列表的正确Git命令或解决方法。
相关Workflow配置
name: Automation for csv, py and diagrams files of Sequel pushed files on: push: branches: [ "main" ] pull_request: branches: [ "main" ] permissions: write-all jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python 3.11 uses: actions/setup-python@v3 with: python-version: "3.11" - name: Install dependencies run: | sudo apt-get update -y \ && sudo apt-get upgrade -y \ && sudo apt-get install graphviz git -y \ && python -m pip install --upgrade pip \ && pip install pandas sql-metadata diagrams - name: App with Automation for csv and diagrams run: | # stop the build if there are Python syntax errors or undefined names python automation_csv_diagram.py --last_commit
相关Python脚本
import subprocess import sys from glob import glob from re import findall, IGNORECASE, match, MULTILINE, search, S, sub global REQUEST_DIR REQUEST_DIR = "bq" def pickup(lastcommit_fct: bool) -> list[str]: """ :param lastcommit_fct: bool 获取子目录中的SQL文件列表 :return: List[str] """ global REQUEST_DIR if lastcommit_fct: if not os.name == "nt": # 判断是否为GitHub Actions的Ubuntu环境 git_diff = subprocess.getoutput('git diff-tree --no-commit-id --name-only -r $GITHUB_SHA') else: git_diff = subprocess.getoutput('git diff-tree --no-commit-id --name-only -r HEAD') files = findall(".*\.sql", git_diff, MULTILINE | IGNORECASE) ##DEBUG MODE############################### mode = True if mode: var_githubsha = subprocess.getoutput("echo $GITHUB_SHA") sys.exit('github sha: ' + var_githubsha + "\ngit_diff: " + git_diff + '\nfiles: ' + str(files)) ########################################### if len(files) > 0: files = [y for y in [x.strip() for x in files] if match(r".*\.sql", y, IGNORECASE)] else: sys.exit("Pas de fichier SQL dans le dernier commit git_diff" + git_diff) if not lastcommit_fct: files: list = glob(f'{REQUEST_DIR}/**/*.sql') return sorted(files) def main(lastcommit_fct): files = pickup(lastcommit_fct) if __name__ == '__main__': option = str(sys.argv[1]) if option == "--all_directories": main(False) # 生成./bq目录下所有SQL文件的文档 elif option == "--last_commit": main(True) # 仅生成最后一次提交中SQL文件的文档 else: print("""运行脚本生成./bq目录下所有Sequel文件的文档: $python automation_csv_diagram --all_directories 运行脚本生成最新推送的Sequel文件的文档: $python automation_csv_diagram --last_commit""")
解决方案
问题根源
actions/checkout@v3默认仅拉取最新提交:不完整的仓库克隆导致Git无法识别完整提交历史,$GITHUB_SHA对应的提交无法被正确解析。- Shell变量解析失败:Python的
subprocess.getoutput()使用单引号包裹命令时,Bash不会解析$GITHUB_SHA变量,导致传递给Git的是字符串$GITHUB_SHA而非实际提交哈希。
修复步骤
1. 修改Workflow的checkout步骤,拉取完整仓库历史
更新actions/checkout配置,添加fetch-depth: 0拉取所有历史:
- uses: actions/checkout@v3 with: fetch-depth: 0 # 拉取完整仓库历史
2. 修复Python脚本中的环境变量传递问题
有两种可靠方式解决:
- 方式一:改用双引号包裹命令:让Bash自动解析环境变量
git_diff = subprocess.getoutput("git diff-tree --no-commit-id --name-only -r $GITHUB_SHA")
- 方式二:直接在Python中读取环境变量(推荐,避免Shell解析问题)
import os # ... git_sha = os.environ.get('GITHUB_SHA') git_diff = subprocess.getoutput(f'git diff-tree --no-commit-id --name-only -r {git_sha}')
3. 基于GitHub事件的优化(可选)
如果仅需获取本次推送的修改文件,可直接读取GitHub事件文件,无需调用Git命令:
import json import os def get_pushed_files(): event_path = os.environ.get('GITHUB_EVENT_PATH') with open(event_path, 'r') as f: event_data = json.load(f) # 提取推送事件中所有新增、修改、删除的文件 files = [] for commit in event_data.get('commits', []): files.extend(commit.get('modified', [])) files.extend(commit.get('added', [])) files.extend(commit.get('removed', [])) # 去重并筛选SQL文件 sql_files = list(set([f for f in files if f.endswith('.sql')])) return sorted(sql_files)
内容的提问来源于stack exchange,提问作者Romain Boyrie
相关产品推荐
相关产品推荐

