Actions: Shard test suite (#105166)
This commit is contained in:
+79
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
{
|
||||
echo "pkgs-with-tests-named.sh: Find packages with tests in them, filtered by the test names."
|
||||
echo "usage: $0 [-h] [-d <directory>] -b <beginning_with> [-s]"
|
||||
echo
|
||||
echo " -h: Show this help message."
|
||||
echo " -b: Tests beginning with this name will be included."
|
||||
echo " Can only be used once. If not specified, all directories will be included."
|
||||
echo " -d: The directory to find packages with tests in."
|
||||
echo " Can be a path or a /... style pattern."
|
||||
echo " Can be repeated to specify multiple directories."
|
||||
echo " Default: ./..."
|
||||
echo " -s: Split final package list with spaces rather than newlines."
|
||||
} >&2
|
||||
}
|
||||
|
||||
beginningWith=""
|
||||
dirs=()
|
||||
s=0
|
||||
while getopts ":hb:c:d:s" opt; do
|
||||
case $opt in
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
b)
|
||||
beginningWith="$OPTARG"
|
||||
;;
|
||||
d)
|
||||
dirs+=("$OPTARG")
|
||||
;;
|
||||
s)
|
||||
s=1
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ ${#dirs[@]} -eq 0 ]]; then
|
||||
dirs+=("./...")
|
||||
fi
|
||||
if [ -z "$beginningWith" ]; then
|
||||
for pkg in "${dirs[@]}"; do
|
||||
if [ $s -eq 1 ]; then
|
||||
printf "%s " "$pkg"
|
||||
else
|
||||
printf "%s\n" "$pkg"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
readarray -t PACKAGES <<< "$(go list -f '{{.Dir}}' -e "${dirs[@]}")"
|
||||
|
||||
for i in "${!PACKAGES[@]}"; do
|
||||
readarray -t PKG_FILES <<< "$(find "${PACKAGES[$i]}" -type f -name '*_test.go')"
|
||||
if [ ${#PKG_FILES[@]} -eq 0 ] || [ ${#PKG_FILES[@]} -eq 1 ] && [ -z "${PKG_FILES[0]}" ]; then
|
||||
unset "PACKAGES[$i]"
|
||||
continue
|
||||
fi
|
||||
if ! grep -q "^func $beginningWith" "${PKG_FILES[@]}"; then
|
||||
unset "PACKAGES[$i]"
|
||||
fi
|
||||
done
|
||||
|
||||
for pkg in "${PACKAGES[@]}"; do
|
||||
if [ $s -eq 1 ]; then
|
||||
printf "%s " "$pkg"
|
||||
else
|
||||
printf "%s\n" "$pkg"
|
||||
fi
|
||||
done
|
||||
Executable
+149
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
{
|
||||
echo "shard.sh: Shard tests for parallel execution in CI."
|
||||
echo "usage: $0 [-h] -n <shard> -m <total_shards> [-d <directory>] [-s]"
|
||||
echo
|
||||
echo " -h: Show this help message."
|
||||
echo " -n: The shard number (1-indexed)."
|
||||
echo " -m: The total number of shards. Must be equal to or greater than -n."
|
||||
echo " -N: The shard in shard notation (n/m), corresponding to -n and -m."
|
||||
echo " -d: The directory to find packages with tests in."
|
||||
echo " Can be a path or a /... style pattern."
|
||||
echo " Can be repeated to specify multiple directories."
|
||||
echo " Can be - to read from stdin."
|
||||
echo " Default: ./..."
|
||||
echo " -s: Split final package list with spaces rather than newlines."
|
||||
} >&2
|
||||
}
|
||||
|
||||
is_int() {
|
||||
# we can't just return the result of the regex match shellcheck is unhappy...
|
||||
if [[ "$1" =~ ^[0-9]+$ ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
n=0
|
||||
m=0
|
||||
dirs=()
|
||||
s=0
|
||||
while getopts ":hn:m:d:sN:" opt; do
|
||||
case $opt in
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
n)
|
||||
if ! is_int "$OPTARG"; then
|
||||
echo "Error: -n must be an integer." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
n=$OPTARG
|
||||
;;
|
||||
m)
|
||||
if ! is_int "$OPTARG"; then
|
||||
echo "Error: -m must be an integer." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
m=$OPTARG
|
||||
;;
|
||||
N)
|
||||
if [[ "$OPTARG" =~ ^([0-9]+)/([0-9]+)$ ]]; then
|
||||
n="${BASH_REMATCH[1]}"
|
||||
m="${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "Error: -N must be in the form n/m." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
d)
|
||||
dirs+=("$OPTARG")
|
||||
;;
|
||||
s)
|
||||
s=1
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
:)
|
||||
echo "Option -$OPTARG requires an argument." >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ $n -eq 0 || $m -eq 0 ]]; then
|
||||
echo "Error: -n and -m are required." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ $n -lt 1 || $m -lt 1 ]]; then
|
||||
echo "Error: -n and -m must be greater than 0." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ $n -gt $m ]]; then
|
||||
echo "Error: -n must be less than or equal to -m." >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ ${#dirs[@]} -eq 0 ]]; then
|
||||
dirs+=("./...")
|
||||
fi
|
||||
# If dirs is just ("-"), read from stdin instead.
|
||||
if [[ ${#dirs[@]} -eq 1 && "${dirs[0]}" == "-" ]]; then
|
||||
dirs=()
|
||||
while IFS= read -r line; do
|
||||
dirs+=("$line")
|
||||
done
|
||||
fi
|
||||
if [[ $n -eq 1 && $m -eq 1 ]]; then
|
||||
# If there is only one shard, just return all packages.
|
||||
for pkg in "${dirs[@]}"; do
|
||||
if [ $s -eq 1 ]; then
|
||||
printf "%s " "$pkg"
|
||||
else
|
||||
printf "%s\n" "$pkg"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
readarray -t PACKAGES <<< "$(go list -f '{{.Dir}}' -e "${dirs[@]}")"
|
||||
if [[ ${#PACKAGES[@]} -eq 0 ]]; then
|
||||
echo "No packages found in directories: ${dirs[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in "${!PACKAGES[@]}"; do
|
||||
if [ -z "$(find "${PACKAGES[i]}" -maxdepth 1 -type f -name '*_test.go' -printf '.' -quit)" ]; then
|
||||
# There are no test files in this package.
|
||||
unset 'PACKAGES[i]'
|
||||
fi
|
||||
done
|
||||
|
||||
for i in "${!PACKAGES[@]}"; do
|
||||
if (( (i % m) + 1 != n )); then
|
||||
unset 'PACKAGES[i]'
|
||||
fi
|
||||
done
|
||||
|
||||
for pkg in "${PACKAGES[@]}"; do
|
||||
if [ $s -eq 1 ]; then
|
||||
printf "%s " "$pkg"
|
||||
else
|
||||
printf "%s\n" "$pkg"
|
||||
fi
|
||||
done
|
||||
Reference in New Issue
Block a user