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>
This commit is contained in:
52
docs/adr/005-git-trailer-loop-prevention.md
Normal file
52
docs/adr/005-git-trailer-loop-prevention.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# ADR-005: Git Trailer for Loop Prevention
|
||||
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-01
|
||||
|
||||
## Context
|
||||
|
||||
Bidirectional sync creates an infinite loop risk: forward sync pushes commit A to the subrepo, reverse sync sees commit A as "new" and creates a PR back to the monorepo, forward sync sees the merged PR as "new" and pushes again, etc.
|
||||
|
||||
### Alternatives considered
|
||||
|
||||
1. **SHA tracking only**: Compare SHAs to skip already-synced content. Breaks when josh-proxy rewrites SHAs (which it always does for filtered views). The monorepo commit SHA and the filtered/subrepo commit SHA are never the same.
|
||||
|
||||
2. **Commit message prefix**: Add `[sync]` to bot commit messages. Fragile — humans might use the same prefix. Requires string matching on message content.
|
||||
|
||||
3. **Git trailer**: A structured key-value pair in the commit message body (after a blank line), following the `git interpret-trailers` convention. Format: `Key: value`. Machine-parseable, unlikely to be used by humans, and supported by `git log --grep`.
|
||||
|
||||
## Decision
|
||||
|
||||
All bot commits include a git trailer with a configurable key (default: `Josh-Sync-Origin`). Both sync directions filter out commits containing this trailer.
|
||||
|
||||
### Format
|
||||
|
||||
```
|
||||
Sync from monorepo 2026-02-12T10:30:00Z
|
||||
|
||||
Josh-Sync-Origin: forward/main/2026-02-12T10:30:00Z
|
||||
```
|
||||
|
||||
The trailer value encodes: direction, branch, and timestamp. This aids debugging but is not parsed by the loop filter — only the trailer key presence matters.
|
||||
|
||||
### Filtering
|
||||
|
||||
- **Reverse sync**: `git log --invert-grep --grep="^${BOT_TRAILER}:"` excludes all commits with the trailer
|
||||
- **CI loop guard**: The composite action checks if HEAD commit has the trailer before running sync at all
|
||||
|
||||
### Configuration
|
||||
|
||||
The trailer key is set in `.josh-sync.yml` under `bot.trailer`. This allows multiple josh-sync instances (with different bots) to operate on the same repos without interfering.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:**
|
||||
- Reliable loop prevention — trailer is part of the immutable commit object
|
||||
- Configurable key avoids conflicts between multiple sync bots
|
||||
- Human-readable — `git log` shows the trailer in commit messages
|
||||
- CI loop guard prevents unnecessary sync runs entirely
|
||||
|
||||
**Negative:**
|
||||
- Commits with manually-added trailers matching the key would be incorrectly filtered
|
||||
- Trailer must be in the commit body (after blank line), not the subject line
|
||||
- Squash-and-merge on PRs may lose the trailer if the platform doesn't preserve commit message body
|
||||
Reference in New Issue
Block a user