diff --git a/.github/scripts/retry-backports.sh b/.github/scripts/retry-backports.sh index 723955972a35a8..5eaca535f0b508 100755 --- a/.github/scripts/retry-backports.sh +++ b/.github/scripts/retry-backports.sh @@ -12,6 +12,8 @@ # read, and GITHUB_REPOSITORY. # # Usage: retry-backports.sh [--stale] +# +# Nothing to retry is the usual case and exits 0. set -euo pipefail @@ -29,7 +31,7 @@ R=$GITHUB_REPOSITORY -q ".[] | select(.headRefName | startswith(\"$PREFIX\")) | select(.mergeable == \"CONFLICTING\") | .headRefName" | sed "s|^$PREFIX||" fi -} | grep -xE '[0-9]+' | sort -un | while read -r n; do +} | { grep -xE '[0-9]+' || true; } | sort -un | while read -r n; do echo "Dispatching the backport of #$n" gh workflow run kernel-nightly.yml --repo "$R" --ref "$TARGET" -f backport_pr="$n" done diff --git a/.github/scripts/tests/retry-backports.test.sh b/.github/scripts/tests/retry-backports.test.sh new file mode 100755 index 00000000000000..5f900c5c1672b6 --- /dev/null +++ b/.github/scripts/tests/retry-backports.test.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Tests for .github/scripts/retry-backports.sh against a fake gh. +# +# The fake answers the two pull request listings from WAITING and STALE and +# records every dispatch, so each case checks exactly which backports the +# script started, and that having nothing to retry is a success. +# +# Run from anywhere: bash .github/scripts/tests/retry-backports.test.sh +set -uo pipefail + +HERE=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +RETRY="$HERE/../retry-backports.sh" + +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT +mkdir "$WORK/bin" +cat >"$WORK/bin/gh" <<'GH' +#!/usr/bin/env bash +case "$1 $2" in +"pr list") + case " $* " in + *" --label backport-waiting "*) [ -z "$WAITING" ] || printf '%s\n' $WAITING ;; + *) [ -z "$STALE" ] || printf '%s\n' $STALE ;; + esac ;; +"workflow run") echo "$*" >>"$DISPATCHED" ;; +*) echo "unexpected: gh $*" >&2; exit 2 ;; +esac +GH +chmod +x "$WORK/bin/gh" +export PATH="$WORK/bin:$PATH" GITHUB_REPOSITORY=edera-dev/linux DISPATCHED="$WORK/dispatched" + +failures=0 +ok() { echo "ok $1"; } +bad() { + echo "FAIL $1" >&2 + [ -z "${2:-}" ] || printf ' %s\n' "${2//$'\n'/$'\n' }" >&2 + failures=$((failures + 1)) +} + +# check +check() { + local name=$1 args=$2 out got + : >"$DISPATCHED" + # shellcheck disable=SC2086 # $args is zero or one word + if ! out=$(WAITING=$3 STALE=$4 bash "$RETRY" $args 2>&1); then + bad "$name" "exited non-zero: $out" + return + fi + got=$(sed -E 's/.*backport_pr=([0-9]+).*/\1/' "$DISPATCHED" | xargs) + if [ "$got" = "$5" ]; then ok "$name"; else bad "$name" "dispatched '$got', expected '$5'"; fi +} + +check "nothing waiting, no --stale" "" "" "" "" +check "nothing waiting, nothing stale" --stale "" "" "" +check "waiting pull requests are dispatched" "" "7 12" "" "7 12" +check "stale backports are dispatched by number" --stale "" \ + "backport/edera-6.18-lts/pr-23 backport/edera-6.18-lts/pr-9" "9 23" +check "stale backports are ignored without --stale" "" "" "backport/edera-6.18-lts/pr-23" "" +check "a pull request both waiting and stale goes once" --stale "23" \ + "backport/edera-6.18-lts/pr-23" "23" + +if [ "$failures" -ne 0 ]; then + echo "$failures failure(s)" >&2 + exit 1 +fi +echo "all passed" diff --git a/.github/workflows/automation-selftest.yml b/.github/workflows/automation-selftest.yml index fff5f1f7ac104d..0f5b41444b775e 100644 --- a/.github/workflows/automation-selftest.yml +++ b/.github/workflows/automation-selftest.yml @@ -64,5 +64,8 @@ jobs: - name: Backport tests run: bash .github/scripts/tests/backport.test.sh + - name: Backport retry tests + run: bash .github/scripts/tests/retry-backports.test.sh + - name: Shellcheck run: shellcheck .github/scripts/*.sh .github/scripts/tests/*.sh