Files
2025-11-29 18:14:39 +08:00

352 lines
8.1 KiB
Markdown

---
description: Create pull request with automatic Linear integration
category: version-control-git
tools: Bash(linearis *), Bash(git *), Bash(gh *), Read, Task
model: inherit
version: 1.0.0
---
# Create Pull Request
Orchestrates the complete PR creation flow: commit → rebase → push → create → describe → link Linear
ticket.
## Prerequisites
Before executing, verify required tools are installed:
```bash
if [[ -f "${CLAUDE_PLUGIN_ROOT}/scripts/check-prerequisites.sh" ]]; then
"${CLAUDE_PLUGIN_ROOT}/scripts/check-prerequisites.sh" || exit 1
fi
```
## Configuration
Read team configuration from `.claude/config.json`:
```bash
CONFIG_FILE=".claude/config.json"
TEAM_KEY=$(jq -r '.catalyst.linear.teamKey // "PROJ"' "$CONFIG_FILE")
```
## Process:
### 1. Check for uncommitted changes
```bash
git status --porcelain
```
If there are uncommitted changes:
- Offer to commit: "You have uncommitted changes. Create commits now? [Y/n]"
- If yes: internally call `/catalyst-dev:commit` workflow
- If no: proceed (user may want to commit manually later)
### 2. Verify not on main/master branch
```bash
branch=$(git branch --show-current)
```
If on `main` or `master`:
- Error: "Cannot create PR from main branch. Create a feature branch first."
- Exit
### 3. Detect base branch
```bash
# Check which exists
if git show-ref --verify --quiet refs/heads/main; then
base="main"
elif git show-ref --verify --quiet refs/heads/master; then
base="master"
else
base=$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')
fi
```
### 4. Check if branch is up-to-date with base
```bash
# Fetch latest
git fetch origin $base
# Check if behind
if git log HEAD..origin/$base --oneline | grep -q .; then
echo "Branch is behind $base"
fi
```
If behind:
- Auto-rebase: `git rebase origin/$base`
- If conflicts:
- Show conflicting files
- Error: "Rebase conflicts detected. Resolve conflicts and run /catalyst-dev:create_pr again."
- Exit
### 5. Check for existing PR
```bash
gh pr view --json number,url,title,state 2>/dev/null
```
If PR exists:
- Show: "PR #{number} already exists: {title}\n{url}"
- Ask: "What would you like to do?\n [D] Describe/update this PR\n [S] Skip (do nothing)\n [A]
Abort"
- If D: call `/catalyst-dev:describe_pr` and exit
- If S: exit with success message
- If A: exit
- **This is the ONLY interactive prompt in the happy path**
### 6. Extract ticket from branch name
```bash
branch=$(git branch --show-current)
# Extract pattern: PREFIX-NUMBER using configured team key
if [[ "$branch" =~ ($TEAM_KEY-[0-9]+) ]]; then
ticket="${BASH_REMATCH[1]}" # e.g., RCW-13
fi
```
### 7. Generate PR title from branch and ticket
```bash
# Branch format examples:
# - RCW-13-implement-pr-lifecycle → "RCW-13: implement pr lifecycle"
# - feature-add-validation → "add validation"
# Extract description from branch name
if [[ "$ticket" ]]; then
# Remove ticket prefix from branch
desc=$(echo "$branch" | sed "s/^$ticket-//")
# Convert kebab-case to spaces
desc=$(echo "$desc" | tr '-' ' ')
# Capitalize first word
desc="$(tr '[:lower:]' '[:upper:]' <<< ${desc:0:1})${desc:1}"
title="$ticket: $desc"
else
# No ticket in branch
desc=$(echo "$branch" | tr '-' ' ')
desc="$(tr '[:lower:]' '[:upper:]' <<< ${desc:0:1})${desc:1}"
title="$desc"
fi
```
### 8. Push branch
```bash
# Check if branch has upstream
if ! git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null; then
# No upstream, push with -u
git push -u origin HEAD
else
# Has upstream, check if up-to-date
git push
fi
```
### 9. Create PR
**CRITICAL: NO CLAUDE ATTRIBUTION**
DO NOT add any of the following to the PR:
- ❌ "Generated with Claude Code" or similar messages
- ❌ "Co-Authored-By: Claude" lines
- ❌ Any reference to AI assistance
- ❌ Links to Claude Code or Anthropic
The PR should be authored solely by the user (git author). Keep the description clean and professional.
```bash
# Minimal initial body (NO CLAUDE ATTRIBUTION)
body="Automated PR creation. Comprehensive description generating..."
# If ticket exists, add reference
if [[ "$ticket" ]]; then
body="$body\n\nRefs: $ticket"
fi
# Create PR (author will be the git user)
gh pr create --title "$title" --body "$body" --base "$base"
```
Capture PR number and URL from output.
### Track in Workflow Context
After creating the PR, add it to workflow context:
```bash
if [[ -f "${CLAUDE_PLUGIN_ROOT}/scripts/workflow-context.sh" ]]; then
"${CLAUDE_PLUGIN_ROOT}/scripts/workflow-context.sh" add prs "$PR_URL" "${TICKET_ID:-null}"
fi
```
### 10. Auto-call /catalyst-dev:describe_pr
Immediately call `/catalyst-dev:describe_pr` with the PR number to:
- Generate comprehensive description
- Run verification checks
- Update PR title (refined from code analysis)
- Save to thoughts/
- Update Linear ticket
### 11. Update Linear ticket (if ticket found)
If ticket was extracted from branch:
```bash
# Verify linearis is available
if ! command -v linearis &> /dev/null; then
echo "⚠️ Linearis CLI not found - skipping Linear ticket update"
echo "Install: npm install -g --install-links ryanrozich/linearis#feat/cycles-cli"
else
# Update ticket state to "In Review"
linearis issues update "$ticket" --state "In Review" --assignee "@me"
# Add comment with PR link
linearis comments create "$ticket" \
--body "PR created and ready for review!\n\n**PR**: $prUrl\n\nDescription has been auto-generated with verification checks."
fi
```
### 12. Report success
```
✅ Pull request created successfully!
**PR**: #{number} - {title}
**URL**: {url}
**Base**: {base_branch}
**Ticket**: {ticket} (moved to "In Review")
Description has been generated and verification checks have been run.
Review the PR on GitHub!
```
## Error Handling
**On main/master branch:**
```
❌ Cannot create PR from main branch.
Create a feature branch first:
git checkout -b TICKET-123-feature-name
```
**Rebase conflicts:**
```
❌ Rebase conflicts detected
Conflicting files:
- src/file1.ts
- src/file2.ts
Resolve conflicts and run:
git add <resolved-files>
git rebase --continue
/catalyst-dev:create_pr
```
**GitHub CLI not configured:**
```
❌ GitHub CLI not configured
Run: gh auth login
Then: gh repo set-default
```
**Linearis CLI not found:**
```
⚠️ Linearis CLI not found
PR created successfully, but Linear ticket not updated.
Install Linearis:
npm install -g --install-links ryanrozich/linearis#feat/cycles-cli
Configure:
export LINEAR_API_TOKEN=your_token
```
**Linear ticket not found:**
```
⚠️ Could not find Linear ticket for {ticket}
PR created successfully, but ticket not updated.
Update manually or check ticket ID.
```
## Configuration
Uses `.claude/config.json`:
```json
{
"catalyst": {
"project": {
"ticketPrefix": "RCW"
},
"linear": {
"teamKey": "RCW",
"inReviewStatusName": "In Review"
}
}
}
```
## Examples
**Branch: `RCW-13-implement-pr-lifecycle`**
```
Extracting ticket: RCW-13
Generated title: "RCW-13: Implement pr lifecycle"
Creating PR...
✅ PR #2 created
Calling /catalyst-dev:describe_pr to generate description...
Updating Linear ticket RCW-13 → In Review
✅ Complete!
```
**Branch: `feature-add-validation` (no ticket)**
```
No ticket found in branch name
Generated title: "Feature add validation"
Creating PR...
✅ PR #3 created
Calling /catalyst-dev:describe_pr...
⚠️ No Linear ticket to update
✅ Complete!
```
## Integration with Other Commands
- **Calls `/catalyst-dev:commit`** - if uncommitted changes (optional)
- **Calls `/catalyst-dev:describe_pr`** - always, to generate comprehensive description
- **Sets up for `/catalyst-dev:merge_pr`** - PR is now ready for review and eventual merge
## Remember:
- **Minimize prompts** - only ask when PR already exists
- **Auto-rebase** - keep branch up-to-date with base
- **Auto-link Linear** - extract ticket from branch, update status with Linearis CLI
- **Auto-describe** - comprehensive description generated immediately
- **Fail fast** - stop on conflicts or errors with clear messages
- **Graceful degradation** - If Linearis not installed, warn but continue