- Add v1.1.0 and v1.2.0 changelog entries - Add exclude field to config reference and example config - Add ADRs documenting all major design decisions - Fix step numbering in reverse_sync() - Fix action.yml to copy VERSION file - Add dist/ and .env to .gitignore - Use refs/tags/ format for Nix flake tag refs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.2 KiB
ADR-002: State Storage on Orphan Git Branch
Status: Accepted Date: 2026-01
Context
Josh-sync needs persistent state to track what has already been synced (last-synced commit SHAs, timestamps, status). This prevents re-syncing unchanged content and enables incremental operation. The state must survive CI runner teardown — runners are ephemeral containers.
Alternatives considered
-
File in the repo: Commit a state JSON file to the monorepo. Every sync run creates a commit, polluting history. Race conditions when multiple sync jobs run concurrently.
-
External database/KV store: Redis, SQLite, or a cloud KV service. Adds an infrastructure dependency. Credentials and connectivity to manage.
-
CI artifacts/cache: Platform-specific (GitHub Actions cache, Gitea cache). Not portable across CI platforms. Expiry policies vary.
-
Orphan git branch: A branch with no parent relationship to the main history. Stores JSON files in a simple
<target>/<branch>.jsonlayout. Pushed to origin, so it survives runner teardown. No external dependencies — uses git itself.
Decision
Store sync state as JSON files on an orphan branch (josh-sync-state) in the monorepo.
Storage layout
origin/josh-sync-state/
<target>/<branch>.json # sync state per target/branch
<target>/onboard.json # onboard workflow state (v1.1+)
Implementation
read_state():git fetch origin josh-sync-state && git show origin/josh-sync-state:<key>.jsonwrite_state(): Usesgit worktreeto check out the orphan branch in a temp directory, writes JSON, commits, and pushes. This avoids touching the main working tree.
Consequences
Positive:
- Zero external dependencies — only git
- Portable across CI platforms (Gitea Actions, GitHub Actions, local)
- Human-readable JSON files — easy to inspect and debug
- Atomic updates via git commit + push
- Natural namespacing via directory structure
Negative:
- Concurrent writes can race (mitigated by concurrency groups in CI workflows)
git worktreeadds complexity to the write path- State branch appears in
git branch -aoutput (minor clutter) - Push failures on the state branch are non-fatal (logged as warning, sync still succeeds)