diff --git a/.github/workflows/check-cherry-picks.yml b/.github/workflows/check-cherry-picks.yml index e85fa59bb6995..3c6ef1d189206 100644 --- a/.github/workflows/check-cherry-picks.yml +++ b/.github/workflows/check-cherry-picks.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - filter: blob:none + filter: tree:0 path: trusted - name: Check cherry-picks @@ -28,4 +28,4 @@ jobs: BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | - ./trusted/maintainers/scripts/check-cherry-picks.sh "$BASE_SHA" "$HEAD_SHA" + ./trusted/ci/check-cherry-picks.sh "$BASE_SHA" "$HEAD_SHA" diff --git a/maintainers/scripts/check-cherry-picks.sh b/ci/check-cherry-picks.sh similarity index 58% rename from maintainers/scripts/check-cherry-picks.sh rename to ci/check-cherry-picks.sh index 0e02c709d8f5d..612174925f575 100755 --- a/maintainers/scripts/check-cherry-picks.sh +++ b/ci/check-cherry-picks.sh @@ -11,14 +11,15 @@ fi # Make sure we are inside the nixpkgs repo, even when called from outside cd "$(dirname "${BASH_SOURCE[0]}")" -PICKABLE_BRANCHES=${PICKABLE_BRANCHES:-master staging release-??.?? staging-??.??} +PICKABLE_BRANCHES="master release-??.?? staging-??.?? haskell-updates python-updates" problem=0 -commits="$(git rev-list \ - -E -i --grep="cherry.*[0-9a-f]{40}" --reverse \ - "$1..$2")" +# Not everyone calls their remote "origin" +remote="$(git remote -v | grep -i 'NixOS/nixpkgs' | head -n1 | cut -f1 || true)" -while read new_commit_sha ; do +commits="$(git rev-list --reverse "$1..$2")" + +while read -r new_commit_sha ; do if [ -z "$new_commit_sha" ] ; then continue # skip empty lines fi @@ -33,30 +34,47 @@ while read new_commit_sha ; do 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}' + | grep -Eoi -m1 '[0-9a-f]{40}' || true ) - if [ "$?" != "0" ] ; then - echo " ? Couldn't locate original commit hash in message" - [ "$GITHUB_ACTIONS" = 'true' ] && echo ::endgroup:: + if [ -z "$original_commit_sha" ] ; then + if [ "$GITHUB_ACTIONS" = 'true' ] ; then + echo ::endgroup:: + echo -n "::error ::" + else + echo -n " ✘ " + fi + echo "Couldn't locate original commit hash in message" + echo "Note this should not necessarily be treated as a hard fail, but a reviewer's attention should" \ + "be drawn to it and github actions have no way of doing that but to raise a 'failure'" + problem=1 continue fi set -f # prevent pathname expansion of patterns - for branch_pattern in $PICKABLE_BRANCHES ; do + for pattern in $PICKABLE_BRANCHES ; do set +f # re-enable pathname expansion + # Reverse sorting by refname and taking one match only means we can only backport + # from unstable and the latest stable. That makes sense, because even right after + # branch-off, when we have two supported stable branches, we only ever want to cherry-pick + # **to** the older one, but never **from** it. + # This makes the job significantly faster in the case when commits can't be found, + # because it doesn't need to iterate through 20+ branches, which all need to be fetched. + branches="$(git for-each-ref --sort=-refname --format="%(refname)" \ + "refs/remotes/${remote:-origin}/$pattern" | head -n1)" + 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 + range_diff_common='git --no-pager 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 $range_diff_common --no-color 2> /dev/null | grep -E '^ {4}[+-]{2}' > /dev/null ; then if [ "$GITHUB_ACTIONS" = 'true' ] ; then echo ::endgroup:: echo -n "::warning ::" @@ -79,11 +97,7 @@ while read new_commit_sha ; do # move on to next commit continue 3 fi - done <<< "$( - git for-each-ref \ - --format="%(refname)" \ - "refs/remotes/origin/$branch_pattern" - )" + done <<< "$branches" done if [ "$GITHUB_ACTIONS" = 'true' ] ; then