anthropics / anthropics/claude-code-action

feat: Implement idempotent branch operations to improve reliability

Open
#787 0 comments 0 reactions 0 assignees View on GitHub
enhancement feature-request p2
Dominant language
TypeScript
Stars
8.9k
Forks
2.1k
Avg merge
3d 9h
Merged PRs (30d)
10

Description

## Problem

When a GitHub Actions job fails and is retried, the current implementation creates a **new branch** because branch names include timestamps:

```
claude/issue-123-20250103-1430
claude/issue-123-20250103-1445 <- retry creates new branch
claude/issue-123-20250103-1500 <- another new branch
```

This causes:
1. **Branch sprawl** - Accumulation of orphan branches
2. **Lost work** - Previous progress not continued
3. **Confusion** - Multiple branches for same issue/PR

## Root Cause

The current approach uses unique timestamps to **avoid** conflicts rather than **solving** them. This is accidental complexity.

The fundamental question: **Why does the same issue/PR need multiple branches?**

In most cases, one issue = one Claude branch. Multiple triggers on the same issue should continue on the same branch, not create new ones.

## Proposed Solution

### 1. Simplified Branch Naming

**Before:**
```
{prefix}{entity_type}-{entity_number}-{timestamp}
Example: claude/issue-123-20250103-1430
```

**After:**
```
{prefix}{entity_type}-{entity_number}
Example: claude/issue-123
```

### 2. Idempotent Branch Creation (check-before-create)

```typescript
async function setupBranch(...): Promise {
const branchName = `${branchPrefix}${entityType}-${entityNumber}`;

const branchExists = await checkBranchExists(octokit, owner, repo, branchName);

if (branchExists) {
// Branch exists -> checkout and continue
execGit(["fetch", "origin", branchName]);
execGit(["checkout", branchName]);
} else {
// Branch doesn't exist -> create
execGit(["fetch", "origin", sourceBranch, "--depth=1"]);
execGit(["checkout", sourceBranch]);
execGit(["checkout", "-b", branchName]);
}

return { baseBranch: sourceBranch, claudeBranch: branchName, currentBranch: branchName };
}
```

### 3. Documentation for Concurrency Control

Users should configure workflow-level concurrency to prevent simultaneous executions:

```yaml
concurrency:
group: claude-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: false
```

## Files to Modify

| File | Change |
|------|--------|
| `src/github/operations/branch.ts` | Remove timestamp, add check-before-create |
| `src/mcp/github-file-ops-server.ts` | Idempotent handling for commit signing mode |
| `README.md` or `docs/` | Concurrency configuration docs |
| `test/branch.test.ts` | Add idempotency tests |

## Benefits

1. **Reliability** - Retries work correctly without creating duplicate branches
2. **Simplicity** - One branch per issue/PR, easy to understand
3. **No sprawl** - Eliminates accumulation of orphan branches

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.