Files
josh-sync/docs/adr/002-state-on-orphan-branch.md
Slim B 8ab07b83ab Update docs, changelog, examples, and add ADRs for v1.2
- 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>
2026-02-14 21:28:40 +03:00

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

  1. 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.

  2. External database/KV store: Redis, SQLite, or a cloud KV service. Adds an infrastructure dependency. Credentials and connectivity to manage.

  3. CI artifacts/cache: Platform-specific (GitHub Actions cache, Gitea cache). Not portable across CI platforms. Expiry policies vary.

  4. Orphan git branch: A branch with no parent relationship to the main history. Stores JSON files in a simple <target>/<branch>.json layout. 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>.json
  • write_state(): Uses git worktree to 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 worktree adds complexity to the write path
  • State branch appears in git branch -a output (minor clutter)
  • Push failures on the state branch are non-fatal (logged as warning, sync still succeeds)