0d2aea9664d83357caf26cd71f8b3adfa27ec879
- SC2015: Wrap A && B || C patterns in brace groups for directive scope
- SC2064: Suppress for intentional early trap expansion (local vars)
- SC2164: Add || exit to cd commands in subshells
- SC2001: Suppress for sed URL injection (clearer than parameter expansion)
- SC1083: Handle {tree} git syntax (quote or suppress)
- SC1091: Suppress for runtime-resolved source paths
- SC2034: Remove unused exit codes (E_OK, E_CONFIG, E_AUTH)
- SC2116: Eliminate useless echo in mono_auth_url construction
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
josh-sync
Bidirectional monorepo ↔ subrepo sync via josh-proxy. Supports multiple sync targets from a single config.
Quick Start
1. Add config
Create .josh-sync.yml in your monorepo root:
josh:
proxy_url: "https://josh.example.com"
monorepo_path: "org/monorepo"
targets:
- name: "billing"
subfolder: "services/billing"
josh_filter: ":/services/billing"
subrepo_url: "git@gitea.example.com:ext/billing.git"
subrepo_auth: "ssh"
branches:
main: main
forward_only: []
bot:
name: "josh-sync-bot"
email: "josh-sync-bot@example.com"
trailer: "Josh-Sync-Origin"
2. Add CI workflows
Copy from examples/ and customize paths/branches:
# .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:
{ inputs, ... }: {
imports = [ inputs.josh-sync.devenvModules.default ];
}
Run josh-sync preflight to validate your setup.
CLI
josh-sync sync [--forward|--reverse] [--target NAME[,NAME]] [--branch BRANCH]
josh-sync preflight
josh-sync import <target>
josh-sync reset <target>
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-leasefor safety. - Reverse sync (subrepo → mono): always creates a PR, never pushes directly.
- Loop prevention:
Josh-Sync-Origin:git trailer filters out bot commits. - State tracking: orphan branch
josh-sync-statestores JSON per target/branch.
Dependencies
bash >=4, git, curl, jq, yq (mikefarah/yq v4+), openssh
License
MIT
Languages
Shell
95.6%
Nix
2.8%
Makefile
1.6%