git 检查拉取请求是否是目标分支的最新请求

siv3szwd  于 2023-04-04  发布在  Git
关注(0)|答案(6)|浏览(222)

我们的项目使用受保护的分支,要求PR的基础分支与目标分支保持最新,以便合并。我们还使用Jenkins构建PR的未合并头部,因为我们使用的插件会在目标分支更改时自动重建所有打开的PR,这会很快堵塞管道。所以,如果PR在没有更新到目标分支的情况下被打开,我们希望能够立即停止Jenkins管道并通知提交者他们需要首先合并。
因此,使用GitHub API,我希望能够判断一个pull请求是否是目标分支的最新版本。最接近这一点的似乎是pull请求上的“mergable”属性,但看起来它只指示是否可以进行安全的自动合并,而不是分支是否已经是最新的。
是否有直接的API json标签可以查看?如果没有,是否有一种简单的方法可以通过git命令手动检查?

6mzjoqzu

6mzjoqzu1#

我不知道GitHub是否通过他们的API公开了这些信息,但你可以用Git命令手动检测到这一点。你想找到所谓的合并基,并确保这个提交与master(或任何你的主分支)的提示相同。
bash脚本的形式中,它看起来像这样:

if [ $(git merge-base @ master) == $(git rev-parse master) ]
then
  echo "Your branch is up to date."
  exit 0
else
  echo "You need to merge / rebase."
  exit 1
fi

如果您将此脚本作为构建步骤包含在内,那么退出值应该会导致Jenkins在必要时失败。
正如Dmitry's answer中提到的,在新版本的Git中,你可以使用git merge-base--is-ancestor标志将其简化为一个命令。脚本如下所示:

if git merge-base --is-ancestor master @
then
  echo "Your branch is up to date."
  exit 0
else
  echo "You need to merge / rebase."
  exit 1
fi
iyzzxitl

iyzzxitl2#

如果你想使用github API。任何返回pull request对象的API都会有mergeable_state字段在里面。如果它的值是behind,那就意味着在pull request创建之后,基础分支会被更新。即:请求分支已过期。
下面是mergestatestatus的解释
如果你在Jenkings服务器中处理webhook响应,大多数pull request事件,如pull request created、edited、closed或issue_comment事件,都会在pull request对象中包含mergeable_state信息。

ao218c7q

ao218c7q3#

有一种现代的方法可以做到这一点

git merge-base --is-ancestor A B

参见git-merge-base

xn1cxnb4

xn1cxnb44#

您需要使用GitHub的GraphQL API并检索mergeStateStatus值,正如其他人所提到的那样。下面的示例shell脚本假设您已经知道pull请求的编号并具有GitHub personal access token

# get-merge-state-status.sh example

# $TOKEN should be a defined environment variable

OWN_ORG='IBM'
REPO='data-import'

# get PR number from input
PR_NUMBER=$1

# prepare query with the appropriate parameters
QUERY=`cat <<EOF
{"query": 
    "query {
        repository(owner: \"${OWN_ORG}\", name: \"${REPO}\") {
            pullRequest(number: ${PR_NUMBER}) {
                title
                state
                mergeStateStatus
            }
        }
    }"
}
EOF`

# remove new lines so that the api understands the query
QUERY=$(echo $QUERY|tr -d '\n')

curl_opts=(
 -s
 -H "Authorization: bearer $TOKEN"
 -H "Accept: application/vnd.github.merge-info-preview+json"
 -X POST 
 -d "$QUERY"
)

# make the api call
JSON=$(curl "${curl_opts[@]}" https://api.github.com/graphql)

STATE=$(echo $JSON | jq -r '.data.repository.pullRequest.state')
M_STATE=$(echo $JSON | jq -r '.data.repository.pullRequest.mergeStateStatus')

echo $STATE $M_STATE

然后,您可以运行脚本如下:

[anask@supremedev]$ bash get-merge-state-status.sh 10
OPEN CLEAN

请注意,如果您使用的是GitHub Enterprise,请将地址从api.github.com更改为api.github.<SRV_NAME>.com

e4eetjau

e4eetjau5#

git rev-list可用于返回两个分支之间的差值,只要PR分支与目标分支(例如master分支)具有公共点:

git rev-list --left-right --count  \                                                                 
    origin/dev_develop...$(git branch --show-current) | \                                        
    awk '{print "Behind "$1" - Ahead "$2""}'

# output example: Behind 13 - Ahead 20

因此,您可以使用适当的退出代码添加以下检查:

target="origin/master"
source=$(git branch --show-current)

# compare the target branch to the pull request branch
behind=`git rev-list --left-right --count  $target...$source | awk '{print $1}'`

if [[ $behind = 0 ]];
    then
        echo 'Up to date!'
        exit 0
    else
        echo 'Please merge!'
        exit 1
fi

如果你使用的是Travis或其他CI作业,它们不会拉取所有提交,请在比较分支之前执行git fetch

# fetch the pull request branch's commits
git config remote.origin.fetch \
    +refs/heads/"${source}":refs/remotes/origin/"${source}"
git fetch origin
tyg4sfes

tyg4sfes6#

对于希望实现序列化合并的工作流的人来说,这是一个非常常见的问题。
这是可以使用Mergify轻松解决的问题。它通过strict workflow提供您所需要的。Mergify负责更新您的过期拉取请求,并为您命令合并有效的拉取请求。我们构建Mergify实际上首先解决了这个问题!
(免责声明:我是Mergify的作者之一)

相关问题