# SPDX-License-Identifier: MIT name: 'Cascading PR' author: 'Forgejo authors' description: | 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. When used in a workflow triggered by a PR event in `origin-repo`, `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. 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/) with the proposed change and `cascading-pr` waits until the CI in `actions/setup-forgejo` is successful. The `update` script is expected to be found in `origin-repo` and is given the following arguments: * 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` 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`. `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 update to `destination-repo` (or `destination-fork-repo`) and open a pull request. It needs the `read:user`, `write:repository` and `write:issue` scopes. 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. 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. If the fork of the destination repository is specified and it does not exist, it is created. inputs: origin-url: description: 'URL of the Forgejo instance where the PR that triggers the action is located (e.g. https://code.forgejo.org)' required: true origin-repo: description: 'the repository in which the PR was created' required: true origin-token: description: 'a token with write permission on origin-repo' required: true origin-pr: description: 'number of the PR in {orign-repo}, mutually exclusive with {origin-ref}' origin-ref: description: 'reference in {orign-repo}, mutually exclusive with {origin-pr}' destination-url: description: 'URL of the Forgejo instance where the cascading PR is created or updated (e.g. https://code.forgejo.org)' required: true destination-repo: description: 'the repository in which the cascading PR is created or updated' required: true destination-fork-repo: description: 'the fork of {destination-repo} in which the {destination-branch} will be created or updated' destination-branch: description: 'the base branch of the destination repository for the cascading PR' required: true destination-token: description: 'a token with write permission on destination-repo' required: true update: description: 'path to the script to update the content of the cascading PR' required: true prefix: description: 'prefix of the branch from which the cascading PR is created on {destination-repo} or {destination-fork-repo} (default to {origin-repo})' close: description: 'if true the cascading PR will be closed and the branch deleted when (i) the {origin-pr} is merged or (ii) when the cascading PR status is success if {origin-ref} is set' default: false verbose: description: 'if true print verbose information' default: false debug: description: 'if true print debug information' default: false runs: using: "composite" steps: - run: | export PATH=${{ github.action_path }}:$PATH if "${{ inputs.verbose }}"; then verbosity="$verbosity --verbose" fi if "${{ inputs.debug }}"; then verbosity="$verbosity --debug" fi origin_token=$(pwd)/origin.token echo -n ${{ inputs.origin-token }} > $origin_token destination_token=$(pwd)/destination.token echo -n ${{ inputs.destination-token }} > $destination_token cascading-pr.sh $verbosity \ --origin-url "${{ inputs.origin-url }}" \ --origin-repo "${{ inputs.origin-repo }}" \ --origin-token "@$origin_token" \ --origin-pr "${{ inputs.origin-pr }}" \ --origin-ref "${{ inputs.origin-ref }}" \ --destination-url "${{ inputs.destination-url }}" \ --destination-repo "${{ inputs.destination-repo }}" \ --destination-fork-repo "${{ inputs.destination-fork-repo }}" \ --destination-token "@$destination_token" \ --destination-branch "${{ inputs.destination-branch }}" \ --update "${{ inputs.update }}" \ --prefix "${{ inputs.prefix }}" \ --close "${{ inputs.close }}" \ run