1
0
Fork 0
mirror of https://code.forgejo.org/actions/cascading-pr synced 2025-03-15 06:46:59 +01:00
cascading-pr/cascading-pr-lib.sh

244 lines
4.8 KiB
Bash
Raw Permalink Normal View History

2023-10-11 18:05:11 +02:00
# SPDX-License-Identifier: MIT
2023-10-14 16:01:37 +02:00
set -o pipefail
2023-10-11 18:05:11 +02:00
declare -A options
2023-10-12 19:13:07 +02:00
PREFIX===============
2023-10-11 18:05:11 +02:00
VERBOSE=false
2023-10-12 15:12:52 +02:00
2023-10-11 18:05:11 +02:00
DEBUG=false
2023-10-12 15:12:52 +02:00
2023-10-11 18:05:11 +02:00
: ${EXIT_ON_ERROR:=true}
2023-10-12 15:12:52 +02:00
: ${TMPDIR:=$(mktemp -d)}
# default loop delay is 3600 sec (1 hour)
: ${LOOPS:=100}
: ${LOOP_DELAY:=36}
2023-10-12 21:49:24 +02:00
2023-10-14 16:01:37 +02:00
: ${RETRY_DELAYS:=1 1 5 5 15 30}
2023-10-13 14:24:19 +02:00
function dependencies() {
if ! which jq curl > /dev/null ; then
apt-get update -qq
apt-get -qq install -y jq curl
fi
}
2023-10-14 16:01:37 +02:00
function retry() {
rm -f $TMPDIR/retry.{out,attempt,err}
local success=false
2023-10-14 16:01:37 +02:00
for delay in $RETRY_DELAYS ; do
if "$@" > $TMPDIR/retry.attempt 2>> $TMPDIR/retry.err ; then
2023-10-14 16:01:37 +02:00
success=true
break
fi
cat $TMPDIR/retry.{err,attempt} >> $TMPDIR/retry.out
cat $TMPDIR/retry.{err,attempt} >&2
echo waiting $delay "$@" >&2
2023-10-14 16:01:37 +02:00
sleep $delay
done
if $success ; then
cat $TMPDIR/retry.attempt
2023-10-14 16:01:37 +02:00
return 0
else
echo retry failed for "$@" >&2
cat $TMPDIR/retry.out >&2
2023-10-14 16:01:37 +02:00
return 1
fi
}
2023-10-11 18:05:11 +02:00
function debug() {
DEBUG=true
VERBOSE=true
2023-10-11 18:05:11 +02:00
set -x
PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
}
function verbose() {
VERBOSE=true
}
function log() {
echo "$@" >&2
}
function log_error() {
log "$@"
}
function log_verbose() {
if $VERBOSE ; then
log_info "$@"
2023-10-11 18:05:11 +02:00
fi
}
function log_info() {
2023-10-12 19:13:07 +02:00
echo "$PREFIX $@"
2023-10-11 18:05:11 +02:00
}
function fatal_error() {
log_error "$@"
if $EXIT_ON_ERROR ; then
exit 1
else
return 1
fi
}
2023-10-12 19:13:07 +02:00
function stash_debug() {
echo start $SELF
mkdir -p $TMPDIR
> $TMPDIR/run.out
tail --follow $TMPDIR/run.out | sed --unbuffered -n -e "/^$PREFIX/s/^$PREFIX //p" &
pid=$!
if ! $SELF --debug "$@" >& $TMPDIR/run.out ; then
kill $pid
cat $TMPDIR/run.out
echo fail $SELF
return 1
fi
kill $pid
echo success $SELF
}
2023-10-11 18:05:11 +02:00
function host_port() {
local url="$1"
local host_port="${url##http*://}"
echo ${host_port%%/}
}
2023-10-12 21:49:24 +02:00
function scheme() {
local url="$1"
echo "${url%%://*}"
}
function owner() {
local repo="$1"
echo "${repo%%/*}"
}
function repository() {
local repo="$1"
echo "${repo##*/}"
}
2023-10-12 21:49:24 +02:00
function get_status() {
local api="$1"
local sha="$2"
forgejo-curl.sh api_json $api/commits/$sha/status
}
function check_status() {
local api="$1"
local sha="$2"
local expected_status="$3"
2023-10-12 23:24:11 +02:00
local expected_description="$4"
2023-10-12 21:49:24 +02:00
get_status $api $sha > $TMPDIR/status.json
local status="$(jq --raw-output .state < $TMPDIR/status.json)"
local description="$(jq --raw-output .statuses[0].description < $TMPDIR/status.json)"
if test "$status" = "$expected_status" && test -z "$expected_description" -o "$description" = "$expected_description"; then
echo OK
elif test "$status" = "failure" -o "$status" = "success"; then
echo NOK
else
echo RETRY
fi
}
function wait_success() {
wait_status success "$@"
}
function wait_failure() {
wait_status failure "$@"
}
function wait_running() {
wait_status pending "$@" "Has started running"
}
function wait_log() {
local sha="$1" expected_status="$2" expected_description="$3"
local status="$(jq --raw-output .state < $TMPDIR/status.json)"
local description="$(jq --raw-output .statuses[0].description < $TMPDIR/status.json)"
if test "$expected_description"; then
expected_description=" '$expected_description'"
fi
log_info "$sha status waiting '$expected_status'$expected_description, currently '$status' '$description'"
}
function wait_status() {
2023-10-12 23:24:11 +02:00
local status="$1"
2023-10-12 21:49:24 +02:00
local api="$2"
local sha="$3"
local description="$4"
for i in $(seq $LOOPS); do
if test $(check_status "$api" "$sha" "$status" "$description") != RETRY ; then
break
fi
wait_log "$sha" "$status" "$description"
sleep $LOOP_DELAY
done
if test $(check_status "$api" "$sha" "$status" "$description") = "OK" ; then
log_info "$sha status OK"
else
2023-10-12 23:24:11 +02:00
get_status $api $sha | jq .statuses
2023-10-12 21:49:24 +02:00
log_info "$sha status NOK"
return 1
fi
}
function sanity_check_pr_or_ref() {
local pr="$1" ref="$2"
if test "$pr" -a "$ref" ; then
log_error "--origin-pr $pr and --origin-ref $ref are mutually exclusive"
return 1
fi
if test -z "$pr" -a -z "$ref" ; then
log_error "one of --origin-pr or --origin-ref must be set"
return 2
fi
}
function set_origin_head() {
local pr="${options[origin_pr]}"
local ref="${options[origin_ref]}"
sanity_check_pr_or_ref "$pr" "$ref"
if test "$pr"; then
options[origin_head]=refs/pull/$pr/head
origin_sanity_check
else
options[origin_head]=$ref
fi
}
function origin_has_pr() {
test "${options[origin_pr]}"
}
function set_destination_head() {
local pr="${options[origin_pr]}"
local ref="${options[origin_ref]}"
sanity_check_pr_or_ref "$pr" "$ref"
if $(origin_has_pr); then
options[destination_head]=${options[prefix]}-$pr
else
options[destination_head]=${options[prefix]}-$ref
fi
}