如何将GitLab CI构建状态推送到GitHub网站代码仓库
目标
在GitLab Runner完成GitHub仓库镜像的CI构建后,我希望自动将构建状态徽章推送到GitHub网站。
方案一
我最初的想法是在.gitlab-ci.yml中加入shell脚本,获取对应commit的构建状态,克隆GitHub状态网站仓库,通过git add、commit、push操作更新或新增构建状态。
但该方案存在两个实际问题:一是commit的构建状态要等CI完全结束后才会发布,yml中的脚本可能无法获取到最新的构建状态,不过我猜测可以通过post之类的参数解决该问题;二是该方案会污染原仓库,且对于没有GitHub状态网站仓库push权限的其他用户,会导致CI运行失败。
方案二
第二个选项是编写本地shell脚本监控GitLab服务器的构建状态,将新的构建状态徽章推送到GitHub状态网站仓库,但我认为GitLab本身应该有专门实现该需求的工具或选项。
方案三
第三个思路是使用GitLab的钩子脚本,但我还没搞清楚如何使用Gitlab-API封装来创建钩子,实现将作为github_repository镜像的gitlab_mirror_repo仓库的构建状态推送到github_build_status_website的需求。
问题
因此我想咨询:如何通过本地GitHub ssh-key,将我自建GitLab CI Runner上gitlab_mirror_repo仓库的构建状态.svg文件推送到名为github_build_status_website的GitHub仓库中?
备注
- 我了解GitLab的GitHub集成功能,但目前无力支付相关费用;
- 无需考虑
github_build_status_website仓库的其他内容,只要该仓库内包含.svg文件,我就可以基于它搭建网站。
解决方案
直接优化你提到的方案一即可解决所有问题,无需额外付费功能,也不会出现你担心的权限、仓库污染问题:
步骤1:配置CI保密变量,隔离权限
进入GitLab镜像项目的「设置」-「CI/CD」-「变量」页面,添加两个保密变量:
GH_SSH_KEY:值为你有权限推送GitHub状态仓库的SSH私钥内容,勾选「保密变量」「掩码变量」,不需要勾选「保护变量」即可对所有分支生效GH_STATUS_REPO_URL:值为GitHub状态仓库的SSH地址,格式为git@github.com:你的GitHub用户名/github_build_status_website.git
变量仅项目维护者可编辑查看,普通贡献者提交代码时无法访问,不会出现无权限导致CI失败的问题。
步骤2:调整CI阶段顺序,确保获取最终构建状态
将CI流程拆分为build(原有构建逻辑)和status_sync(状态同步)两个阶段,设置同步阶段在所有构建任务执行完成后触发,通过GitLab内置的CI预定义变量直接获取构建状态,不需要额外调用API查询。
可用的.gitlab-ci.yml配置参考:
stages: - build - status_sync # 你原有项目的构建任务,可保留原有所有配置 your_original_build_job: stage: build script: - 你的原有构建命令 when: always # 状态同步任务 sync_build_status_to_github: stage: status_sync # 依赖前面的构建任务,等它执行完再运行 needs: [your_original_build_job] # 不管构建成功、失败、取消都执行同步 when: always # 仅在主分支执行,避免其他分支/合并请求误操作 only: [main] before_script: # 初始化SSH环境 - mkdir -p ~/.ssh - echo "$GH_SSH_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan github.com >> ~/.ssh/known_hosts # 配置Git提交信息 - git config --global user.name "GitLab CI Sync Bot" - git config --global user.email "ci-bot@your-self-hosted-gitlab.com" script: # 克隆GitHub状态仓库 - git clone $GH_STATUS_REPO_URL status_repo - cd status_repo # 拉取当前构建对应的状态svg,以下两种方式二选一即可 # 方式1:直接拉取GitLab对应commit的构建状态徽章(替换为你自建GitLab的实际地址和项目路径) - wget -O build_status.svg "https://你的自建GitLab域名/项目所属组/项目名/-/badges/build.svg?commit_sha=$CI_COMMIT_SHA" # 方式2:根据内置变量$CI_JOB_STATUS(值为success/failed/canceled等)自己生成对应状态的svg # 提交推送 - git add build_status.svg - git commit -m "同步构建状态:$CI_COMMIT_SHA - $CI_JOB_STATUS" || echo "状态无变化,跳过提交" - git push origin main
其他说明
整个同步逻辑都在CI的临时运行环境中执行,所有Git操作都针对GitHub状态仓库,不会对你的gitlab_mirror_repo产生任何提交,不存在仓库污染问题。
如果不想修改CI配置,也可以使用GitLab项目Webhook实现:在项目设置中配置Webhook,触发条件选择「Pipeline事件」,自己搭建一个简单的后端服务接收事件,判断流水线状态后拉取svg推送到GitHub即可,该方案和CI流程完全解耦。
内容的提问来源于stack exchange,提问作者a.t.

