Files
josh-sync/schema/config-schema.json
SBPro b28662d3b4 Release 2.0.0 — explicit monorepo_url, drop first-target-host inference
Breaking change. The monorepo's gitea host was previously inferred from the
first target's subrepo_url, silently coupling the two and breaking on any
multi-host setup (monorepo on host A, target on host B). v2.0.0 replaces the
inference with a required josh.monorepo_url field that mirrors subrepo_url —
same parsing, same SSH/HTTPS auth options, same shape.

- schema_version: 2 is now required; v1 configs are rejected with a clear migration error
- josh.monorepo_url is required; josh.monorepo_auth is optional (default https)
- mono_auth_url() in lib/auth.sh mirrors subrepo_auth_url()
- MONOREPO_API derives from monorepo_url's host instead of .[0].gitea_host;
  env-var override preserved as escape hatch
- initial_import() and force-push call mono_auth_url() instead of building URLs inline
- ADR-012 documents the rationale; CHANGELOG includes migration snippet

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 06:31:21 +03:00

118 lines
4.0 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "josh-sync configuration",
"description": "Configuration for bidirectional monorepo ↔ subrepo sync via josh-proxy",
"type": "object",
"required": ["schema_version", "josh", "targets", "bot"],
"properties": {
"schema_version": {
"type": "integer",
"const": 2,
"description": "Schema version. Required. Must be 2 for josh-sync v2.x configs."
},
"josh": {
"type": "object",
"required": ["proxy_url", "monorepo_path", "monorepo_url"],
"properties": {
"proxy_url": {
"type": "string",
"description": "Josh-proxy URL (no trailing slash)",
"pattern": "^https?://"
},
"monorepo_path": {
"type": "string",
"description": "Repo path as josh-proxy sees it (org/repo)"
},
"monorepo_url": {
"type": "string",
"description": "Monorepo git clone URL — git@host:org/repo.git (SSH) or https://host/org/repo.git. The gitea host is derived from this URL."
},
"monorepo_auth": {
"type": "string",
"enum": ["https", "ssh"],
"default": "https",
"description": "Auth method for cloning the monorepo. SSH uses the user's ssh-agent / ~/.ssh/config; HTTPS injects ${SYNC_BOT_USER}:${SYNC_BOT_TOKEN} into the URL."
}
}
},
"targets": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["name", "subfolder", "subrepo_url", "branches"],
"properties": {
"name": {
"type": "string",
"description": "Unique target identifier"
},
"subfolder": {
"type": "string",
"description": "Monorepo subfolder path"
},
"josh_filter": {
"type": "string",
"description": "Josh filter expression (auto-derived from subfolder if omitted)",
"pattern": "^:"
},
"subrepo_url": {
"type": "string",
"description": "External subrepo git URL (HTTPS or SSH)"
},
"subrepo_auth": {
"type": "string",
"enum": ["https", "ssh"],
"default": "https",
"description": "Auth method for subrepo"
},
"subrepo_token_var": {
"type": "string",
"description": "Env var name for per-target HTTPS token (default: SUBREPO_TOKEN)"
},
"subrepo_ssh_key_var": {
"type": "string",
"description": "Env var name for per-target SSH key (default: SUBREPO_SSH_KEY)"
},
"branches": {
"type": "object",
"description": "Branch mapping: mono_branch → subrepo_branch",
"additionalProperties": {
"type": "string"
}
},
"forward_only": {
"type": "array",
"items": { "type": "string" },
"default": [],
"description": "Branches that only sync mono → subrepo (never reverse)"
},
"exclude": {
"type": "array",
"items": { "type": "string" },
"default": [],
"description": "File/directory patterns to exclude from sync via josh :exclude filter. Josh pattern syntax: 'dir/' for directories, '*.ext' for globs, '**/dir/' for nested matches. Patterns are embedded inline in the josh-proxy URL."
}
}
}
},
"bot": {
"type": "object",
"required": ["name", "email", "trailer"],
"properties": {
"name": {
"type": "string",
"description": "Git commit author name for sync commits"
},
"email": {
"type": "string",
"description": "Git commit author email"
},
"trailer": {
"type": "string",
"description": "Git trailer key for loop prevention"
}
}
}
}
}