diff --git a/bin/autoresolve b/bin/autoresolve index 6e3b8911..08ca1773 100755 --- a/bin/autoresolve +++ b/bin/autoresolve @@ -3,45 +3,31 @@ # First some definitions and functions : "${ICINGABOT_TOKEN:=}" +: "${PULL_REQUEST_NO:=}" RE_IS_CONFLICTING="^UU (.*)" RE_IS_SOURCE_CATALOG="^UU src/([a-z]{2}_[A-Z]{2})/LC_MESSAGES/icinga.po" -RE_LABEL="automatic conflict resolution \(UTC([-+][0-9])?\)" PR_QUERY=$(sed ':a;N;$!ba;s/\n/\\n/g' << GRAPHQL -query { - repository(owner:\"Icinga\", name:\"L10n\") { - pullRequests(first: 100, states: OPEN) { - totalCount - edges { - node { - id - number - author { - login - } - mergeable - maintainerCanModify - headRefName - headRepository { - sshUrl - } - comments(first: 100) { - totalCount - edges { - node { - author { - login - } - } - } - } - labels(first: 100) { - totalCount - edges { - node { - name - } +query (\$number: Int!) { + repository(owner:\"Icinga\", name:\"L10n\") { + pullRequest(number: \$number) { + id + author { + login + } + mergeable + maintainerCanModify + headRefName + headRepository { + sshUrl + } + comments(first: 100) { + totalCount + edges { + node { + author { + login } } } @@ -51,8 +37,11 @@ query { } GRAPHQL ) -get_open_pull_requests() { - curl -sH "Authorization: bearer $ICINGABOT_TOKEN" -d "{\"query\": \"$PR_QUERY\"}" https://api.github.com/graphql +get_pull_request() { + local pull_request_no="$1" + local data="{\"query\": \"$PR_QUERY\", \"variables\": {\"number\": $pull_request_no}}" + + curl -sH "Authorization: bearer $ICINGABOT_TOKEN" -d "$data" https://api.github.com/graphql } FRIENDLY_REMINDER=$(sed ':a;N;$!ba;s/\n/\\n/g' << TEXT @@ -115,80 +104,40 @@ read_json_blob() { echo $json | jq $varpath } -should_get_resolved() { - local offset="$1" - - if [ -z "$offset" ]; then - offset="UTC" - else - case "${offset:0:1}" in - "-") - offset="UTC+${offset:1:2}" - ;; - "+") - offset="UTC-${offset:1:2}" - ;; - esac - fi - - hour=$(TZ=$offset date +%H) - [[ "$hour" == "00" ]] - return -} # Actual script starts here set -e -if [ -z "$ICINGABOT_TOKEN" ]; then - echo "Environment variable ICINGABOT_TOKEN not set" - exit 1 -fi +manage_remote=true +if [ -n "$PULL_REQUEST_NO" ]; then + if [ -z "$ICINGABOT_TOKEN" ]; then + echo "Environment variable ICINGABOT_TOKEN not set" + exit 1 + fi -OPEN_PRS=$(get_open_pull_requests) -PULL_REQUESTS=$(read_json_blob "$OPEN_PRS" .data.repository.pullRequests.edges) + PR_NUMBER="$PULL_REQUEST_NO" + PR_DATA="$(get_pull_request $PR_NUMBER)" + PULL_REQUEST=$(read_json_blob "$PR_DATA" .data.repository.pullRequest) -TOTAL_PULL_REQUESTS=$(read_json_var "$OPEN_PRS" .data.repository.pullRequests.totalCount) -for (( i = 0; i < $TOTAL_PULL_REQUESTS; i++ )); do - PR_NUMBER=$(read_json_var "$PULL_REQUESTS" .[$i].node.number) - - PR_MERGEABLE=$(read_json_var "$PULL_REQUESTS" .[$i].node.mergeable) + PR_MERGEABLE=$(read_json_var "$PULL_REQUEST" .mergeable) if [[ "$PR_MERGEABLE" != "CONFLICTING" ]] && [[ "$PR_MERGEABLE" != "UNKNOWN" ]]; then echo "Ignoring pull request #$PR_NUMBER. No conflicts detected" - continue + exit fi echo "Attempting to resolve pull request #$PR_NUMBER..." - # Pull requests only get automatically resolved if they have an appropriate label - SHOULD_GET_RESOLVED=false - TOTAL_LABELS=$(read_json_var "$PULL_REQUESTS" .[$i].node.labels.totalCount) - for (( j = 0; j < $TOTAL_LABELS; j++ )); do - LABEL=$(read_json_var "$PULL_REQUESTS" .[$i].node.labels.edges[$j].node.name) - if [[ "$LABEL" =~ $RE_LABEL ]] && [[ ${BASH_REMATCH[0]} ]]; then - echo "Identified label '$LABEL'. Checking schedule..." - if should_get_resolved "${BASH_REMATCH[1]}"; then - SHOULD_GET_RESOLVED=true - break - fi - fi - done + PR_ID=$(read_json_var "$PULL_REQUEST" .id) - if [[ "$SHOULD_GET_RESOLVED" == "false" ]]; then - echo "Ignoring pull request #$PR_NUMBER. No label found or it's not scheduled for now" - continue - fi - - PR_ID=$(read_json_var "$PULL_REQUESTS" .[$i].node.id) - - # If however the author disabled maintainer edits, tell him this once - PR_IS_ACCESSIBLE=$(read_json_var "$PULL_REQUESTS" .[$i].node.maintainerCanModify) + # If the author disabled maintainer edits, tell him this once + PR_IS_ACCESSIBLE=$(read_json_var "$PULL_REQUEST" .maintainerCanModify) if [[ "$PR_IS_ACCESSIBLE" == "false" ]]; then ICINGABOT_COMMENTED=false - TOTAL_COMMENTS=$(read_json_var "$PULL_REQUESTS" .[$i].node.comments.totalCount) - for (( j = 0; j < $TOTAL_COMMENTS; j++ )); do - COMMENT_AUTHOR=$(read_json_var "$PULL_REQUESTS" .[$i].node.comments.edges[$j].node.author.login) + TOTAL_COMMENTS=$(read_json_var "$PULL_REQUEST" .comments.totalCount) + for (( i = 0; i < $TOTAL_COMMENTS; i++ )); do + COMMENT_AUTHOR=$(read_json_var "$PULL_REQUEST" .comments.edges[$i].node.author.login) if [[ $COMMENT_AUTHOR != "icingabot" ]]; then continue fi @@ -202,60 +151,69 @@ for (( i = 0; i < $TOTAL_PULL_REQUESTS; i++ )); do fi echo "Ignoring pull request #$PR_NUMBER. Maintainer edits are disallowed" - continue + exit fi - PR_AUTHOR=$(read_json_var "$PULL_REQUESTS" .[$i].node.author.login) - PR_BRANCH=$(read_json_var "$PULL_REQUESTS" .[$i].node.headRefName) - PR_REPO=$(read_json_var "$PULL_REQUESTS" .[$i].node.headRepository.sshUrl) + PR_AUTHOR=$(read_json_var "$PULL_REQUEST" .author.login) + PR_BRANCH=$(read_json_var "$PULL_REQUEST" .headRefName) + PR_REPO=$(read_json_var "$PULL_REQUEST" .headRepository.sshUrl) echo "Resolving pull request #$PR_NUMBER (Author: $PR_AUTHOR, Branch: $PR_BRANCH, Repo: $PR_REPO)" +else + echo "Attempting to resolve source catalog conflicts in local HEAD" + manage_remote=false +fi +if [ "$manage_remote" == true ]; then # Fetch the remote branch git remote add $PR_AUTHOR $PR_REPO git fetch $PR_AUTHOR $PR_BRANCH # Checkout the branch git checkout -b pull/$PR_NUMBER $PR_AUTHOR/$PR_BRANCH +fi - # Attempt to merge master, should fail - git merge --no-ff --no-commit origin/master || true +# Attempt to merge master, should fail +git merge --no-ff --no-commit origin/master || true - if [ ! -f .git/MERGE_HEAD ]; then - echo "Merge aborted or succeeded for some unknown reason. Cancelling pull request resolution" - continue - fi +if [ ! -f .git/MERGE_HEAD ]; then + echo "Merge aborted or succeeded for some unknown reason. Cancelling pull request resolution" + exit +fi - # Resolve source catalog conflicts - GIT_STATUS=$(git status -suno) - while IFS= read -r line; do - if [[ "$line" =~ $RE_IS_CONFLICTING ]] && [[ ${BASH_REMATCH[0]} ]]; then - # Only a conflict, yet - FILENAME="${BASH_REMATCH[1]}" +# Resolve source catalog conflicts +GIT_STATUS=$(git status -suno) +while IFS= read -r line; do + if [[ "$line" =~ $RE_IS_CONFLICTING ]] && [[ ${BASH_REMATCH[0]} ]]; then + # Only a conflict, yet + FILENAME="${BASH_REMATCH[1]}" - # Reset file to the author's version - git checkout --ours $FILENAME + # Reset file to the author's version + git checkout --ours $FILENAME - if [[ "$line" =~ $RE_IS_SOURCE_CATALOG ]] && [[ ${BASH_REMATCH[0]} ]]; then - # It's a source catalog! Utilize msgmerge to update the source catalog with the latest messages - LOCALE="${BASH_REMATCH[1]}" - echo "Resolving file '$FILENAME':" - msgmerge --update --backup=none --lang=$LOCALE --sort-by-file $FILENAME src/icinga.pot - git add $FILENAME - else - # It's some other file we don't care about. That's the authors duty to fix this - git add $FILENAME - fi + if [[ "$line" =~ $RE_IS_SOURCE_CATALOG ]] && [[ ${BASH_REMATCH[0]} ]]; then + # It's a source catalog! Utilize msgmerge to update the source catalog with the latest messages + LOCALE="${BASH_REMATCH[1]}" + echo "Resolving file '$FILENAME':" + msgmerge --update --backup=none --lang=$LOCALE --sort-by-file $FILENAME src/icinga.pot + git add $FILENAME + else + # It's some other file we don't care about. That's the authors duty to fix this + git add $FILENAME fi - done <<< "$GIT_STATUS" + fi +done <<< "$GIT_STATUS" - # Finish the merge - echo -e "Update with base 'origin/master'\n\nResolves source catalog conflicts" > .git/MERGE_MSG - GIT_EDITOR=true git merge --continue +# Finish the merge +echo -e "Update with base 'origin/master'\n\nResolves source catalog conflicts" > .git/MERGE_MSG +GIT_EDITOR=true git merge --continue +if [ "$manage_remote" == true ]; then echo "Successfully resolved pull request #$PR_NUMBER. Pushing the changes now" # Push the new changes git push $PR_AUTHOR pull/$PR_NUMBER:$PR_BRANCH send_success_message "$PR_ID" -done +else + echo "Successfully resolved source catalog conflicts in local HEAD" +fi