352 lines
8.1 KiB
Markdown
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
|