• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2
3set -xe
4
5OWNER=$1
6REPOSITORY=$2
7shift 2
8
9UPSTREAM=origin
10DEFAULT_BRANCH=main
11
12COMMIT_QUEUE_LABEL="commit-queue"
13COMMIT_QUEUE_FAILED_LABEL="commit-queue-failed"
14
15commit_queue_failed() {
16  pr=$1
17
18  gh pr edit "$pr" --add-label "${COMMIT_QUEUE_FAILED_LABEL}"
19
20  # shellcheck disable=SC2154
21  cqurl="${GITHUB_SERVER_URL}/${OWNER}/${REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
22  body="<details><summary>Commit Queue failed</summary><pre>$(cat output)</pre><a href='$cqurl'>$cqurl</a></details>"
23  echo "$body"
24
25  gh pr comment "$pr" --body "$body"
26
27  rm output
28}
29
30# TODO(mmarchini): should this be set with whoever added the label for each PR?
31git config --local user.email "github-bot@iojs.org"
32git config --local user.name "Node.js GitHub Bot"
33
34for pr in "$@"; do
35  gh pr view "$pr" --json labels --jq ".labels" > labels.json
36  # Skip PR if CI was requested
37  if jq -e 'map(.name) | index("request-ci")' < labels.json; then
38    echo "pr ${pr} skipped, waiting for CI to start"
39    continue
40  fi
41
42  # Skip PR if CI is still running
43  if gh pr checks "$pr" | grep -q "\spending\s"; then
44    echo "pr ${pr} skipped, CI still running"
45    continue
46  fi
47
48  # Delete the commit queue label
49  gh pr edit "$pr" --remove-label "$COMMIT_QUEUE_LABEL"
50
51  if jq -e 'map(.name) | index("commit-queue-squash")' < labels.json; then
52    MULTIPLE_COMMIT_POLICY="--fixupAll"
53  elif jq -e 'map(.name) | index("commit-queue-rebase")' < labels.json; then
54    MULTIPLE_COMMIT_POLICY=""
55  else
56    MULTIPLE_COMMIT_POLICY="--oneCommitMax"
57  fi
58
59  git node land --autorebase --yes $MULTIPLE_COMMIT_POLICY "$pr" >output 2>&1 || echo "Failed to land #${pr}"
60  # cat here otherwise we'll be supressing the output of git node land
61  cat output
62
63  # TODO(mmarchini): workaround for ncu not returning the expected status code,
64  # if the "Landed in..." message was not on the output we assume land failed
65  if ! grep -q '. Post "Landed in .*/pull/'"${pr}" output; then
66    commit_queue_failed "$pr"
67    # If `git node land --abort` fails, we're in unknown state. Better to stop
68    # the script here, current PR was removed from the queue so it shouldn't
69    # interfere again in the future.
70    git node land --abort --yes
71    continue
72  fi
73
74  if [ -z "$MULTIPLE_COMMIT_POLICY" ]; then
75    start_sha=$(git rev-parse $UPSTREAM/$DEFAULT_BRANCH)
76    end_sha=$(git rev-parse HEAD)
77    commits="${start_sha}...${end_sha}"
78
79    if ! git push $UPSTREAM $DEFAULT_BRANCH >> output 2>&1; then
80      commit_queue_failed "$pr"
81      continue
82    fi
83  else
84    # If there's only one commit, we can use the Squash and Merge feature from GitHub.
85    # TODO: use `gh pr merge` when the GitHub CLI allows to customize the commit title (https://github.com/cli/cli/issues/1023).
86    commit_title=$(git log -1 --pretty='format:%s')
87    commit_body=$(git log -1 --pretty='format:%b')
88    commit_head=$(grep 'Fetched commits as' output | cut -d. -f3 | xargs git rev-parse)
89
90    jq -n \
91      --arg title "${commit_title}" \
92      --arg body "${commit_body}" \
93      --arg head "${commit_head}" \
94      '{merge_method:"squash",commit_title:$title,commit_message:$body,sha:$head}' > output.json
95    cat output.json
96    if ! gh api -X PUT "repos/${OWNER}/${REPOSITORY}/pulls/${pr}/merge" --input output.json > output; then
97      commit_queue_failed "$pr"
98      continue
99    fi
100    cat output
101    if ! commits="$(jq -r 'if .merged then .sha else error("not merged") end' < output)"; then
102      commit_queue_failed "$pr"
103      continue
104    fi
105    rm output.json
106  fi
107
108  rm output
109
110  gh pr comment "$pr" --body "Landed in $commits"
111
112  [ -z "$MULTIPLE_COMMIT_POLICY" ] && gh pr close "$pr"
113done
114
115rm -f labels.json
116