Each task includes: - Scope: what to build - Implementation: code sketches + details - Verification: concrete test criteria - Done criteria: acceptance checklist
2.5 KiB
2.5 KiB
T0.3: Git & Locking
Scope
Implement action/git.go + internal/lock/flock.go for repo cloning, worktree management, and squash-merge.
Implementation
File: internal/lock/flock.go
package lock
// Acquire advisory file lock (blocking)
func Acquire(path string) error
// Release advisory file lock
func Release(path string) error
File: action/git.go
type CloneRepoInput struct {
RemoteURL string
TargetRepoPath string
}
func CloneRepoActivity(ctx context.Context, in CloneRepoInput) error
// If $TargetRepoPath/.git exists: git -C $TargetRepoPath fetch origin
// Else: git clone $RemoteURL $TargetRepoPath
type GitWorktreeAddInput struct {
RepoPath string
TaskID string
}
func GitWorktreeAddActivity(ctx context.Context, in GitWorktreeAddInput) (string, error)
// Guarded by orchestrator.lock
// git worktree add -b task/<TaskID> ../worktrees/<id> origin/main
// Return worktree path
type GitCommitInput struct {
WorktreePath string
Message string
}
func GitCommitActivity(ctx context.Context, in GitCommitInput) error
// No lock needed; safe within isolated worktree
// git -C $WorktreePath add -A
// git -C $WorktreePath commit -m "$Message"
type GitPushInput struct {
RepoPath string
}
func GitPushActivity(ctx context.Context, in GitPushInput) error
// Guarded by orchestrator.lock
// git -C $RepoPath push origin main
type GitSquashMergeInput struct {
RepoPath string
Branches []string // ["task/T0.1", "task/T0.2", ...]
Message string
}
func GitSquashMergeActivity(ctx context.Context, in GitSquashMergeInput) error
// Guarded by orchestrator.lock
// fetch origin main
// checkout main && pull --ff-only origin main
// for b in branches: merge --squash $b
// commit -m $Message
// push origin main
// for b in branches: worktree remove + branch -D
Verification
cd /Users/rockliang/workplace/Poimen/workflows
go test -v ./tests -run TestGit
# Test script: tests/git_test.go
Test cases:
- Clone into empty path → creates .git
- Clone into existing path → fetches instead of re-cloning
- Worktree add → returns valid path
- Commit in worktree → file changes staged
- Squash-merge → one commit on main, branches cleaned up
Done Criteria
go test ./tests -run TestGitpasses- Tested against local scratch git repo (not real remote)
- No lock deadlocks on concurrent calls
- Squash-merge produces exactly one commit