使用 GitHub Action 作为 Git 子模块检出仓库

3

背景

我的项目包含一个git子模块,两者都托管在GitHub上。
作为项目的一部分,子模块源代码将被构建,并且子模块中的更改可能会影响到包含的项目。

我的目标是确保子模块不会破坏包含的项目。
为此,我正在尝试在子模块存储库上创建一个GitHub操作,以便在push/pull时执行以下操作:

  • 克隆包含的项目
  • 使用特定的push/PR SHA检出子模块
  • 构建带有子模块的项目

问题

标准的Checkout v2 操作不支持这样的工作流程。
相反,我根据$GITHUB_SHA克隆并检出子模块,就像这样:

- name: Checkout project
  run: git clone <Project>
- name: Update submodules
  run: git submodule update --init --recursive
- name: Checkout submodule
  working-directory: ./<submodule dir>
      run: |
        git fetch
        git checkout $GITHUB_SHA
- name: Build
  run : make

这对于推送操作很有效,但不适用于拉取请求
在拉取请求中,我得到了类似于这样的内容:

fatal: reference is not a tree: 48fd1d918a25e7544969d13949b1d436f525412c

在PR中,由$GITHUB_SHA提供的SHA值根本找不到。

示例

问题

  • 为什么在PR中$GITHUB_SHA是错误的?它在PR中代表什么?
  • 是否有更好的方法来实现我想要做的事情?

澄清

如果不清楚的话-问题出现在子模块的repo上,而不是主项目repo上。
该操作正在子模块repo上运行,并且检出包含和子模块。

问题与PR的$GITHUB_SHA有关(子模块的),它似乎并不代表子模块上的提交,尽管我原本以为会这样。


更新1

我进行了另一次尝试:
将此作为“运行”步骤中的Checkout submodule:

        git fetch ${{ github.event.repository.git_url }}
        git fetch ${{ github.event.pull_request.head.repo.clone_url }}
        git checkout ${{ github.sha }} || git checkout ${{ github.event.pull_request.head.sha }}

在PR上,两个SHA的检出仍然失败,错误信息如下:

fatal: reference is not a tree

从原始存储库获取拉取请求(PR)未能解决问题。
pull_request.head.sha 看起来正确(这次是正确的SHA),但即使对于此,git checkout 也失败了!不知道为什么。


更新2

最终我找到了一个解决方法!
这是“检出子模块”的运行步骤:

      run: |
        git fetch --force ${{ github.event.repository.git_url }} "+refs/heads/*:refs/remotes/origin/*"
        git fetch --force ${{ github.event.repository.git_url }} "+refs/pull/*/head:refs/remotes/origin/pr/*"
        git checkout ${{ github.sha }} || git checkout ${{ github.event.pull_request.head.sha }}

我的操作如下:

  • git_url获取最新的提交记录
  • git_url获取所有拉取请求
  • 尝试检出github.sha。这对于推送操作有效,但在拉取请求中无效
  • 如果以上步骤失败,则检出github.event.pull_request.head.sha。这对于拉取请求有效,但在推送操作中无效...

然而,同样存在一些问题-

  • 为什么github.sha在拉取请求中是错误的?在拉取请求中表示什么?
  • 除了从远程获取所有拉取请求并尝试github.shagithub.event.pull_request.head.sha之外,是否有更好的方法实现我想要的功能?

你能否在你的 Checkout 子模块的 "run" 步骤中执行 git statusgit remote -v 命令,以确保你处于正确的工作目录中? - VonC
@VonC git remote -v 不相关,因为我没有使用命名的远程,而是提供了一个完整的远程 URL。拉取命令成功完成。 git status 返回:HEAD 处于分离状态...没有要提交的内容,工作树干净。 - Amir Gonnen
$GITHUB_SHA是否可能是PR分支的一部分,而该分支不是默认refspec的一部分?(如此处所示:https://gist.github.com/piscisaureus/3342247)。您可以添加一个远程,然后`git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/origin/pr/*",然后git fetch`吗? - VonC
最终我找到了一个解决方法,通过获取拉取请求并尝试 GitHub 上下文提供的两个 SHA,详见“更新2”。我没有将其作为答案添加,因为它引发更多问题而不是答案... - Amir Gonnen
@VonC 好的,我想我已经搞定了!请看我的回答。 - Amir Gonnen
干得好!我已经删除了我的答案,因为它现在只是噪音。 - VonC
1个回答

2
我在这里找到了答案:
https://frontside.com/blog/2020-05-26-github-actions-pull_request/#how-does-pull_request-affect-actionscheckout 显然,在PR的情况下,github.sha(或$GITHUB_SHA)代表的是从基础分支合并到目标分支所创建的提交的SHA,而不是基础变更提交本身的SHA。
要获取它,我需要获取refs/pull/*/merge而不是refs/pull/*/head
现在这个运行步骤更有意义了:
        git fetch --force ${{ github.event.repository.git_url }} "+refs/heads/*:refs/remotes/origin/*"
        git fetch --force ${{ github.event.repository.git_url }} "+refs/pull/*/merge:refs/remotes/origin/pr/*"
        git checkout ${{ github.sha }}

第一个fetch将获取push操作的heads。第二个将获取PR的合并提交。
两者都由github.sha表示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接