about summary refs log tree commit diff
path: root/maintainers/scripts
diff options
context:
space:
mode:
authorRobert Scott <code@humanleg.org.uk>2022-05-07 12:54:51 +0100
committerRobert Scott <code@humanleg.org.uk>2024-04-01 16:10:13 +0100
commitfbad66daa54da694be13df7b24b18b7bad843d56 (patch)
tree66cdfefa9e871e751a233928c902f6b93e28ff14 /maintainers/scripts
parent354e1366a78c6d178bdd636ea8e9b8628a015e12 (diff)
add "Check cherry-picks" github action
the intention being to catch commits which declare themselves as
cherry-picks, but either:

 - don't refer to a commit in the master or staging branches
 - are significantly altered from their original commit

determining the latter is not an exact science, but the heuristic of
looking for differences in only the added or removed lines seems to
work quite well. still, this should be considered an assistant
for reviewers rather than a hard failure. unfortunately github
workflows don't have a way of raising a gentle warning instead of a
failure.

the formatting of the output also leaves something to be desired due
to the limitations of github actions' "group" commands.
Diffstat (limited to 'maintainers/scripts')
-rwxr-xr-xmaintainers/scripts/check-cherry-picks.sh92
1 files changed, 92 insertions, 0 deletions
diff --git a/maintainers/scripts/check-cherry-picks.sh b/maintainers/scripts/check-cherry-picks.sh
new file mode 100755
index 0000000000000..082c33fe088a0
--- /dev/null
+++ b/maintainers/scripts/check-cherry-picks.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+# Find alleged cherry-picks
+
+set -e
+
+if [ $# != "2" ] ; then
+  echo "usage: check-cherry-picks.sh base_rev head_rev"
+  exit 2
+fi
+
+PICKABLE_BRANCHES=${PICKABLE_BRANCHES:-master staging release-??.?? staging-??.??}
+problem=0
+
+while read new_commit_sha ; do
+  if [ "$GITHUB_ACTIONS" = 'true' ] ; then
+    echo "::group::Commit $new_commit_sha"
+  else
+    echo "================================================="
+  fi
+  git rev-list --max-count=1 --format=medium "$new_commit_sha"
+  echo "-------------------------------------------------"
+
+  original_commit_sha=$(
+    git rev-list --max-count=1 --format=format:%B "$new_commit_sha" \
+    | grep -Ei -m1 "cherry.*[0-9a-f]{40}" \
+    | grep -Eoi -m1 '[0-9a-f]{40}'
+  )
+  if [ "$?" != "0" ] ; then
+    echo "  ? Couldn't locate original commit hash in message"
+    [ "$GITHUB_ACTIONS" = 'true' ] && echo ::endgroup::
+    continue
+  fi
+
+  set -f # prevent pathname expansion of patterns
+  for branch_pattern in $PICKABLE_BRANCHES ; do
+    set +f # re-enable pathname expansion
+
+    while read -r picked_branch ; do
+      if git merge-base --is-ancestor "$original_commit_sha" "$picked_branch" ; then
+        echo "  ✔ $original_commit_sha present in branch $picked_branch"
+
+        range_diff_common='git range-diff
+          --no-notes
+          --creation-factor=100
+          '"$original_commit_sha~..$original_commit_sha"'
+          '"$new_commit_sha~..$new_commit_sha"'
+        '
+
+        if $range_diff_common --no-color | grep -E '^ {4}[+-]{2}' > /dev/null ; then
+          if [ "$GITHUB_ACTIONS" = 'true' ] ; then
+            echo ::endgroup::
+            echo -n "::warning ::"
+          else
+            echo -n "  ⚠ "
+          fi
+          echo "Difference between $new_commit_sha and original $original_commit_sha may warrant inspection:"
+
+          $range_diff_common --color
+
+          problem=1
+        else
+          echo "  ✔ $original_commit_sha highly similar to $new_commit_sha"
+          $range_diff_common --color
+          [ "$GITHUB_ACTIONS" = 'true' ] && echo ::endgroup::
+        fi
+
+        # move on to next commit
+        continue 3
+      fi
+    done <<< "$(
+      git for-each-ref \
+      --format="%(refname)" \
+      "refs/remotes/origin/$branch_pattern"
+    )"
+  done
+
+  if [ "$GITHUB_ACTIONS" = 'true' ] ; then
+    echo ::endgroup::
+    echo -n "::error ::"
+  else
+    echo -n "  ✘ "
+  fi
+  echo "$original_commit_sha not found in any pickable branch"
+
+  problem=1
+done <<< "$(
+  git rev-list \
+    -E -i --grep="cherry.*[0-9a-f]{40}" --reverse \
+    "$1..$2"
+)"
+
+exit $problem