mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2026-10-16 08:25:49 +08:00
118 lines
4.0 KiB
Bash
118 lines
4.0 KiB
Bash
# shellcheck shell=bash
|
|
# CI network operations have bounded retries; build and test commands are not retried.
|
|
ci_retry() {
|
|
local attempt status stdout_file stderr_file
|
|
stdout_file=$(mktemp)
|
|
stderr_file=$(mktemp)
|
|
for attempt in 1 2 3; do
|
|
if "$@" >"$stdout_file" 2>"$stderr_file"; then
|
|
cat "$stdout_file"
|
|
cat "$stderr_file" >&2
|
|
rm -f "$stdout_file" "$stderr_file"
|
|
return 0
|
|
else
|
|
status=$?
|
|
fi
|
|
if [[ "$attempt" == 3 ]] || ! grep -Eiq 'HTTP[^0-9]*(408|429|500|502|503|504)|timed? out|timeout|connection (reset|refused|closed)|temporary failure|TLS handshake|unexpected EOF|could not resolve host|failed to connect|remote end hung up' "$stdout_file" "$stderr_file"; then
|
|
cat "$stdout_file"
|
|
cat "$stderr_file" >&2
|
|
rm -f "$stdout_file" "$stderr_file"
|
|
return "$status"
|
|
fi
|
|
sleep "$((attempt * 2))"
|
|
done
|
|
}
|
|
gh() { ci_retry command gh "$@"; }
|
|
git() {
|
|
if [[ "${1:-}" != clone ]]; then
|
|
command git "$@"
|
|
return
|
|
fi
|
|
local destination temporary status
|
|
local clone_args=("$@")
|
|
destination="${clone_args[${#clone_args[@]}-1]}"
|
|
# Calls without an explicit destination keep git's native behavior.
|
|
if [[ "$destination" == *://* || "$destination" == *.git ]]; then
|
|
ci_retry command git "$@"
|
|
return
|
|
fi
|
|
if [[ -e "$destination" || -L "$destination" ]]; then
|
|
printf 'Clone destination already exists.\n' >&2
|
|
return 1
|
|
fi
|
|
mkdir -p "$(dirname "$destination")"
|
|
temporary=$(mktemp -d "${destination}.ci-XXXXXX")
|
|
clone_args[${#clone_args[@]}-1]="$temporary"
|
|
# A failed clone may leave a partial checkout; clear only our owned temp directory.
|
|
if ci_retry ci_clone_attempt "$temporary" "${clone_args[@]}"; then
|
|
if [[ -e "$destination" || -L "$destination" ]]; then
|
|
rm -rf "$temporary"
|
|
return 1
|
|
fi
|
|
mv "$temporary" "$destination"
|
|
else
|
|
status=$?
|
|
rm -rf "$temporary"
|
|
return "$status"
|
|
fi
|
|
}
|
|
ci_clone_attempt() {
|
|
local temporary="$1"
|
|
shift
|
|
rm -rf "$temporary"
|
|
command git "$@"
|
|
}
|
|
curl() {
|
|
local argument mutating=false status stdout_file stderr_file source_index=-1 backup='' i
|
|
local curl_args=("$@")
|
|
for ((i=0; i<${#curl_args[@]}; i++)); do
|
|
argument="${curl_args[i]}"
|
|
case "$argument" in
|
|
--fail-with-body) curl_args[i]=--fail ;;
|
|
--data*|-d*|--form*|-F*|--upload-file*|-T*) mutating=true ;;
|
|
POST|PATCH|PUT|DELETE|-XPOST|-XPATCH|-XPUT|-XDELETE|--request=POST|--request=PATCH|--request=PUT|--request=DELETE) mutating=true ;;
|
|
https://*) source_index=$i ;;
|
|
esac
|
|
done
|
|
if $mutating; then
|
|
# A timed-out mutation may already have reached the server.
|
|
command curl --fail --connect-timeout 15 --max-time 600 "${curl_args[@]}"
|
|
return
|
|
fi
|
|
if [[ "$source_index" -ge 0 ]]; then
|
|
case "${curl_args[source_index]}" in
|
|
https://cdn.spiritlhl.net/https://*|https://cdn.spiritlhl.top/https://*)
|
|
backup="${curl_args[source_index]#*/https://}"
|
|
backup="https://$backup" ;;
|
|
https://ftp.gnu.org/gnu/*)
|
|
backup="https://ftpmirror.gnu.org/${curl_args[source_index]#https://ftp.gnu.org/gnu/}" ;;
|
|
esac
|
|
fi
|
|
stdout_file=$(mktemp)
|
|
stderr_file=$(mktemp)
|
|
if command curl --fail --connect-timeout 15 --max-time 1200 --retry 3 --retry-max-time 180 --retry-connrefused "${curl_args[@]}" >"$stdout_file" 2>"$stderr_file"; then
|
|
cat "$stdout_file"
|
|
cat "$stderr_file" >&2
|
|
rm -f "$stdout_file" "$stderr_file"
|
|
return 0
|
|
else
|
|
status=$?
|
|
fi
|
|
if [[ -n "$backup" ]]; then
|
|
curl_args[source_index]="$backup"
|
|
if command curl --fail --connect-timeout 15 --max-time 1200 --retry 3 --retry-max-time 180 --retry-connrefused "${curl_args[@]}" >"$stdout_file" 2>"$stderr_file"; then
|
|
cat "$stdout_file"
|
|
cat "$stderr_file" >&2
|
|
rm -f "$stdout_file" "$stderr_file"
|
|
return 0
|
|
else
|
|
status=$?
|
|
fi
|
|
fi
|
|
cat "$stdout_file"
|
|
cat "$stderr_file" >&2
|
|
rm -f "$stdout_file" "$stderr_file"
|
|
return "$status"
|
|
}
|
|
wget() { command wget --tries=3 --timeout=45 --waitretry=2 --retry-connrefused "$@"; }
|