No Branch/Tag Specified
main
feature-activitypub
feature-go-ap-inbox-outbox
old
feature-manual-inbox-outbox
feature-manual-inbox-outbox-old
feature-inbox-outbox
feature-go-fed
feature-activitypub-old
base-activitypub
release/v1.16
release/v1.15
release/v1.14
release/v1.13
release/v1.12
release/v1.11
release/v1.10
release/v1.9
release/v1.8
v1.19.0-dev
v1.18.0-rc0
v1.17.3
v1.17.2
v1.17.1
v1.17.0
v1.17.0-rc2
v1.16.9
v1.17.0-rc1
v1.18.0-dev
v1.16.8
v1.16.7
v1.16.6
v1.16.5
v1.16.4
v1.16.3
v1.16.2
v1.16.1
v1.16.0
v1.15.11
v1.17.0-dev
v1.16.0-rc1
v1.15.10
v1.15.9
v1.15.8
v1.15.7
v1.15.6
v1.15.5
v1.15.4
v1.15.3
v1.15.2
v1.15.1
v1.14.7
v1.15.0
v1.15.0-rc3
v1.14.6
v1.15.0-rc2
v1.14.5
v1.16.0-dev
v1.15.0-rc1
v1.14.4
v1.14.3
v1.14.2
v1.14.1
v1.14.0
v1.13.7
v1.14.0-rc2
v1.13.6
v1.13.5
v1.14.0-rc1
v1.15.0-dev
v1.13.4
v1.13.3
v1.13.2
v1.13.1
v1.13.0
v1.12.6
v1.13.0-rc2
v1.14.0-dev
v1.13.0-rc1
v1.12.5
v1.12.4
v1.12.3
v1.12.2
v1.12.1
v1.11.8
v1.12.0
v1.11.7
v1.12.0-rc2
v1.11.6
v1.12.0-rc1
v1.13.0-dev
v1.11.5
v1.11.4
v1.11.3
v1.10.6
v1.12.0-dev
v1.11.2
v1.10.5
v1.11.1
v1.10.4
v1.11.0
v1.11.0-rc2
v1.10.3
v1.11.0-rc1
v1.10.2
v1.10.1
v1.10.0
v1.9.6
v1.9.5
v1.10.0-rc2
v1.11.0-dev
v1.10.0-rc1
v1.9.4
v1.9.3
v1.9.2
v1.9.1
v1.9.0
v1.9.0-rc2
v1.10.0-dev
v1.9.0-rc1
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.8.0-rc3
v1.7.6
v1.8.0-rc2
v1.7.5
v1.8.0-rc1
v1.9.0-dev
v1.7.4
v1.7.3
v1.7.2
v1.7.1
v1.7.0
v1.7.0-rc3
v1.6.4
v1.7.0-rc2
v1.6.3
v1.7.0-rc1
v1.7.0-dev
v1.6.2
v1.6.1
v1.6.0
v1.6.0-rc2
v1.5.3
v1.6.0-rc1
v1.6.0-dev
v1.5.2
v1.5.1
v1.5.0
v1.5.0-rc2
v1.5.0-rc1
v1.5.0-dev
v1.4.3
v1.4.2
v1.4.1
v1.4.0
v1.4.0-rc3
v1.4.0-rc2
v1.3.3
v1.4.0-rc1
v1.3.2
v1.3.1
v1.3.0
v1.3.0-rc2
v1.3.0-rc1
v1.2.3
v1.2.2
v1.2.1
v1.2.0
v1.2.0-rc3
v1.2.0-rc2
v1.1.4
v1.2.0-rc1
v1.1.3
v1.1.2
v1.1.1
v1.1.0
v1.0.2
v1.0.1
v1.0.0
v0.9.99
Labels
No Label
Milestone
Set milestone
Clear milestone
No items
No Milestone
Projects
Set Project
Clear projects
No project
Assignees
Assign users
Clear assignees
No Assignees
4 Participants
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.
No due date set.
Dependencies
No dependencies set.
Reference: xy/gitea#7
Reference in New Issue
There is no content yet.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may exist for a short time before cleaning up, in most cases it CANNOT be undone. Continue?
For federated pull requests, this requires federated forking (use a Create activity and ForgeFed's Create flow) and patches over ActivityPub (https://codeberg.org/ForgeFed/ForgeFed/issues/88).
To make the implementation easier, I think we should try to reuse most of the existing code in Gitea for handling pull requests. (This is because we are retrofitting federation onto an existing forge, so we have to reuse the already present database representations and code for processing various actions.) To do that, we can mirror the remote fork to the original instance and when the original instance receives a Patch activity, it will create the pull request from the mirror of the remote fork to the original repo. The mirror doesn't necessarily have to be using Gitea's preexisting mirror functionality. We can also use ForgeFed to do mirroring.
I propose that the flow for federated PRs will look like this:
Alice has a repository hello-world on alice.com.
Bobert forks the repository to his instance at bobert.com. His instance creates the forked repository (maybe using the Gitea migrations feature) and sends a Create activity back to alice.com informing it that Alice's repo has been forked. alice.com creates a mirror of Bobert's forked repo. (Alternatively, Bobert's repo can be a push-mirror to the copy on alice.com)
Bobert pushes some commits to his fork. The commits are mirrored to alice.com.
Bobert creates a pull request. His instance sends a Patch activity instructing Alice's instance on how to construct the pull request using the mirror of Bobert's fork on alice.com.
The one thing that's currently missing is that Alice should also be able to push commits to Bobert's fork, but this requires federated collaborators which I haven't figure out how to do yet.
I guess I'm missing something, but I don't quite see why it has to be so complicated:
Why is federated forking (via ActivityPub) needed? Actually why is it needed at all, not just as a prerequisite for federated PRs?
I would have thought a fork simply consists of the other instance doing
git clone https://gitea.com/Ta180m/gitea
- what else needs to happen?I guess maybe it's to tell the origin repo that the clone exists?
I would have thought that any clone of the git repo could potentailly be able to send a PR - is there a reason that would be impossible or undesirable?
I've read the linked issue too, but I'm still puzzled why patches would be necessary for a PR between two Git repos. Surely the PR could just reference the target and origin URIs and the instance receiving the PR could do a
git pull
from the origin?What am I missing? (Sorry to be the one asking all the dumb questions…)
Hmm, thinking more, maybe the answer to both questions is that it's to support inter-VCS clones and PRs – so the origin and target needn't necessarily both be Git for example? ?
I guess that would be kind of cool if it's possible.
Or maybe I'm on the wrong track... ?
This should be avoided as much as possible. If I just click on fork and fork it to my Bobert's instance and never touch it again. Alice's instance shouldn't store that fork. You likely want to do this once the Bobert's instance wants to interact(so creating pull-request), but even then we might utilize AGit in order to avoid creating new repositories for each federated interacting with Alice's repository.
The purpose of the Create activity is to inform the original repo that it's been forked so the new fork can be listed as one of the forks of that repo.
Well yes, any Git forge supporting ForgeFed will be able to send a PR over ForgeFed, but not any clone in general, because to send a PR over ForgeFed, your forge has to actually support ForgeFed.
We need some sort of ActivityStreams object to notify the original instance that there's a PR incoming, so it seemed natural to use a ForgeFed patch. For Gitea-to-Gitea federation, it doesn't make much sense to store the actual changes in this object, so it'll probably only contain the target and origin URLs as you said.
No worries, these are great questions!
Inter-VCS clones and PRs sound really cool, but I don't think they'd work well in practice since different VCSes have significant differences. It would also be quite the nightmare to implement!
Good thinking. We can make it so that instead, when the original instance receives the Create activity, it's only used to list the fork as one of the forks of the repo (and maybe a special repository that contains no actual content is created). I haven't looked into the Agit flow yet, but that could be a good way to reduce disk space for storing remote forks when they submit PRs.
Ah yeah maybe still smart idea to send the Create activity so the repository can list it as a fork. FYI AGit isn't really well-known and only Gitea has added support for it since Gitea 1.16, so it might be a bit rough and need some polishing to fit our use-case, but it's really a nice solution in order to avoid disk space problems.
That makes sense. I don't know if it needs to be a strict requirement in order to be able to send a pull request, but maybe.
I was inexact with my wording, but that's exactly what I meant. Good to know.
I'm still not familiar enough with the specs to know if it's "natural", so I'll take you at your word – though on the surface it sounds odd to send a
patch
activity without a patch attached. ?What other use-cases does the
patch
activity have? Are there instances when a standalone patch would be sent via ForgeFed/ActivityPub, outside a pull request?I assume that would be the case with Git-to-Git federation in general – and indeed, more generally, whenever the same DVCS is used on both sides? Or is that not so?
Well, that's why I was assuming that in that instance a simple patch/diff would be sent instead of a literal pull request. But maybe it's not that simple even. I haven't thought about it at all. ?
Even at the point of a PR being sent, is it actually necessary to duplicate the remote repo locally? Since it's a clone of the local repo anyway, can't we just add it as a remote?
I think my wording there is a bit misleading. By patch activity, I meant the proposal in ForgeFed #88, which is a actually a Ticket object with an extra attachment. Since pull requests in Gitea are just issues with associated code, it seemed natural in that sense to use the Ticket object with extra information about the origin and target branches.
That's right. The only case where you would need to send in the actual changes is if you're using an generic AP server (for instance, pebbles in https://codeberg.org/ForgeFed/ForgeFed/src/branch/main/doc/EXAMPLE_WORKFLOWS.md), but I think this will be a very rare use case and we probably won't support it initially in Gitea.
One way to deal with this is to use AGit as @gusted suggested.
What happens if a server's offline?
With the current code, if one server is offline, the two servers will get out of sync.
There are a few ways to fix this. The easiest solution is this: let's say you want to open a PR on a remote instance, but that remote instance is down. Then your instance tries to make the PR and fails, so you see that no PR is created on your side either. Then both servers can be consistent and in sync.
The other solution is to keep an outgoing queue of activities. If you make the PR and it fails, you instance keeps it in a queue and tries again after a certain amount of time.
For all of these solutions, to ensure consistency, creating a PR to a offline server should visibly fail. The question now is whether we want to keep retrying a set number of times or just give up immediately.