使用PyGithub的update_file提交时如何实现commit签名验证
PyGithub提交Commit显示已验证状态实现方法
PyGithub 封装的update_file/create_file等高层方法默认调用GitHub Web提交接口,默认不会自动附加签名,除非使用接口默认的提交身份,否则生成的commit不会出现「已验证」标识。
方案一:零配置使用GitHub自动托管签名
不需要本地生成或管理GPG密钥,满足以下两个条件即可自动获得GitHub官方签名,显示已验证:
- 使用的PAT/Token所属账号已经完成对应邮箱的验证
- 调用
update_file时不要手动传入author、committer参数
此时GitHub会自动使用Token绑定的账号身份生成commit,附加托管签名,直接满足验证要求。
如果需要自定义提交者/作者信息,使用下面的手动GPG签名方案。
方案二:自定义提交身份+本地GPG签名
该方案可以自定义提交身份,通过本地GPG密钥生成签名,提交后GitHub校验通过即可显示已验证。
前置准备
- 本地生成GPG密钥对,将公钥上传到GitHub账号的「SSH和GPG密钥」设置页
- 提交时填写的作者/提交者姓名、邮箱必须和GPG密钥绑定的身份完全一致,且邮箱已经在GitHub账号完成验证
- 安装依赖:
pip install pygithub python-gnupg
实现代码
from github import Github, InputGitAuthor, InputGitTreeElement import gnupg from datetime import datetime # 配置项 - 替换为你自己的信息 GITHUB_TOKEN = "你的GitHub访问令牌" REPO_FULL_NAME = "目标仓库所属用户名/仓库名" BRANCH_NAME = "master" UPDATE_FILE_PATH = "README.md" COMMIT_MESSAGE = "更新README文件内容" NEW_FILE_CONTENT = "更新后的文件内容" GPG_KEY_ID = "本地GPG密钥ID" GPG_KEY_PASSPHRASE = "GPG私钥的解锁密码" # 初始化实例 gpg = gnupg.GPG() gh_client = Github(GITHUB_TOKEN) target_repo = gh_client.get_repo(REPO_FULL_NAME) # 获取分支当前状态 branch_ref = target_repo.get_git_ref(f"heads/{BRANCH_NAME}") base_commit = target_repo.get_git_commit(branch_ref.object.sha) old_file = target_repo.get_contents(UPDATE_FILE_PATH, ref=BRANCH_NAME) # 生成新内容的blob对象 new_content_blob = target_repo.create_git_blob(NEW_FILE_CONTENT, "utf-8") # 构造新的提交树 new_tree_element = InputGitTreeElement( path=UPDATE_FILE_PATH, mode=old_file.mode, type="blob", sha=new_content_blob.sha ) new_commit_tree = target_repo.create_git_tree([new_tree_element], base_commit.tree) # 构造作者/提交者信息,必须和GPG密钥绑定信息一致 commit_time = datetime.utcnow().isoformat() + "Z" commit_author = InputGitAuthor( name="你的GitHub显示名称", email="你的GitHub已验证邮箱", date=commit_time ) commit_committer = commit_author # 生成符合Git规范的待签名内容 unsigned_commit = f"""tree {new_commit_tree.sha} parent {base_commit.sha} author {commit_author.name} <{commit_author.email}> {commit_author.date} committer {commit_committer.name} <{commit_committer.email}> {commit_committer.date} {COMMIT_MESSAGE} """ # 调用本地GPG生成 detached 签名 gpg_sign = gpg.sign( unsigned_commit, keyid=GPG_KEY_ID, passphrase=GPG_KEY_PASSPHRASE, detach=True, clearsign=False ).data.decode("utf-8") # 创建带GPG签名的Commit signed_commit = target_repo.create_git_commit( message=COMMIT_MESSAGE, tree=new_commit_tree, parents=[base_commit], author=commit_author, committer=commit_committer, signature=gpg_sign ) # 将分支指针指向新生成的签名Commit,完成提交 branch_ref.edit(signed_commit.sha)
常见踩坑点
- 提交信息里的邮箱必须是GitHub账号已经完成验证的邮箱,否则签名合法也不会显示已验证
- 待签名的commit内容必须严格符合Git格式,换行、空格不能有偏差,否则签名校验会失败
- 上传到GitHub的GPG公钥必须和本地签名用的私钥是匹配的密钥对
- 方案一不要手动传入author/committer参数,否则GitHub不会自动附加托管签名
内容的提问来源于stack exchange,提问作者adityaprasad502
相关产品推荐
相关产品推荐

