Eyal Gerber
Eyal Gerber

Reputation: 1657

How to check if a pull request on GitHub has conflicts using a script?

I was wondering how to check if a pull request has conflicts on GitHub using a script from my PC? There is a nice solution mentioned here to do it via GitHub actions: https://stackoverflow.com/a/71692270/4441211

However, taking the same script from https://olivernybroe/action-conflict-finder and running it on my PC won't work unless I do a local merge. After identifying the conflicts I would have to discard the local merge. This process seems inefficient and I was looking for a "cleaner" and faster solution.

Upvotes: 2

Views: 2489

Answers (4)

Eyal Gerber
Eyal Gerber

Reputation: 1657

Here is another answer to my question. This answer, I believe, is better than my previous answer. This also aligns with the comment that @VonC made in the question above to use git merge-tree. Since a pull request is a request to merge one branch to another, all we need to do is check whether two of the branches have merge conflicts. This can also be done locally (assuming the branches are up to date locally):

So this solution would be to do a "virtual" merge and easily see the result of the merge, including conflicts. Here is my solution using bash:

# Define the branches
origin_branch="$(git rev-parse --abbrev-ref HEAD)" #get current checked out branch
destination_branch="origin/main"

# Perform the merge-tree command (virtual merge)
git merge-tree --write-tree $origin_branch $destination_branch

And if you want to see only the conflicts, you can modify the script above as follows:

# Define the branches
origin_branch="$(git rev-parse --abbrev-ref HEAD)" #get current checked out branch
destination_branch="origin/main"

# Perform the merge-tree command and capture the output
merge_output=$(git merge-tree --write-tree --name-only $origin_branch $destination_branch)

# Extract file names with conflicts from the merge output using grep and store in an array
mapfile -t conflicted_files < <(echo "$merge_output" | grep -E '^CONFLICT*' | awk '{print $NF}')

# Display the list of file conflicts
echo "Conflicts found in the following files:"
printf '%s\n' "${conflicted_files[@]}"

Upvotes: 1

dacucar
dacucar

Reputation: 306

I had a similar need and found that the gh pr view command can be used to query for this information:

$ gh pr view --json mergeable 111

{
  "mergeable": "CONFLICTING"
}

The only "but" is that the possible values for mergeable are CONFLICTING, MERGEABLE or UNKNOWN (source), which would need to be in consideration if you are writing any sort of automation using this information.

There is also mergeStatusState that may provide additional information in other use cases beyond checking merge-ability.

Upvotes: 3

L&#233;a Gris
L&#233;a Gris

Reputation: 19555

Here is how to pipe it without a shell loop, and parse JSON natively, either with gh api -q built-in jq query, or jq itself.

#!/usr/bin/env sh

REPOSITORY_NAME=
OWNER=

gh api -H "Accept: application/vnd.github+json" \
  "repos/${OWNER}/${REPOSITORY_NAME}/pulls" --cache 1h |
  jq -j --arg curbranch "$(git rev-parse --abbrev-ref HEAD)" \
  '
.[] | select(
  (.base.ref == $curbranch) and
  (.state == "open") and
  (.draft == false)
) | .number | tostring + "\u0000"
' |
  xargs -0 -I{} \
    gh api -H "Accept: application/vnd.github+json" \
    "repos/${OWNER}/${REPOSITORY_NAME}/pulls/{}" --cache 1h \
    -q '
"PR #" + (.number | tostring) + ": " +
.title + " is " +
if .mergeable != false then "mergeable" else "not mergeable" end
'

Altenatively using a while read -r loop instead of xargs which seems problematic in some Windows environment:

gh api -H "Accept: application/vnd.github+json" \
  "repos/${OWNER}/${REPOSITORY_NAME}/pulls" --cache 1h |
  jq -r --arg curbranch "$(git rev-parse --abbrev-ref HEAD)" \
  '
.[] | select(
  (.base.ref == $curbranch) and
  (.state == "open") and
  (.draft != true)
) | .number
' | while read -r pr; do
    gh api -H "Accept: application/vnd.github+json" \
    "repos/${OWNER}/${REPOSITORY_NAME}/pulls/${pr}" --cache 1h \
    -q '
"PR #" + (.number | tostring) + ": " +
.title + " is " +
if .mergeable != false then "mergeable" else "not mergeable" end
'
done

Upvotes: 5

Eyal Gerber
Eyal Gerber

Reputation: 1657

So I wanted to share my solution which is much "cleaner" than what I wrote in the question. I simply used GitHub API to retrieve the "mergeable" state information of the pull request. This does not require me to do any local merges and discards to search for conflict-identifying strings such as ">>>>>>>" etc.

#!/bin/bash    
OWNER="GitHub_UserName" #your github user name or organization name - whoever owns the repository
REPOSITORY_NAME="Your_Repo_Name"
PR_List=$(gh pr list) #Get list of pull requests of the repository
Current_Branch=$(git rev-parse --abbrev-ref HEAD) #get the current branch name
if [[ $(grep "$Current_Branch" <<< "$PR_List") ]]; then #If true then there exists a PR for this branch in the repository 
        #Get the line of the pull request from the list:
        PR_Line=$(grep "$Current_Branch" <<< "$PR_List")
        
        #Get the specific numerical ID of the pull request
        PR_ID=$(awk '{print $1}' <<< "$PR_Line")    #taken from https://stackoverflow.com/a/36736249/4441211

        #now get all the PR information from GitHub:
        pr_data=$(gh api -H "Accept: application/vnd.github+json" repos/$OWNER/$REPOSITORY_NAME/pulls/$PR_ID)

        #Now extract the specific "mergeable" state of the PR and then check it:
        mergeable_row=$(grep "mergeable" <<< "$pr_data")
        mergeable_string=$(echo "$mergeable_row" | awk -F 'mergeable":' '{printf $NF}')
        mergeable_state=$(echo "$mergeable_string" | cut -d',' -f 1)
        echo "Mergeable = $mergeable_state" #for debug
        if [ "$mergeable_state" == "false" ]; then
            MergeIssuesFound="yes"
            echo "Pull Request in repository $REPOSITORY_NAME is NOT mergeable"
        else
            MergeIssuesFound="no"
            echo "Pull Request in repository $REPOSITORY_NAME is mergeable"
        fi
fi

Upvotes: 1

Related Questions