diff --git a/.forgejo/cascading-pr-end-to-end b/.forgejo/cascading-pr-end-to-end
new file mode 100755
index 0000000000..a2950664ae
--- /dev/null
+++ b/.forgejo/cascading-pr-end-to-end
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -ex
+
+end_to_end=$1
+end_to_end_pr=$2
+forgejo=$3
+forgejo_pr=$4
+
+url=$(jq --raw-output .head.repo.html_url < $forgejo_pr)
+test "$url" != null
+branch=$(jq --raw-output .head.ref < $forgejo_pr)
+test "$branch" != null
+cd $end_to_end
+echo $url $branch 7.0.0+0-gitea-1.22.0 > forgejo/sources/1.22
+date > last-upgrade
diff --git a/.forgejo/workflows/cascade-setup-end-to-end.yml b/.forgejo/workflows/cascade-setup-end-to-end.yml
new file mode 100644
index 0000000000..7e4fb9a7b3
--- /dev/null
+++ b/.forgejo/workflows/cascade-setup-end-to-end.yml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: MIT
+on:
+   pull_request_target:
+     types:
+       - closed
+       - labeled
+
+jobs:
+  info:
+    runs-on: docker
+    container:
+      image: node:20-bookworm
+    steps:
+      - name: event
+        run: |
+          echo github.event.pull_request.head.repo.fork = ${{ github.event.pull_request.head.repo.fork }}
+          echo github.event.action = ${{ github.event.action }}
+          echo github.event.pull_request.merged = ${{ github.event.pull_request.merged }}
+          echo github.event.pull_request.labels.*.name
+          cat <<'EOF'
+          ${{ toJSON(github.event.pull_request.labels.*.name) }}
+          EOF
+
+  cascade:
+    runs-on: docker
+    container:
+      image: node:20-bookworm
+    if: >
+      github.event.pull_request.head.repo.fork == false &&
+      (
+        (
+          github.event.action == 'closed' && github.event.pull_request.merged
+        ) ||
+        (
+          github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'ready-to-merge')
+        )
+      )
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/cascading-pr@v1
+        with:
+          origin-url: ${{ env.GITHUB_SERVER_URL }}
+          origin-repo: ${{ github.repository }}
+          origin-token: ${{ secrets.END_TO_END_CASCADING_PR_ORIGIN }}
+          origin-pr: ${{ github.event.pull_request.number }}
+          destination-url: https://code.forgejo.org
+          destination-fork-repo: cascading-pr/end-to-end
+          destination-repo: forgejo/end-to-end
+          destination-branch: main
+          destination-token: ${{ secrets.END_TO_END_CASCADING_PR_DESTINATION }}
+          close-merge: true
+          update: .forgejo/cascading-pr-end-to-end