mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-09 19:13:26 +03:00

Instead of failing the job, the workflow will now post review comments as "Request Changes". This makes the feedback more readily visible and avoids having to merge despite a failing CI job. It is also a pre-requisite to enable required status checks / required workflows in the future. Committers are asked to confirm the differences by explicitly dismissing the generated review. After dismissal, the related review comment will automatically be marked as "resolved". The comments only report warnings and errors. Reviews are automatically dismissed when they have been addressed by the author and no problems remain. If problems remain, existing, still pending, review comments will be updated. If the same problems had already been dismissed earlier, no new review comment will be created either.
139 lines
4.6 KiB
Bash
Executable file
139 lines
4.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Find alleged cherry-picks
|
|
|
|
set -euo pipefail
|
|
|
|
if [[ $# != "2" && $# != "3" ]] ; then
|
|
echo "usage: check-cherry-picks.sh base_rev head_rev [markdown_file]"
|
|
exit 2
|
|
fi
|
|
|
|
markdown_file="$(realpath ${3:-/dev/null})"
|
|
[ -v 3 ] && rm -f "$markdown_file"
|
|
|
|
# Make sure we are inside the nixpkgs repo, even when called from outside
|
|
cd "$(dirname "${BASH_SOURCE[0]}")"
|
|
|
|
PICKABLE_BRANCHES="master staging release-??.?? staging-??.?? haskell-updates python-updates staging-next staging-next-??.??"
|
|
problem=0
|
|
|
|
# Not everyone calls their remote "origin"
|
|
remote="$(git remote -v | grep -i 'NixOS/nixpkgs' | head -n1 | cut -f1 || true)"
|
|
|
|
commits="$(git rev-list --reverse "$1..$2")"
|
|
|
|
log() {
|
|
type="$1"
|
|
shift 1
|
|
|
|
local -A prefix
|
|
prefix[success]=" ✔ "
|
|
if [ -v GITHUB_ACTIONS ]; then
|
|
prefix[warning]="::warning::"
|
|
prefix[error]="::error::"
|
|
else
|
|
prefix[warning]=" ⚠ "
|
|
prefix[error]=" ✘ "
|
|
fi
|
|
|
|
echo "${prefix[$type]}$@"
|
|
|
|
# Only logging errors and warnings, which allows comparing the markdown file
|
|
# between pushes to the PR. Even if a new, proper cherry-pick, commit is added
|
|
# it won't change the markdown file's content and thus not trigger another comment.
|
|
if [ "$type" != "success" ]; then
|
|
local -A alert
|
|
alert[warning]="WARNING"
|
|
alert[error]="CAUTION"
|
|
echo >> $markdown_file
|
|
echo "> [!${alert[$type]}]" >> $markdown_file
|
|
echo "> $@" >> $markdown_file
|
|
fi
|
|
}
|
|
|
|
endgroup() {
|
|
if [ -v GITHUB_ACTIONS ] ; then
|
|
echo ::endgroup::
|
|
fi
|
|
}
|
|
|
|
while read -r new_commit_sha ; do
|
|
if [ -v GITHUB_ACTIONS ] ; 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}' || true
|
|
)
|
|
if [ -z "$original_commit_sha" ] ; then
|
|
endgroup
|
|
log warning "Couldn't locate original commit hash in message of $new_commit_sha."
|
|
problem=1
|
|
continue
|
|
fi
|
|
|
|
set -f # prevent pathname expansion of patterns
|
|
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
|
|
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 2> /dev/null | grep -E '^ {4}[+-]{2}' > /dev/null ; then
|
|
log success "$original_commit_sha present in branch $picked_branch"
|
|
endgroup
|
|
log warning "Difference between $new_commit_sha and original $original_commit_sha may warrant inspection."
|
|
|
|
# First line contains commit SHAs, which we already printed.
|
|
$range_diff_common --color | tail -n +2
|
|
|
|
echo -e "> <details><summary>Show diff</summary>\n>" >> $markdown_file
|
|
echo '> ```diff' >> $markdown_file
|
|
# The output of `git range-diff` is indented with 4 spaces, which we need to match with the
|
|
# code blocks indent to get proper syntax highlighting on GitHub.
|
|
$range_diff_common | tail -n +2 | sed -Ee 's/^ {4}/> /g' >> $markdown_file
|
|
echo '> ```' >> $markdown_file
|
|
echo "> </details>" >> $markdown_file
|
|
|
|
problem=1
|
|
else
|
|
log success "$original_commit_sha present in branch $picked_branch"
|
|
log success "$original_commit_sha highly similar to $new_commit_sha"
|
|
$range_diff_common --color
|
|
endgroup
|
|
fi
|
|
|
|
# move on to next commit
|
|
continue 3
|
|
fi
|
|
done <<< "$branches"
|
|
done
|
|
|
|
endgroup
|
|
log error "$original_commit_sha given in $new_commit_sha not found in any pickable branch."
|
|
|
|
problem=1
|
|
done <<< "$commits"
|
|
|
|
exit $problem
|