diff --git a/cascading-pr-lib.sh b/cascading-pr-lib.sh index 8febf6c..82b634a 100644 --- a/cascading-pr-lib.sh +++ b/cascading-pr-lib.sh @@ -12,6 +12,10 @@ DEBUG=false : ${TMPDIR:=$(mktemp -d)} +: ${LOOPS:=80} + +: ${LOOP_DELAY:=5} + function debug() { DEBUG=true set -x @@ -72,3 +76,77 @@ function host_port() { echo ${host_port%%/} } +function scheme() { + local url="$1" + + echo "${url%%://*}" +} + +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" + local expected_description="$3" + + 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() { + local api="$2" + local sha="$3" + local status="$1" + 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 + get_status $url $repo $sha | jq .statuses + log_info "$sha status NOK" + return 1 + fi +} diff --git a/cascading-pr.sh b/cascading-pr.sh index 0dd00b8..349f541 100755 --- a/cascading-pr.sh +++ b/cascading-pr.sh @@ -48,9 +48,64 @@ function upsert_pr() { log_info "PR created $url" } +function upsert_clone() { + local direction=$1 branch=$2 clone=$3 + + local fetch=true + if ! test -d $TMPDIR/$direction; then + git clone $clone -b $branch $TMPDIR/$direction + fetch=false + fi + ( + cd $TMPDIR/$direction + if $fetch; then + git fetch $direction + fi + git config user.email cascading-pr@example.com + git config user.name cascading-pr + ) +} + +function push() { + local direction=$1 branch=$2 clone=$3 + + ( + cd $TMPDIR/$direction + if git diff; then + log_info "nothing to push" + else + git add . + git commit -m 'cascading-pr update' + git push --force-push origin $branch + git rev-parse HEAD > ../$direction.sha + log_info "pushed" + fi + ) +} + +function wait_destination_ci() { + local sha="$1" + local repo_api=${options[destination_url]}/api/v1/repos/${options[destination_repo]} + wait_success $repo_api $sha +} + +function update() { + upsert_clone origin ${options[origin_head]} ${options[origin_clone]} + upsert_clone destination ${options[destination_head]} ${options[destination_clone]} + ( + cd $TMPDIR/origin + ${options[update]} $TMPDIR/destination + ) + push destination ${options[destination_clone]} +} + function finalize_options() { + options[origin_scheme]=$(scheme ${options[origin_url]}) options[origin_host_port]=$(host_port ${options[origin_url]}) + options[origin_clone]=${options[origin_scheme]}://:${options[origin_token]}@${options[origin_host_port]}/${options[origin_repo]} + options[destination_scheme]=$(scheme ${options[destination_url]}) options[destination_host_port]=$(host_port ${options[destination_url]}) + options[destination_clone]=${options[destination_scheme]}://:${options[destination_token]}@${options[destination_host_port]}/${options[destination_repo]} options[destination_base]=${options[destination_branch]} : ${options[prefix]:=${options[origin_repo]}} options[destination_head]=${options[prefix]}-${options[origin_pr]} @@ -61,12 +116,8 @@ function run() { upsert_branch upsert_pr repo_login ${options[origin_repo]} - - # open a PR on destination - # checkout the head of the PR - # update the PR - # force-push the head - # wait on the status of the tip of the head + update + wait_destination_ci $(cat $TMPDIR/destination.sha) } function main() {