51 lines
2.2 KiB
Markdown
51 lines
2.2 KiB
Markdown
|
|
# 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)
|