Federated via graft
2.3 kB
68 lines
1# graft
2
3A daemon and web-UI that mirrors repositories between Forgejo instances. Also connect to Radicle, Activity Pub and ATProto: git content, issues, comments and pull requests / patches.
4
5It runs on a timer, keeps state in a local SQLite file, and never force-pushes. Real divergences between the two sides are reported and left for humans to resolve.
6
7## What it syncs
8
9- **Git content**: the default branch, fast-forward only.
10- **Issues**: Forgejo issues become Radicle issues and vice versa. Create-only for now — edits made after the first mirror aren't propagated yet.
11- **Patches / pull requests**: a Forgejo PR opens a Radicle patch (and back), by pushing the PR's head commit to `refs/patches` on the Radicle side, or as a branch + PR on the Forgejo side.
12
13## Why
14
15Forgejo and Radicle solve the same problem — hosting and reviewing changes to a git repository — with opposite architectures: one is a server you point a browser at, the other is a peer-to-peer protocol with no server at all. `graft` lets a project exist on both.
16
17## Requirements
18
19- Go 1.23+ to build
20- `git`
21- the `rad` CLI, with `git-remote-rad` on `PATH`, and a Radicle node already running with its own identity (`rad auth`)
22- a Forgejo access token scoped to `write:repository` and `write:issue` on the repo you're syncing
23
24## Build
25
26```sh
27go build -o graft ./cmd/sync
28```
29
30## Config
31
32```yaml
33sync_interval: 5m
34state_db: /var/lib/graft/state.db
35
36repos:
37 - name: my-project
38 forgejo:
39 base_url: https://git.example.org
40 owner: alice
41 repo: my-project
42 token_file: /etc/graft/my-project.token
43 radicle:
44 rid: rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
45 http_base_url: https://seed.example.org
46 rad_home: /home/graft/.radicle
47 sync:
48 git: true
49 issues: true
50 patches: true
51```
52
53Tokens live in their own files, never inline in the config. `graft` reads them at startup and expects `chmod 600`.
54
55## Run
56
57```sh
58graft -config /etc/graft/config.yaml # loop forever, per sync_interval
59graft -config /etc/graft/config.yaml -once # one pass, then exit
60```
61
62A systemd unit is in `systemd/graft.service`.
63
64Full walkthrough, from a blank server to a running mirror: [TUTORIAL.md](TUTORIAL.md).
65
66## License
67
68GPLv3. See [LICENSE](LICENSE).