2023-10-11 18:09:39 +02:00
|
|
|
Create and synchronize a PR in a dependent repository
|
2023-10-11 15:39:52 +02:00
|
|
|
|
2023-10-13 23:38:57 +02:00
|
|
|
<!-- action-docs-description -->
|
|
|
|
## Description
|
|
|
|
|
|
|
|
|
2024-01-02 18:39:58 +01:00
|
|
|
If repository A depends on repository B, `cascadinging-pr` can be used
|
|
|
|
by a workflow in repository B to trigger the CI on repository A and
|
|
|
|
verify it passes when using a modified version of repository B. This
|
|
|
|
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.
|
2023-11-01 21:33:35 +01:00
|
|
|
|
|
|
|
When used in a workflow triggered by a PR event in `origin-repo`,
|
2024-01-02 18:39:58 +01:00
|
|
|
`cascading-pr` will create, update and close a matching PR in the
|
|
|
|
`destination-repo`. When the PR is updated, `cascading-pr` will
|
|
|
|
update the matching PR. It waits for the workflow triggered by these
|
|
|
|
updates in `destination-repo` to complete. If fails, `cascading-pr`,
|
|
|
|
also fails.
|
2023-10-13 23:38:57 +02:00
|
|
|
|
|
|
|
As an example, when a PR is created in
|
|
|
|
[`forgejo/runner`](https://code.forgejo.org/forgejo/runner/), a
|
|
|
|
matching PR is created in
|
|
|
|
[`actions/setup-forgejo`](https://code.forgejo.org/actions/setup-forgejo/)
|
2024-01-02 18:39:58 +01:00
|
|
|
with the proposed change and `cascading-pr` waits until the CI in
|
2023-11-01 21:33:35 +01:00
|
|
|
`actions/setup-forgejo` is successful.
|
2023-10-13 23:38:57 +02:00
|
|
|
|
2024-01-02 18:39:58 +01:00
|
|
|
The `update` script is expected to be found in `origin-repo` and is
|
|
|
|
given the following arguments:
|
2023-10-13 23:38:57 +02:00
|
|
|
|
2024-01-02 18:39:58 +01:00
|
|
|
* A directory path in which the `destination-branch` of `destination-repo`
|
|
|
|
(or a fork) is checked-out.
|
|
|
|
* The path to a JSON file describing the pull request in `destination-repo`.
|
|
|
|
* A directory path in which the head of `origin-repo` is checked-out at:
|
|
|
|
* if `origin-pr` is specified, the head branch of `origin-pr`
|
|
|
|
* otherwise `origin-ref`
|
|
|
|
* Information about the `origin-repo`
|
|
|
|
* if `origin-pr` is specified, the path to a JSON file desccribing
|
|
|
|
the pull request in `origin-repo`
|
|
|
|
* otherwise `origin-ref`
|
2023-10-13 23:38:57 +02:00
|
|
|
|
2024-01-02 18:39:58 +01:00
|
|
|
If changes are found in the destination repository directory after
|
|
|
|
the `update` script runs, they will be pushed as a new commit in the
|
|
|
|
PR in the `destination-repo`.
|
2023-10-28 17:40:09 +02:00
|
|
|
|
2023-11-01 21:33:35 +01:00
|
|
|
`origin-token` is used when accessing `origin-repo` and needs the
|
|
|
|
`read:user`, `read:repository` and `write:issue` scopes.
|
|
|
|
|
|
|
|
`destination-token` is used to push the branch that contains an
|
2024-01-02 18:39:58 +01:00
|
|
|
update to `destination-repo` (or `destination-fork-repo`) and open a
|
|
|
|
pull request. It needs the `read:user`, `write:repository` and
|
|
|
|
`write:issue` scopes.
|
2023-11-01 21:33:35 +01:00
|
|
|
|
|
|
|
It is recommended that a dedicated user is used to create
|
|
|
|
`destination-token` and that `destination-fork-repo` is always used
|
|
|
|
unless the users who are able to create pull requests are trusted.
|
|
|
|
|
2024-01-02 18:39:58 +01:00
|
|
|
When the PR in the `destination-repo` is from a forked repository,
|
|
|
|
the `update` script is run from the default branch of
|
|
|
|
`destination-repo` instead of the head of the PR which is a branch
|
|
|
|
in destination-fork-repo. The PR author must not be trusted and it
|
|
|
|
is imperative that the `update` script never runs anything found in
|
|
|
|
the head branch of the PR.
|
2023-11-01 17:47:42 +01:00
|
|
|
|
|
|
|
If the fork of the destination repository is specified and it does
|
|
|
|
not exist, it is created.
|
2023-10-13 23:38:57 +02:00
|
|
|
<!-- action-docs-description -->
|
|
|
|
<!-- action-docs-inputs -->
|
|
|
|
## Inputs
|
|
|
|
|
|
|
|
| parameter | description | required | default |
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
| 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-token | a token with write permission on origin-repo | `true` | |
|
2024-01-02 18:39:58 +01:00
|
|
|
| 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` | |
|
2023-10-13 23:38:57 +02:00
|
|
|
| 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` | |
|
2023-11-01 18:40:23 +01:00
|
|
|
| destination-fork-repo | the fork of {destination-repo} in which the {destination-branch} will be created or updated | `false` | |
|
2023-10-13 23:38:57 +02:00
|
|
|
| destination-branch | the base branch of the destination repository for the cascading PR | `true` | |
|
|
|
|
| destination-token | a token with write permission on destination-repo | `true` | |
|
|
|
|
| update | path to the script to update the content of the cascading PR | `true` | |
|
|
|
|
| prefix | prefix of the cascading PR created on destination-repo (default to {origin-repo}) | `false` | |
|
2023-10-24 22:51:30 +02:00
|
|
|
| close-merge | if true the cascading PR will be closed and the branch deleted when the PR is merged | `false` | false |
|
2023-10-13 23:38:57 +02:00
|
|
|
| verbose | if true print verbose information | `false` | false |
|
|
|
|
| debug | if true print debug information | `false` | false |
|
|
|
|
<!-- action-docs-inputs -->
|
|
|
|
|
2023-11-05 00:02:27 +01:00
|
|
|
# Forgejo dependencies
|
|
|
|
|
|
|
|
The [Forgejo](https://codeberg.org/forgejo/forgejo/) repositories that depend on each other are
|
|
|
|
linked with workflows using `cascading-pr` as follows.
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart TD
|
|
|
|
lxc-helper(lxc-helper) --> act(act)
|
|
|
|
act --> runner(Forgejo runner)
|
|
|
|
runner --> setup-forgejo(setup-forgejo)
|
|
|
|
setup-forgejo --> e2e(end-to-end)
|
|
|
|
forgejo-curl(forgejo-curl.sh) --> setup-forgejo
|
|
|
|
forgejo(forgejo) --> e2e
|
|
|
|
|
|
|
|
click lxc-helper "https://code.forgejo.org/forgejo/lxc-helpers/src/branch/main/.forgejo/workflows/cascade-act.yml"
|
|
|
|
click act "https://code.forgejo.org/forgejo/act/src/branch/main/.forgejo/workflows/cascade-runner.yml"
|
|
|
|
click runner "https://code.forgejo.org/forgejo/runner/src/branch/main/.forgejo/workflows/cascade-setup-forgejo.yml"
|
|
|
|
click setup-forgejo "https://code.forgejo.org/actions/setup-forgejo/src/branch/main/.forgejo/workflows/cascade-end-to-end.yml"
|
|
|
|
click e2e "https://code.forgejo.org/actions/end-to-end"
|
|
|
|
click forgejo-curl "https://code.forgejo.org/forgejo/forgejo-curl/src/branch/main/.forgejo/workflows/cascade-setup-forgejo.yml"
|
|
|
|
click forgejo "https://codeberg.org/forgejo/forgejo/src/branch/forgejo/.forgejo/workflows/cascade-setup-end-to-end.yml"
|
|
|
|
```
|
|
|
|
|
|
|
|
# Example workflow
|
2023-10-13 23:38:57 +02:00
|
|
|
|
|
|
|
```yaml
|
|
|
|
on:
|
|
|
|
pull_request:
|
|
|
|
types:
|
|
|
|
- opened
|
|
|
|
- synchronize
|
|
|
|
- closed
|
|
|
|
|
|
|
|
jobs:
|
|
|
|
test:
|
|
|
|
runs-on: docker
|
|
|
|
steps:
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/cascading-pr@v1
|
|
|
|
with:
|
|
|
|
origin-url: https://code.forgejo.org
|
|
|
|
origin-repo: forgejo/lxc-helpers
|
|
|
|
origin-token: ${{ secrets.ORIGIN_TOKEN }}
|
|
|
|
origin-pr: ${{ github.event.pull_request.number }}
|
|
|
|
destination-url: https://code.forgejo.org
|
2023-11-05 00:02:27 +01:00
|
|
|
destination-repo: forgejo/act
|
2023-10-13 23:38:57 +02:00
|
|
|
destination-branch: main
|
|
|
|
destination-token: ${{ secrets.DESTINATION_TOKEN }}
|
|
|
|
update: ./upgrade-lxc-helpers
|
|
|
|
```
|
|
|
|
|
2023-11-01 17:06:59 +01:00
|
|
|
# Pull requests from forked repositories
|
|
|
|
|
|
|
|
When `cascading-pr` runs as a consequence of pull request from a
|
|
|
|
forked repository, the workflow must be triggered by a `pull_request_target`
|
|
|
|
event otherwise it will not have access to secrets.
|
|
|
|
|
|
|
|
# Prevent privilege escalation
|
|
|
|
|
|
|
|
When `cascading-pr` runs as a consequence of a pull request from a
|
|
|
|
repository forked from `orgin-repo`, it should create a pull request
|
|
|
|
from a forked repository of `destination-repo` by specifying the
|
|
|
|
`destination-fork-repo`.
|
|
|
|
|
|
|
|
If the `destination-fork-repo` repository does not exist, it will be
|
|
|
|
created as a fork of the `destination-repo` repository, using
|
|
|
|
`destination-token`.
|
|
|
|
|
2023-10-11 15:39:52 +02:00
|
|
|
# Hacking
|
|
|
|
|
2023-10-13 15:52:40 +02:00
|
|
|
The test environment consists of the following (all users password is admin1234)
|
2023-10-13 14:54:56 +02:00
|
|
|
|
|
|
|
* A forgejo instance with a runner
|
|
|
|
* An unprivileged user user1
|
|
|
|
* The repository user1/originrepo
|
|
|
|
* contains a pull_request workflow using cascading-pr that targets user2/destinationrepo
|
|
|
|
* contains a script that will modify user2/destinationrepo
|
2023-10-13 15:23:50 +02:00
|
|
|
* a branch1 at the same commit as main
|
2023-10-13 14:54:56 +02:00
|
|
|
* The repository user1/cascading-pr with the action under test
|
|
|
|
* An unprivileged user user2
|
|
|
|
* The repository user2/destinationrepo
|
|
|
|
|
2023-10-22 17:25:03 +02:00
|
|
|
```sh
|
|
|
|
git clone https://code.forgejo.org/actions/setup-forgejo
|
|
|
|
export PATH=$(pwd)/setup-forgejo:$PATH
|
|
|
|
git clone https://code.forgejo.org/actions/cascading-pr
|
|
|
|
cd cascading-pr
|
2024-01-02 18:39:58 +01:00
|
|
|
export DIR=/tmp/forgejo-for-cascading-pr
|
2023-10-22 17:25:03 +02:00
|
|
|
forgejo-curl.sh logout
|
|
|
|
forgejo-runner.sh teardown
|
2024-01-02 18:39:58 +01:00
|
|
|
forgejo-binary.sh teardown
|
|
|
|
forgejo-binary.sh setup root admin1234 https://codeberg.org/forgejo/forgejo/releases/download/v1.21.3-0/forgejo-1.21.3-0-linux-amd64
|
2023-10-22 17:25:03 +02:00
|
|
|
FORGEJO_RUNNER_CONFIG=$(pwd)/tests/runner-config.yaml forgejo-runner.sh setup
|
2024-01-02 18:39:58 +01:00
|
|
|
url=$(cat $DIR/forgejo-url)
|
2023-10-22 17:25:03 +02:00
|
|
|
firefox $url
|
|
|
|
```
|
|
|
|
|
2023-10-13 15:23:50 +02:00
|
|
|
The test for a successful run of the cascading-pr action consists of:
|
|
|
|
|
|
|
|
* creating a PR from branch1 to main
|
|
|
|
* wait for the commit status until it is successful
|
|
|
|
|
2023-10-13 14:54:56 +02:00
|
|
|
## testing an update on the action
|
|
|
|
|
|
|
|
* run `tests/run.sh --debug` once so all is in place
|
|
|
|
* commit changes to the files that are in the cascading-pr action
|
|
|
|
(action.yml, cascading-pr.sh etc.)
|
|
|
|
* push the modified action to `user1/cascading-pr`
|
|
|
|
* visit $url/user1/originrepo/actions/runs/1 and click re-run
|
|
|
|
|
|
|
|
## interactive debugging
|
|
|
|
|
|
|
|
Following the steps below recreate the same environment as the
|
|
|
|
integration workflow locally. It is helpful for forensic analysis when
|
|
|
|
something does not run as expected and the error displayed are unclear.
|
|
|
|
|
|
|
|
To help with the development loop all steps are idempotent and
|
|
|
|
running `tests/run.sh --debug` multiple times must succeed.
|
|
|
|
|
|
|
|
Individual steps can be run independendely by using the name of the function.
|
|
|
|
For instance:
|
|
|
|
|
|
|
|
* `tests/run.sh --debug create_pull_request` will only call the `create_pull_request`
|
|
|
|
function found in `tests/run.sh` to (re)create the pull request in `user1/originrepo`.
|
|
|
|
* `./cascading-pr.sh --debug --origin-url ... upsert_branch` will only call the `upsert_branch`
|
|
|
|
function found in `cascading-pr.sh`.
|
|
|
|
|
|
|
|
## directories
|
|
|
|
|
|
|
|
The `tests/run.sh` script stores all its files in
|
|
|
|
`/tmp/cascading-pr-test`. The temporary directories created by
|
|
|
|
`cascading-pr.sh` are disposed of when the script ends.
|
|
|
|
|
|
|
|
## logging
|
|
|
|
|
|
|
|
If `--debug` is used a full debug log is displayed, very complete and
|
|
|
|
very verbose. Otherwise it is stashed in a temporary file and only
|
|
|
|
displayed if an error happens.
|
|
|
|
|
|
|
|
## snippets for copy/pasting
|
|
|
|
|
2023-10-11 15:39:52 +02:00
|
|
|
```sh
|
2023-10-11 16:25:56 +02:00
|
|
|
tests/run.sh --debug
|
2023-10-22 18:26:56 +02:00
|
|
|
tests/run.sh --debug no_change_no_cascade_pr
|
2023-10-13 14:54:56 +02:00
|
|
|
./cascading-pr.sh --debug --origin-url "$url" --origin-repo "user1/originrepo" --origin-token "$(cat /tmp/cascading-pr-test/user1/repo-token)" --origin-pr 1 --destination-url "$url" --destination-repo "user2/destinationrepo" --destination-token "$(cat /tmp/cascading-pr-test/user2/repo-token)" --destination-branch "main" --update "upgraded" run
|
2023-10-11 15:39:52 +02:00
|
|
|
```
|
2023-10-13 23:38:57 +02:00
|
|
|
|
|
|
|
## Update the README
|
|
|
|
|
|
|
|
With https://github.com/npalm/action-docs `action-docs --update-readme`
|