1
0
Fork 0
mirror of https://code.forgejo.org/actions/cascading-pr synced 2025-03-14 22:36:58 +01:00

close cascading PR if the origin PR is closed

This commit is contained in:
Earl Warren 2023-10-13 19:10:50 +02:00
parent dd3807fb41
commit 657e223acc
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
3 changed files with 113 additions and 27 deletions

View file

@ -24,34 +24,88 @@ function repo_curl() {
DOT=$TMPDIR/$repo forgejo-curl.sh "$@"
}
function exists_branch() {
repo_curl ${options[destination_repo]} api_json ${options[destination_api]}/branches/${options[destination_head]} >& /dev/null
}
function delete_branch() {
if ! $(exists_branch) ; then
log_info "branch ${options[destination_head]} does not exists"
return
fi
repo_curl ${options[destination_repo]} api_json -X DELETE ${options[destination_api]}/branches/${options[destination_head]}
log_info "branch ${options[destination_head]} deleted"
}
function upsert_branch() {
local repo_api=${options[destination_url]}/api/v1/repos/${options[destination_repo]}
if repo_curl ${options[destination_repo]} api_json $repo_api/branches/${options[destination_head]} >& /dev/null ; then
if $(exists_branch) ; then
log_info "branch ${options[destination_head]} already exists"
return
fi
repo_curl ${options[destination_repo]} api_json --data-raw '{"new_branch_name":"'${options[destination_head]}'","old_branch_name":"'${options[destination_base]}'"}' $repo_api/branches
repo_curl ${options[destination_repo]} api_json --data-raw '{"new_branch_name":"'${options[destination_head]}'","old_branch_name":"'${options[destination_base]}'"}' ${options[destination_api]}/branches
log_info "branch ${options[destination_head]} created"
}
function upsert_pr() {
local repo_api=${options[destination_url]}/api/v1/repos/${options[destination_repo]}
local title="cascading-pr from ${options[origin_url]}/${options[origin_repo]}/pulls/${options[origin_pr]}"
repo_curl ${options[destination_repo]} api --get --data state=open --data type=pulls --data-urlencode q="$title" $repo_api/issues | jq --raw-output .[0] > $TMPDIR/destination-pr.json
url=$(jq --raw-output .url < $TMPDIR/destination-pr.json)
if test "$url" != "null"; then
log_info "PR already exists $url"
return
fi
repo_curl ${options[destination_repo]} api_json --data-raw '{"title":"'"$title"'","base":"'${options[destination_base]}'","head":"'${options[destination_head]}'"}' $repo_api/pulls > $TMPDIR/destination-pr.json
url=$(jq --raw-output .url < $TMPDIR/destination-pr.json)
log_info "PR created $url"
function pr_destination_title() {
echo "cascading-pr from ${options[origin_url]}/${options[origin_repo]}/pulls/${options[origin_pr]}"
}
function origin_pr_head() {
local repo_api=${options[origin_url]}/api/v1/repos/${options[origin_repo]}
repo_curl ${options[origin_repo]} api_json $repo_api/pulls/${options[origin_pr]} > $TMPDIR/origin-pr.json
jq --raw-output .head.ref < $TMPDIR/origin-pr.json
function upsert_pr() {
url=$(pr_url destination)
state=$(pr_state destination)
if test "$url" != "null" -a "$state" = "open"; then
log_info "an open PR already exists $url"
return
fi
local title=$(pr_destination_title)
repo_curl ${options[destination_repo]} api_json --data-raw '{"title":"'"$title"'","base":"'${options[destination_base]}'","head":"'${options[destination_head]}'"}' ${options[destination_api]}/pulls > $TMPDIR/destination-pr.json
log_info "PR created $(pr_url destination)"
}
function close_pr() {
local direction=$1
if test "$(pr_state ${direction})" = "open"; then
log_info "closing $(pr_url ${direction})"
local number=$(pr_number $direction)
repo_curl ${options[${direction}_repo]} api_json -X PATCH --data-raw '{"state":"closed"}' ${options[${direction}_api]}/issues/$number
delete_branch $(pr_head ${direction})
else
log_info "no open PR found"
fi
}
function pr_get_origin() {
repo_curl ${options[origin_repo]} api_json ${options[origin_api]}/pulls/${options[origin_pr]} > $TMPDIR/origin-pr.json
}
function pr_get_destination() {
local title=$(pr_destination_title)
repo_curl ${options[destination_repo]} api --get --data state=open --data type=pulls --data-urlencode q="$title" ${options[destination_api]}/issues | jq --raw-output .[0] > $TMPDIR/destination-pr.json
}
function pr() {
local direction=$1
if ! test -f $TMPDIR/${direction}-pr.json; then
pr_get_$direction
fi
cat $TMPDIR/${direction}-pr.json
}
function pr_state() {
pr $1 | jq --raw-output .state
}
function pr_url() {
pr $1 | jq --raw-output .url
}
function pr_number() {
pr $1 | jq --raw-output .number
}
function pr_head() {
pr $1 | jq --raw-output .head.ref
}
function upsert_clone() {
@ -106,10 +160,12 @@ function update() {
}
function finalize_options() {
options[origin_api]=${options[origin_url]}/api/v1/repos/${options[origin_repo]}
options[origin_scheme]=$(scheme ${options[origin_url]})
options[origin_host_port]=$(host_port ${options[origin_url]})
options[origin_clone]=${options[origin_scheme]}://any:${options[origin_token]}@${options[origin_host_port]}/${options[origin_repo]}
options[origin_head]=$(origin_pr_head)
options[origin_head]=$(pr_head origin)
options[destination_api]=${options[destination_url]}/api/v1/repos/${options[destination_repo]}
options[destination_scheme]=$(scheme ${options[destination_url]})
options[destination_host_port]=$(host_port ${options[destination_url]})
options[destination_clone]=${options[destination_scheme]}://any:${options[destination_token]}@${options[destination_host_port]}/${options[destination_repo]}
@ -119,12 +175,27 @@ function finalize_options() {
}
function run() {
repo_login ${options[destination_repo]}
upsert_branch
upsert_pr
repo_login ${options[origin_repo]}
update
wait_destination_ci $(cat $TMPDIR/destination.sha)
local state=$(pr_state origin)
case "$state" in
open)
log_info "PR is open, update or create the cascade branch and PR"
repo_login ${options[destination_repo]}
upsert_branch
upsert_pr
repo_login ${options[origin_repo]}
update
wait_destination_ci $(cat $TMPDIR/destination.sha)
;;
closed)
log_info "PR is closed, close the cascade PR and remove the branch"
repo_login ${options[destination_repo]}
close_pr destination
;;
*)
log_info "state '$state', do nothing"
;;
esac
}
function main() {

View file

@ -1,6 +1,11 @@
# SPDX-License-Identifier: MIT
name: test
on: [pull_request]
on:
pull_request:
types:
- opened
- synchronize
- closed
jobs:
test:
runs-on: docker

View file

@ -45,6 +45,12 @@ function user_create() {
user_login $username
}
function close_pull_request() {
forgejo-curl.sh api_json ${options[url]}/api/v1/repos/user1/originrepo/pulls | jq --raw-output '.[] | .number' | while read pr ; do
forgejo-curl.sh api_json -X PATCH --data-raw '{"state":"closed"}' ${options[url]}/api/v1/repos/user1/originrepo/issues/$pr
done
}
function create_pull_request() {
forgejo-curl.sh api_json ${options[url]}/api/v1/repos/user1/originrepo/pulls | jq --raw-output '.[] | .number' | while read pr ; do
forgejo-curl.sh api_json -X DELETE ${options[url]}/api/v1/repos/user1/originrepo/issues/$pr
@ -93,6 +99,10 @@ function run() {
create_pull_request
wait_success ${options[url]}/api/v1/repos/user1/originrepo $(cat $TMPDIR/originrepo.sha)
close_pull_request
wait_success ${options[url]}/api/v1/repos/user1/originrepo $(cat $TMPDIR/originrepo.sha)
}
function main() {