116 lines
4.0 KiB
Markdown
116 lines
4.0 KiB
Markdown
# josh-sync
|
|
|
|
Bidirectional monorepo ↔ subrepo sync via [josh-proxy](https://josh-project.github.io/josh/). Supports multiple sync targets from a single config.
|
|
|
|
## Quick Start
|
|
|
|
### 1. Add config
|
|
|
|
Create `.josh-sync.yml` in your monorepo root:
|
|
|
|
```yaml
|
|
schema_version: 2
|
|
|
|
josh:
|
|
proxy_url: "https://josh.example.com"
|
|
monorepo_path: "org/monorepo"
|
|
monorepo_url: "git@gitea.example.com:org/monorepo.git"
|
|
monorepo_auth: "ssh" # optional, default "https"
|
|
|
|
targets:
|
|
- name: "billing"
|
|
subfolder: "services/billing"
|
|
subrepo_url: "git@gitea.example.com:ext/billing.git"
|
|
subrepo_auth: "ssh"
|
|
branches:
|
|
main: main
|
|
exclude: # files excluded from subrepo (optional)
|
|
- ".monorepo/"
|
|
|
|
bot:
|
|
name: "josh-sync-bot"
|
|
email: "josh-sync-bot@example.com"
|
|
trailer: "Josh-Sync-Origin"
|
|
```
|
|
|
|
### 2. Add CI workflows
|
|
|
|
Copy from [examples/](examples/) and customize paths/branches:
|
|
|
|
```yaml
|
|
# .gitea/workflows/josh-sync-forward.yml
|
|
- uses: https://your-gitea.example.com/org/josh-sync@v1
|
|
with:
|
|
direction: forward
|
|
env:
|
|
SYNC_BOT_USER: ${{ secrets.SYNC_BOT_USER }}
|
|
SYNC_BOT_TOKEN: ${{ secrets.SYNC_BOT_TOKEN }}
|
|
SUBREPO_SSH_KEY: ${{ secrets.SUBREPO_SSH_KEY }}
|
|
```
|
|
|
|
### 3. Local dev (Nix)
|
|
|
|
Add josh-sync as a flake input, then:
|
|
|
|
```nix
|
|
{ inputs, ... }: {
|
|
imports = [ inputs.josh-sync.devenvModules.default ];
|
|
}
|
|
```
|
|
|
|
Run `josh-sync preflight` to validate your setup.
|
|
|
|
## Documentation
|
|
|
|
- **[Setup Guide](docs/guide.md)** — Step-by-step: prerequisites, importing existing subrepos, CI workflows, file exclusion, and troubleshooting
|
|
- **[Configuration Reference](docs/config-reference.md)** — Full `.josh-sync.yml` field documentation
|
|
- **[Architecture Decision Records](docs/adr/)** — Design rationale and trade-offs
|
|
- **[Changelog](CHANGELOG.md)** — Version history
|
|
|
|
## Versioning
|
|
|
|
josh-sync follows [semver](https://semver.org/):
|
|
|
|
| Bump | Meaning | Action required |
|
|
|------|---------|-----------------|
|
|
| **Patch** (1.x.**y**) | Bug fixes only | Safe to upgrade |
|
|
| **Minor** (1.**y**.0) | New optional config fields, new commands, new action inputs | Safe to upgrade; new features are opt-in |
|
|
| **Major** (**y**.0.0) | Removed or renamed config fields, CLI flags, action inputs, env vars, or state format | Read the **Breaking Changes** section in the changelog before upgrading |
|
|
|
|
CI workflows pin to a floating major tag (e.g. `@v1`). A breaking change bumps the major version and moves the tag — `@v1` workflows keep working until you explicitly update to `@v2`.
|
|
|
|
## CLI
|
|
|
|
```
|
|
josh-sync sync [--forward|--reverse] [--force] [--target NAME[,NAME]] [--branch BRANCH]
|
|
josh-sync preflight
|
|
josh-sync import <target>
|
|
josh-sync adopt <target> [--restart]
|
|
josh-sync reset <target>
|
|
josh-sync onboard <target> [--restart]
|
|
josh-sync migrate-pr <target> [PR#...] [--all]
|
|
josh-sync status
|
|
josh-sync state show <target> [branch]
|
|
josh-sync state reset <target> [branch]
|
|
```
|
|
|
|
## How It Works
|
|
|
|
- **Forward sync** (mono → subrepo): pushes directly if clean, creates conflict PR if not. Uses `--force-with-lease` for safety.
|
|
- **Reverse sync** (subrepo → mono): creates a PR by default. Add `--force` to bypass the PR and push directly to the mono branch (destructive).
|
|
- **Adoption**: existing active subrepos can be connected to josh-sync with a normal fast-forward merge commit, preserving old subrepo history and avoiding force-push.
|
|
- **File exclusion**: `exclude` patterns are embedded inline in the josh-proxy URL. Excluded files exist only in the monorepo.
|
|
- **Filter reconciliation**: Changing the exclude list auto-creates a merge commit that connects old and new histories — no force-push needed.
|
|
- **Loop prevention**: `Josh-Sync-Origin:` git trailer filters out bot commits.
|
|
- **State tracking**: orphan branch `josh-sync-state` stores JSON per target/branch.
|
|
|
|
## Dependencies
|
|
|
|
`bash >=4`, `git`, `curl`, `jq`, `yq` ([mikefarah/yq](https://github.com/mikefarah/yq) v4+), `openssh`, `rsync`
|
|
|
|
> The Nix flake bundles all dependencies automatically.
|
|
|
|
## License
|
|
|
|
MIT
|