# refray
A tool to keep your repos in sync across all git platforms, while being able to work from everywhere all at once.
Created becasue github is so unusable and [unreliable](https://red-squares.cian.lol/) and I want to leave, but I don't want to leave the community behind.
- **∞-side sync**: Sync between any number of hosted/self-hosted git accounts/orgs/groups
- **read-write mirrors**: Make changes from any provider, and the changes will sync to the others
- **webhook support**: Sync right after push, reduce potential divergence window
- **conflict handling**: Rebase or open pull requests when two platforms diverge
- **tracks deletions**: Branches/repo deletions sync across platforms (with backup)
- **selective sync**: Sync subset of repos by regex white/black list, or by private/public visibility
- **multithreaded**: Process multiple repos simultaneously!
Supported platforms: GitHub, GitLab, Gitea, Forgejo
> [!NOTE]
> My cat made this codebase, meow

## Install
### Option 1. Install with Cargo
1. Install rust cargo if you don't have it: https://rustup.rs
2. `cargo install refray`
### Option 2. Download binary
Go to the [releases page](https://github.com/MaigoLabs/refray/releases), find the latest release, and download the appropriate binary for your platform.
### Option 3. Docker Compose
```sh
docker compose run --rm refray config
# Start the webhook receiver as a service
docker compose up -d --build
# If you want to edit config manually:
docker compose run --rm --entrypoint nano refray /data/config/refray/config.toml
```
## Usage
### 1. Configure
Run the interactive configuration wizard:
```sh
refray config
```
Example Config
```toml
jobs = 8
[[sites]]
name = "github"
provider = "github"
base_url = "https://github.com"
token = { value = "github_pat_..." }
[[sites]]
name = "gitea"
provider = "gitea"
base_url = "https://gitea.example.com"
token = { value = "gitea_pat_..." }
[[mirrors]]
name = "personal"
sync_visibility = "all"
repo_whitelist = "^important-"
repo_blacklist = "-archive$"
create_missing = true
visibility = "private"
conflict_resolution = "auto_rebase_pull_request"
[[mirrors.endpoints]]
site = "github"
kind = "user"
namespace = "hykilpikonna"
[[mirrors.endpoints]]
site = "gitea"
kind = "user"
namespace = "azalea"
```
### 2. One-time Sync
Run all configured mirror groups:
```sh
refray sync
```
Sync options
Run one group:
```sh
refray sync --group personal
```
Preview commands without writing to Git remotes:
```sh
refray sync --dry-run
```
Skip repository creation even when `create_missing = true` in the mirror group:
```sh
refray sync --no-create
```
To restrict which repositories sync, set `repo_whitelist` and/or `repo_blacklist` on the mirror group in config.
Retry only repositories that failed during the previous non-dry-run sync:
```sh
refray sync --retry-failed
```
Control parallelism for sync, serve, and webhook commands in config. The default is 10 workers:
```toml
jobs = 8
```
### 3. Service & Webhooks
You can run `refray` as a service that listens for webhook events and runs full sync periodically. This is the recommended way to run `refray`.
> [!NOTE]
> If you want to use webhooks, you need to expose port 8787 to a public URL that can be accessed by the git provider.
> This can be done using e.g. port forwarding, reverse proxy, cloudflare tunnel, or tailscale funnel.
Start the service (to sync on push and also do full sync periodically):
```sh
refray serve
```
Install webhooks on all repos (with the URL in config):
```sh
refray webhook install
```
To uninstall webhooks previously installed by `refray`:
> [!WARNING]
> If you want to stop using `refray`, make sure you run this! Otherwise, all of your repos will keep trying to send webhooks to the URL.
```sh
refray webhook uninstall
```
By default, uninstall uses `[webhook].url` from your config. To remove hooks for a previous URL, pass it explicitly:
```sh
refray webhook uninstall https://old.example.com/webhook
```
To move installed hooks to a new public URL, use `webhook update`. It removes hooks matching the current configured `[webhook].url`, installs the new URL, updates `[webhook].url` in the config, and refreshes local webhook state:
```sh
refray webhook update https://new.example.com/webhook
```
## Issues and Pull Requests
Issues and pull requests are not mirrored.