mirror of
https://code.forgejo.org/actions/cascading-pr
synced 2025-03-15 06:46:59 +01:00
allow running on a ref instead of a PR
When running from a PR, the ref is the head of the PR in the origin repository. The PR is used to: * display comments about the location of the destination PR * asynchronously close / merge the destination PR when something happens in the origin PR When only the ref is available, the destination PR must be closed and the corresponding branch destroyed immediately after it concludes because there is no convenient way to know what or when something else will happen.
This commit is contained in:
parent
0e9a4e846b
commit
0c3c8b591b
12 changed files with 326 additions and 85 deletions
83
README.md
83
README.md
|
@ -4,58 +4,69 @@ Create and synchronize a PR in a dependent repository
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
|
||||||
If repository A depends on repository B, `cascadinging-pr` can be
|
If repository A depends on repository B, `cascadinging-pr` can be used
|
||||||
used by a workflow in repository B to trigger the CI on repository A
|
by a workflow in repository B to trigger the CI on repository A and
|
||||||
and verify it passes when it will upgrade with the proposed change
|
verify it passes when using a modified version of repository B. This
|
||||||
from repository B.
|
modified version could be a pull request, a branch or a reference.
|
||||||
|
|
||||||
|
In the simplest case `cascading-pr` runs a workflow in `destination-repo`
|
||||||
|
that uses `origin-ref` and blocks until it completes.
|
||||||
|
|
||||||
|
As an example, when a tag is set in Forgejo and builds a new release,
|
||||||
|
it is concluded by a call to `cascading-pr` that runs
|
||||||
|
[end-to-end](https://code.forgejo.org/forgejo/end-to-end/) tests on
|
||||||
|
the newly built release to verify it works as expected.
|
||||||
|
|
||||||
When used in a workflow triggered by a PR event in `origin-repo`,
|
When used in a workflow triggered by a PR event in `origin-repo`,
|
||||||
`cascading-pr` will create, update and close a matching PR in
|
`cascading-pr` will create, update and close a matching PR in the
|
||||||
another repository (`destination-repo`). When the PR is updated,
|
`destination-repo`. When the PR is updated, `cascading-pr` will
|
||||||
`cascading-pr` subsequently will update the matching PR. The
|
update the matching PR. It waits for the workflow triggered by these
|
||||||
worfklows in `origin-repo` will wait for the workflow in
|
updates in `destination-repo` to complete. If fails, `cascading-pr`,
|
||||||
`destination-repo` to complete. If the workflow in
|
also fails.
|
||||||
`destination-repo` fails, the workflow in `origin-repo` will also
|
|
||||||
fail.
|
|
||||||
|
|
||||||
As an example, when a PR is created in
|
As an example, when a PR is created in
|
||||||
[`forgejo/runner`](https://code.forgejo.org/forgejo/runner/), a
|
[`forgejo/runner`](https://code.forgejo.org/forgejo/runner/), a
|
||||||
matching PR is created in
|
matching PR is created in
|
||||||
[`actions/setup-forgejo`](https://code.forgejo.org/actions/setup-forgejo/)
|
[`actions/setup-forgejo`](https://code.forgejo.org/actions/setup-forgejo/)
|
||||||
with the proposed change. `cascading-pr` will wait until the CI in
|
with the proposed change and `cascading-pr` waits until the CI in
|
||||||
`actions/setup-forgejo` is successful.
|
`actions/setup-forgejo` is successful.
|
||||||
|
|
||||||
The `update` script is expected to be found in the origin repository
|
The `update` script is expected to be found in `origin-repo` and is
|
||||||
running the PR. It is given four arguments:
|
given the following arguments:
|
||||||
|
|
||||||
* A directory in which the destination repository (or a fork) is checked-out
|
* A directory path in which the `destination-branch` of `destination-repo`
|
||||||
on the base branch
|
(or a fork) is checked-out.
|
||||||
* A file with the JSON describing the pull request in the
|
* The path to a JSON file describing the pull request in `destination-repo`.
|
||||||
destination repository
|
* A directory path in which the head of `origin-repo` is checked-out at:
|
||||||
* A directory in which the origin repository is checked-out
|
* if `origin-pr` is specified, the head branch of `origin-pr`
|
||||||
on the head branch
|
* otherwise `origin-ref`
|
||||||
* A file with the JSON describing the pull request in the
|
* Information about the `origin-repo`
|
||||||
origin repository
|
* if `origin-pr` is specified, the path to a JSON file desccribing
|
||||||
|
the pull request in `origin-repo`
|
||||||
|
* otherwise `origin-ref`
|
||||||
|
|
||||||
If changes are found in the destination repository directory after the `update` script runs,
|
If changes are found in the destination repository directory after
|
||||||
they will be pushed as a new commit in the PR.
|
the `update` script runs, they will be pushed as a new commit in the
|
||||||
|
PR in the `destination-repo`.
|
||||||
|
|
||||||
`origin-token` is used when accessing `origin-repo` and needs the
|
`origin-token` is used when accessing `origin-repo` and needs the
|
||||||
`read:user`, `read:repository` and `write:issue` scopes.
|
`read:user`, `read:repository` and `write:issue` scopes.
|
||||||
|
|
||||||
`destination-token` is used to push the branch that contains an
|
`destination-token` is used to push the branch that contains an
|
||||||
update to `destination-repo` and to open a pull request. It needs
|
update to `destination-repo` (or `destination-fork-repo`) and open a
|
||||||
the `read:user`, `write:repository` and `write:issue` scopes.
|
pull request. It needs the `read:user`, `write:repository` and
|
||||||
|
`write:issue` scopes.
|
||||||
|
|
||||||
It is recommended that a dedicated user is used to create
|
It is recommended that a dedicated user is used to create
|
||||||
`destination-token` and that `destination-fork-repo` is always used
|
`destination-token` and that `destination-fork-repo` is always used
|
||||||
unless the users who are able to create pull requests are trusted.
|
unless the users who are able to create pull requests are trusted.
|
||||||
|
|
||||||
When the PR is from a forked repository, the `update` script is run
|
When the PR in the `destination-repo` is from a forked repository,
|
||||||
from the default branch of the base repository instead of the head
|
the `update` script is run from the default branch of
|
||||||
branch of the fork. The pull request author must not be trusted
|
`destination-repo` instead of the head of the PR which is a branch
|
||||||
and it is imperative that the `update` script never runs anything
|
in destination-fork-repo. The PR author must not be trusted and it
|
||||||
found in the head branch of the pull request.
|
is imperative that the `update` script never runs anything found in
|
||||||
|
the head branch of the PR.
|
||||||
|
|
||||||
If the fork of the destination repository is specified and it does
|
If the fork of the destination repository is specified and it does
|
||||||
not exist, it is created.
|
not exist, it is created.
|
||||||
|
@ -68,7 +79,8 @@ not exist, it is created.
|
||||||
| origin-url | URL of the Forgejo instance where the PR that triggers the action is located (e.g. https://code.forgejo.org) | `true` | |
|
| origin-url | URL of the Forgejo instance where the PR that triggers the action is located (e.g. https://code.forgejo.org) | `true` | |
|
||||||
| origin-repo | the repository in which the PR was created | `true` | |
|
| origin-repo | the repository in which the PR was created | `true` | |
|
||||||
| origin-token | a token with write permission on origin-repo | `true` | |
|
| origin-token | a token with write permission on origin-repo | `true` | |
|
||||||
| origin-pr | number of the PR in {orign-repo} | `true` | |
|
| origin-pr | number of the PR in {orign-repo}, mutually exclusive with {origin-ref} | `false` | |
|
||||||
|
| origin-ref | reference in {orign-repo}, mutually exclusive with {origin-pr} | `false` | |
|
||||||
| destination-url | URL of the Forgejo instance where the cascading PR is created or updated (e.g. https://code.forgejo.org) | `true` | |
|
| destination-url | URL of the Forgejo instance where the cascading PR is created or updated (e.g. https://code.forgejo.org) | `true` | |
|
||||||
| destination-repo | the repository in which the cascading PR is created or updated | `true` | |
|
| destination-repo | the repository in which the cascading PR is created or updated | `true` | |
|
||||||
| destination-fork-repo | the fork of {destination-repo} in which the {destination-branch} will be created or updated | `false` | |
|
| destination-fork-repo | the fork of {destination-repo} in which the {destination-branch} will be created or updated | `false` | |
|
||||||
|
@ -168,12 +180,13 @@ git clone https://code.forgejo.org/actions/setup-forgejo
|
||||||
export PATH=$(pwd)/setup-forgejo:$PATH
|
export PATH=$(pwd)/setup-forgejo:$PATH
|
||||||
git clone https://code.forgejo.org/actions/cascading-pr
|
git clone https://code.forgejo.org/actions/cascading-pr
|
||||||
cd cascading-pr
|
cd cascading-pr
|
||||||
|
export DIR=/tmp/forgejo-for-cascading-pr
|
||||||
forgejo-curl.sh logout
|
forgejo-curl.sh logout
|
||||||
forgejo-runner.sh teardown
|
forgejo-runner.sh teardown
|
||||||
forgejo.sh teardown
|
forgejo-binary.sh teardown
|
||||||
forgejo.sh setup root admin1234 codeberg.org/forgejo/forgejo 1.21
|
forgejo-binary.sh setup root admin1234 https://codeberg.org/forgejo/forgejo/releases/download/v1.21.3-0/forgejo-1.21.3-0-linux-amd64
|
||||||
FORGEJO_RUNNER_CONFIG=$(pwd)/tests/runner-config.yaml forgejo-runner.sh setup
|
FORGEJO_RUNNER_CONFIG=$(pwd)/tests/runner-config.yaml forgejo-runner.sh setup
|
||||||
url=http://$(cat forgejo-ip):3000
|
url=$(cat $DIR/forgejo-url)
|
||||||
firefox $url
|
firefox $url
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
79
action.yml
79
action.yml
|
@ -3,58 +3,69 @@ name: 'Cascading PR'
|
||||||
author: 'Forgejo authors'
|
author: 'Forgejo authors'
|
||||||
description: |
|
description: |
|
||||||
|
|
||||||
If repository A depends on repository B, `cascadinging-pr` can be
|
If repository A depends on repository B, `cascadinging-pr` can be used
|
||||||
used by a workflow in repository B to trigger the CI on repository A
|
by a workflow in repository B to trigger the CI on repository A and
|
||||||
and verify it passes when it will upgrade with the proposed change
|
verify it passes when using a modified version of repository B. This
|
||||||
from repository B.
|
modified version could be a pull request, a branch or a reference.
|
||||||
|
|
||||||
|
In the simplest case `cascading-pr` runs a workflow in `destination-repo`
|
||||||
|
that uses `origin-ref` and blocks until it completes.
|
||||||
|
|
||||||
|
As an example, when a tag is set in Forgejo and builds a new release,
|
||||||
|
it is concluded by a call to `cascading-pr` that runs
|
||||||
|
[end-to-end](https://code.forgejo.org/forgejo/end-to-end/) tests on
|
||||||
|
the newly built release to verify it works as expected.
|
||||||
|
|
||||||
When used in a workflow triggered by a PR event in `origin-repo`,
|
When used in a workflow triggered by a PR event in `origin-repo`,
|
||||||
`cascading-pr` will create, update and close a matching PR in
|
`cascading-pr` will create, update and close a matching PR in the
|
||||||
another repository (`destination-repo`). When the PR is updated,
|
`destination-repo`. When the PR is updated, `cascading-pr` will
|
||||||
`cascading-pr` subsequently will update the matching PR. The
|
update the matching PR. It waits for the workflow triggered by these
|
||||||
worfklows in `origin-repo` will wait for the workflow in
|
updates in `destination-repo` to complete. If fails, `cascading-pr`,
|
||||||
`destination-repo` to complete. If the workflow in
|
also fails.
|
||||||
`destination-repo` fails, the workflow in `origin-repo` will also
|
|
||||||
fail.
|
|
||||||
|
|
||||||
As an example, when a PR is created in
|
As an example, when a PR is created in
|
||||||
[`forgejo/runner`](https://code.forgejo.org/forgejo/runner/), a
|
[`forgejo/runner`](https://code.forgejo.org/forgejo/runner/), a
|
||||||
matching PR is created in
|
matching PR is created in
|
||||||
[`actions/setup-forgejo`](https://code.forgejo.org/actions/setup-forgejo/)
|
[`actions/setup-forgejo`](https://code.forgejo.org/actions/setup-forgejo/)
|
||||||
with the proposed change. `cascading-pr` will wait until the CI in
|
with the proposed change and `cascading-pr` waits until the CI in
|
||||||
`actions/setup-forgejo` is successful.
|
`actions/setup-forgejo` is successful.
|
||||||
|
|
||||||
The `update` script is expected to be found in the origin repository
|
The `update` script is expected to be found in `origin-repo` and is
|
||||||
running the PR. It is given four arguments:
|
given the following arguments:
|
||||||
|
|
||||||
* A directory in which the destination repository (or a fork) is checked-out
|
* A directory path in which the `destination-branch` of `destination-repo`
|
||||||
on the base branch
|
(or a fork) is checked-out.
|
||||||
* A file with the JSON describing the pull request in the
|
* The path to a JSON file describing the pull request in `destination-repo`.
|
||||||
destination repository
|
* A directory path in which the head of `origin-repo` is checked-out at:
|
||||||
* A directory in which the origin repository is checked-out
|
* if `origin-pr` is specified, the head branch of `origin-pr`
|
||||||
on the head branch
|
* otherwise `origin-ref`
|
||||||
* A file with the JSON describing the pull request in the
|
* Information about the `origin-repo`
|
||||||
origin repository
|
* if `origin-pr` is specified, the path to a JSON file desccribing
|
||||||
|
the pull request in `origin-repo`
|
||||||
|
* otherwise `origin-ref`
|
||||||
|
|
||||||
If changes are found in the destination repository directory after the `update` script runs,
|
If changes are found in the destination repository directory after
|
||||||
they will be pushed as a new commit in the PR.
|
the `update` script runs, they will be pushed as a new commit in the
|
||||||
|
PR in the `destination-repo`.
|
||||||
|
|
||||||
`origin-token` is used when accessing `origin-repo` and needs the
|
`origin-token` is used when accessing `origin-repo` and needs the
|
||||||
`read:user`, `read:repository` and `write:issue` scopes.
|
`read:user`, `read:repository` and `write:issue` scopes.
|
||||||
|
|
||||||
`destination-token` is used to push the branch that contains an
|
`destination-token` is used to push the branch that contains an
|
||||||
update to `destination-repo` and to open a pull request. It needs
|
update to `destination-repo` (or `destination-fork-repo`) and open a
|
||||||
the `read:user`, `write:repository` and `write:issue` scopes.
|
pull request. It needs the `read:user`, `write:repository` and
|
||||||
|
`write:issue` scopes.
|
||||||
|
|
||||||
It is recommended that a dedicated user is used to create
|
It is recommended that a dedicated user is used to create
|
||||||
`destination-token` and that `destination-fork-repo` is always used
|
`destination-token` and that `destination-fork-repo` is always used
|
||||||
unless the users who are able to create pull requests are trusted.
|
unless the users who are able to create pull requests are trusted.
|
||||||
|
|
||||||
When the PR is from a forked repository, the `update` script is run
|
When the PR in the `destination-repo` is from a forked repository,
|
||||||
from the default branch of the base repository instead of the head
|
the `update` script is run from the default branch of
|
||||||
branch of the fork. The pull request author must not be trusted
|
`destination-repo` instead of the head of the PR which is a branch
|
||||||
and it is imperative that the `update` script never runs anything
|
in destination-fork-repo. The PR author must not be trusted and it
|
||||||
found in the head branch of the pull request.
|
is imperative that the `update` script never runs anything found in
|
||||||
|
the head branch of the PR.
|
||||||
|
|
||||||
If the fork of the destination repository is specified and it does
|
If the fork of the destination repository is specified and it does
|
||||||
not exist, it is created.
|
not exist, it is created.
|
||||||
|
@ -70,8 +81,9 @@ inputs:
|
||||||
description: 'a token with write permission on origin-repo'
|
description: 'a token with write permission on origin-repo'
|
||||||
required: true
|
required: true
|
||||||
origin-pr:
|
origin-pr:
|
||||||
description: 'number of the PR in {orign-repo}'
|
description: 'number of the PR in {orign-repo}, mutually exclusive with {origin-ref}'
|
||||||
required: true
|
origin-ref:
|
||||||
|
description: 'reference in {orign-repo}, mutually exclusive with {origin-pr}'
|
||||||
destination-url:
|
destination-url:
|
||||||
description: 'URL of the Forgejo instance where the cascading PR is created or updated (e.g. https://code.forgejo.org)'
|
description: 'URL of the Forgejo instance where the cascading PR is created or updated (e.g. https://code.forgejo.org)'
|
||||||
required: true
|
required: true
|
||||||
|
@ -125,6 +137,7 @@ runs:
|
||||||
--origin-repo "${{ inputs.origin-repo }}" \
|
--origin-repo "${{ inputs.origin-repo }}" \
|
||||||
--origin-token "@$origin_token" \
|
--origin-token "@$origin_token" \
|
||||||
--origin-pr "${{ inputs.origin-pr }}" \
|
--origin-pr "${{ inputs.origin-pr }}" \
|
||||||
|
--origin-ref "${{ inputs.origin-ref }}" \
|
||||||
--destination-url "${{ inputs.destination-url }}" \
|
--destination-url "${{ inputs.destination-url }}" \
|
||||||
--destination-repo "${{ inputs.destination-repo }}" \
|
--destination-repo "${{ inputs.destination-repo }}" \
|
||||||
--destination-fork-repo "${{ inputs.destination-fork-repo }}" \
|
--destination-fork-repo "${{ inputs.destination-fork-repo }}" \
|
||||||
|
|
|
@ -197,3 +197,47 @@ function wait_status() {
|
||||||
return 1
|
return 1
|
||||||
fi
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ function git_checkout() {
|
||||||
(
|
(
|
||||||
cd $TMPDIR/$direction
|
cd $TMPDIR/$direction
|
||||||
if [[ "$ref" =~ ^refs/ ]] ; then
|
if [[ "$ref" =~ ^refs/ ]] ; then
|
||||||
git fetch ${remote} +$ref:$ref
|
git fetch --update-head-ok ${remote} +$ref:$ref
|
||||||
else
|
else
|
||||||
ref=${remote}/$ref
|
ref=${remote}/$ref
|
||||||
fi
|
fi
|
||||||
|
@ -305,7 +305,7 @@ function update() {
|
||||||
local update=${options[update]}
|
local update=${options[update]}
|
||||||
if ! [[ "$update" =~ ^/ ]] ; then
|
if ! [[ "$update" =~ ^/ ]] ; then
|
||||||
local d
|
local d
|
||||||
if $(pr_from_fork origin); then
|
if $(origin_has_pr) && $(pr_from_fork origin); then
|
||||||
local default_branch=$(default_branch origin)
|
local default_branch=$(default_branch origin)
|
||||||
log_info "PR is from a forked repository, using the default branch $default_branch to obtain the update script"
|
log_info "PR is from a forked repository, using the default branch $default_branch to obtain the update script"
|
||||||
d=$TMPDIR/update
|
d=$TMPDIR/update
|
||||||
|
@ -316,7 +316,13 @@ function update() {
|
||||||
update=$d/$update
|
update=$d/$update
|
||||||
fi
|
fi
|
||||||
cd $TMPDIR
|
cd $TMPDIR
|
||||||
$update $TMPDIR/destination $TMPDIR/destination-pr.json $TMPDIR/origin $TMPDIR/origin-pr.json
|
local origin_info
|
||||||
|
if $(origin_has_pr); then
|
||||||
|
origin_info=$TMPDIR/origin-pr.json
|
||||||
|
else
|
||||||
|
origin_info="${options[origin_ref]}"
|
||||||
|
fi
|
||||||
|
$update $TMPDIR/destination $TMPDIR/destination-pr.json $TMPDIR/origin $origin_info
|
||||||
)
|
)
|
||||||
local remote_head=origin
|
local remote_head=origin
|
||||||
if ${options[destination_is_fork]} ; then
|
if ${options[destination_is_fork]} ; then
|
||||||
|
@ -360,8 +366,7 @@ function finalize_options() {
|
||||||
options[origin_scheme]=$(scheme ${options[origin_url]})
|
options[origin_scheme]=$(scheme ${options[origin_url]})
|
||||||
options[origin_host_port]=$(host_port ${options[origin_url]})
|
options[origin_host_port]=$(host_port ${options[origin_url]})
|
||||||
set_git_url origin origin_clone ${options[origin_repo]}
|
set_git_url origin origin_clone ${options[origin_repo]}
|
||||||
options[origin_head]=refs/pull/${options[origin_pr]}/head
|
set_origin_head
|
||||||
origin_sanity_check
|
|
||||||
|
|
||||||
options[destination_api]=${options[destination_url]}/api/v1/repos/${options[destination_repo]}
|
options[destination_api]=${options[destination_url]}/api/v1/repos/${options[destination_repo]}
|
||||||
options[destination_scheme]=$(scheme ${options[destination_url]})
|
options[destination_scheme]=$(scheme ${options[destination_url]})
|
||||||
|
@ -369,7 +374,7 @@ function finalize_options() {
|
||||||
set_git_url destination destination_clone ${options[destination_repo]}
|
set_git_url destination destination_clone ${options[destination_repo]}
|
||||||
options[destination_base]=${options[destination_branch]}
|
options[destination_base]=${options[destination_branch]}
|
||||||
: ${options[prefix]:=${options[origin_repo]}}
|
: ${options[prefix]:=${options[origin_repo]}}
|
||||||
options[destination_head]=${options[prefix]}-${options[origin_pr]}
|
set_destination_head
|
||||||
|
|
||||||
if test "${options[destination_fork_repo]}"; then
|
if test "${options[destination_fork_repo]}"; then
|
||||||
fork_sanity_check
|
fork_sanity_check
|
||||||
|
@ -384,11 +389,39 @@ function finalize_options() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
local state=$(pr_state origin)
|
|
||||||
|
|
||||||
repo_login origin
|
repo_login origin
|
||||||
repo_login destination
|
repo_login destination
|
||||||
|
|
||||||
|
if $(origin_has_pr); then
|
||||||
|
run_origin_pr
|
||||||
|
else
|
||||||
|
run_origin_ref
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_origin_ref() {
|
||||||
|
log_info "update or create the cascade branch and PR"
|
||||||
|
checkout
|
||||||
|
update
|
||||||
|
local sha=$(sha_pushed destination)
|
||||||
|
if test "$sha" ; then
|
||||||
|
upsert_destination_pr
|
||||||
|
local status
|
||||||
|
if wait_destination_ci "$sha" ; then
|
||||||
|
log_info "cascade PR status successful"
|
||||||
|
status=0
|
||||||
|
else
|
||||||
|
log_info "cascade PR status failed"
|
||||||
|
status=1
|
||||||
|
fi
|
||||||
|
close_pr
|
||||||
|
return $status
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_origin_pr() {
|
||||||
|
local state=$(pr_state origin)
|
||||||
|
|
||||||
case "$state" in
|
case "$state" in
|
||||||
open)
|
open)
|
||||||
log_info "PR is open, update or create the cascade branch and PR"
|
log_info "PR is open, update or create the cascade branch and PR"
|
||||||
|
@ -455,6 +488,11 @@ function main() {
|
||||||
options[origin_pr]=$1
|
options[origin_pr]=$1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--origin-ref)
|
||||||
|
shift
|
||||||
|
options[origin_ref]=$1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--destination-url)
|
--destination-url)
|
||||||
shift
|
shift
|
||||||
options[destination_url]=$1
|
options[destination_url]=$1
|
||||||
|
|
8
tests/destination-fail/.forgejo/workflows/test.yml
Normal file
8
tests/destination-fail/.forgejo/workflows/test.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
name: test
|
||||||
|
on: [pull_request_target]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
|
- run: false
|
20
tests/origin-branch-fail/.forgejo/workflows/test.yml
Normal file
20
tests/origin-branch-fail/.forgejo/workflows/test.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
name: test
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
|
- uses: SELF@vTest
|
||||||
|
with:
|
||||||
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
origin-repo: user1/origin-branch-fail
|
||||||
|
origin-token: ${{ secrets.ORIGIN_TOKEN }}
|
||||||
|
origin-ref: refs/heads/main
|
||||||
|
destination-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
destination-repo: user2/destination-fail
|
||||||
|
destination-branch: main
|
||||||
|
destination-token: ${{ secrets.DESTINATION_TOKEN }}
|
||||||
|
update: ./upgraded
|
||||||
|
debug: true
|
1
tests/origin-branch-fail/README
Normal file
1
tests/origin-branch-fail/README
Normal file
|
@ -0,0 +1 @@
|
||||||
|
originrepo
|
14
tests/origin-branch-fail/upgraded
Executable file
14
tests/origin-branch-fail/upgraded
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
destination_checkout="$1"
|
||||||
|
destination_pr_json="$2"
|
||||||
|
origin_checkout="$3"
|
||||||
|
origin_ref="$4"
|
||||||
|
|
||||||
|
test -d $destination_checkout
|
||||||
|
test -d $origin_checkout
|
||||||
|
test "$origin_ref"
|
||||||
|
|
||||||
|
date +%s > $destination_checkout/last
|
20
tests/origin-branch/.forgejo/workflows/test.yml
Normal file
20
tests/origin-branch/.forgejo/workflows/test.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
name: test
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
|
- uses: SELF@vTest
|
||||||
|
with:
|
||||||
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
origin-repo: user1/origin-branch
|
||||||
|
origin-token: ${{ secrets.ORIGIN_TOKEN }}
|
||||||
|
origin-ref: refs/heads/main
|
||||||
|
destination-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
destination-repo: user2/destinationrepo
|
||||||
|
destination-branch: main
|
||||||
|
destination-token: ${{ secrets.DESTINATION_TOKEN }}
|
||||||
|
update: ./upgraded
|
||||||
|
debug: true
|
1
tests/origin-branch/README
Normal file
1
tests/origin-branch/README
Normal file
|
@ -0,0 +1 @@
|
||||||
|
originrepo
|
14
tests/origin-branch/upgraded
Executable file
14
tests/origin-branch/upgraded
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
destination_checkout="$1"
|
||||||
|
destination_pr_json="$2"
|
||||||
|
origin_checkout="$3"
|
||||||
|
origin_ref="$4"
|
||||||
|
|
||||||
|
test -d $destination_checkout
|
||||||
|
test -d $origin_checkout
|
||||||
|
test "$origin_ref"
|
||||||
|
|
||||||
|
date +%s > $destination_checkout/last
|
73
tests/run.sh
73
tests/run.sh
|
@ -79,17 +79,35 @@ function merge_pull_request() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function has_cascade_pull_request() {
|
function has_cascade_pull_request() {
|
||||||
log_verbose "verify a cascade pull request exists"
|
local repo="${1:-destinationrepo}"
|
||||||
test "$(cascade_pull_request_count)" -gt 0
|
|
||||||
|
log_verbose "verify an open cascade pull request exists"
|
||||||
|
test "$(cascade_open_pull_request_count $repo)" -gt 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function has_no_cascade_pull_request() {
|
function has_no_cascade_pull_request() {
|
||||||
log_verbose "verify there is no cascade pull request"
|
local repo="${1:-destinationrepo}"
|
||||||
test "$(cascade_pull_request_count)" = 0
|
|
||||||
|
log_verbose "verify there is no open cascade pull request"
|
||||||
|
test "$(cascade_open_pull_request_count $repo)" = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function cascade_open_pull_request_count() {
|
||||||
|
local repo="$1"
|
||||||
|
|
||||||
|
cascade_pull_request $repo | jq '[ .[] | select(.state == "open") ] | length'
|
||||||
}
|
}
|
||||||
|
|
||||||
function cascade_pull_request_count() {
|
function cascade_pull_request_count() {
|
||||||
forgejo-curl.sh api_json ${options[url]}/api/v1/repos/user2/destinationrepo/pulls | jq '[ .[] | select(.state == "open") ] | length'
|
local repo="$1"
|
||||||
|
|
||||||
|
cascade_pull_request $repo | jq '. | length'
|
||||||
|
}
|
||||||
|
|
||||||
|
function cascade_pull_request() {
|
||||||
|
local repo="$1"
|
||||||
|
|
||||||
|
forgejo-curl.sh api_json ${options[url]}/api/v1/repos/user2/${repo}/pulls
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_branch1() {
|
function create_branch1() {
|
||||||
|
@ -150,6 +168,13 @@ function create_pull_request_case1() {
|
||||||
create_pull_request $baseowner $headowner $repo
|
create_pull_request $baseowner $headowner $repo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unit_finalize_options() {
|
||||||
|
sanity_check_pr_or_ref A B || test $? = 1
|
||||||
|
sanity_check_pr_or_ref '' '' || test $? = 2
|
||||||
|
sanity_check_pr_or_ref A ''
|
||||||
|
sanity_check_pr_or_ref '' B
|
||||||
|
}
|
||||||
|
|
||||||
function unit_retry_fail() {
|
function unit_retry_fail() {
|
||||||
local file=$1
|
local file=$1
|
||||||
local value=$(cat $file)
|
local value=$(cat $file)
|
||||||
|
@ -246,6 +271,34 @@ function no_change_no_cascade_pr() {
|
||||||
has_no_cascade_pull_request
|
has_no_cascade_pull_request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function branch_and_success() {
|
||||||
|
local origin_repo=origin-branch
|
||||||
|
local destination_repo=destinationrepo
|
||||||
|
|
||||||
|
fixture ${origin_repo} ${destination_repo}
|
||||||
|
user_secret user1 DESTINATION_TOKEN $(user_token user2 DESTINATION_TOKEN)
|
||||||
|
|
||||||
|
test $(cascade_pull_request_count ${destination_repo}) = 0
|
||||||
|
create_branch1 user1 ${origin_repo}
|
||||||
|
wait_success ${options[url]}/api/v1/repos/user1/${origin_repo} $(cat $TMPDIR/user1-${origin_repo}.sha)
|
||||||
|
test $(cascade_pull_request_count ${destination_repo}) = 1
|
||||||
|
has_no_cascade_pull_request ${destination_repo}
|
||||||
|
}
|
||||||
|
|
||||||
|
function branch_and_fail() {
|
||||||
|
local origin_repo=origin-branch-fail
|
||||||
|
local destination_repo=destination-fail
|
||||||
|
|
||||||
|
fixture ${origin_repo} ${destination_repo}
|
||||||
|
user_secret user1 DESTINATION_TOKEN $(user_token user2 DESTINATION_TOKEN)
|
||||||
|
|
||||||
|
test $(cascade_pull_request_count ${destination_repo}) = 0
|
||||||
|
create_branch1 user1 ${origin_repo}
|
||||||
|
wait_failure ${options[url]}/api/v1/repos/user1/${origin_repo} $(cat $TMPDIR/user1-${origin_repo}.sha)
|
||||||
|
test $(cascade_pull_request_count ${destination_repo}) = 1
|
||||||
|
has_no_cascade_pull_request ${destination_repo}
|
||||||
|
}
|
||||||
|
|
||||||
function create_and_close() {
|
function create_and_close() {
|
||||||
fixture originrepo destinationrepo
|
fixture originrepo destinationrepo
|
||||||
user_secret user1 DESTINATION_TOKEN $(user_token user2 DESTINATION_TOKEN)
|
user_secret user1 DESTINATION_TOKEN $(user_token user2 DESTINATION_TOKEN)
|
||||||
|
@ -367,6 +420,7 @@ function run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function integration() {
|
function integration() {
|
||||||
|
run branch_and_success
|
||||||
run no_change_no_cascade_pr
|
run no_change_no_cascade_pr
|
||||||
run create_in_destination_fork_and_close
|
run create_in_destination_fork_and_close
|
||||||
run create_and_close
|
run create_and_close
|
||||||
|
@ -379,6 +433,7 @@ function integration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function unit() {
|
function unit() {
|
||||||
|
unit_finalize_options
|
||||||
unit_retry
|
unit_retry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,12 +443,12 @@ function run_tests() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function finalize_options() {
|
function finalize_options() {
|
||||||
if test -f forgejo-ip; then
|
if test -f $DIR/forgejo-ip; then
|
||||||
: ${options[host_port]:=$(cat forgejo-ip):3000}
|
: ${options[host_port]:=$(cat $DIR/forgejo-ip):3000}
|
||||||
fi
|
fi
|
||||||
options[url]=http://${options[host_port]}
|
options[url]=http://${options[host_port]}
|
||||||
if test -f forgejo-token; then
|
if test -f $DIR/forgejo-token; then
|
||||||
: ${options[token]:=$(cat forgejo-token)}
|
: ${options[token]:=$(cat $DIR/forgejo-token)}
|
||||||
fi
|
fi
|
||||||
options[password]=admin1234
|
options[password]=admin1234
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue