---
name: step-pr
description: Create pull request with auto-detection
next_step: null
---

# Step: PR - Create Pull Request

## YOUR TASK:

Create a pull request with proper target, title, and description based on branch type.

**ULTRA THINK about PR requirements.**

---

## EXECUTION SEQUENCE:

### 1. Load Config and Detect Provider

```bash
# Load GitFlow config (sets GF_* variables)
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }

GIT_PROVIDER="$GF_PROVIDER"

# Extract Azure DevOps details if needed
if [ "$GIT_PROVIDER" = "azuredevops" ]; then
  [[ "$GF_REMOTE_URL" =~ dev\.azure\.com/([^/]+)/([^/]+)/_git/([^/]+) ]] && {
    AZURE_ORG="${BASH_REMATCH[1]}"
    AZURE_PROJECT="${BASH_REMATCH[2]}"
    AZURE_REPO="${BASH_REMATCH[3]}"
  }
fi
```

### 2. Determine PR Target

```bash
CURRENT=$(git rev-parse --abbrev-ref HEAD)
BRANCH_TYPE=$(echo $CURRENT | cut -d'/' -f1)

# CRITICAL: Verify config was loaded
if [ -z "$GF_MAIN_BRANCH" ] || [ -z "$GF_DEVELOP_BRANCH" ]; then
  echo "❌ GitFlow config not loaded properly"
  echo "→ Variables GF_MAIN_BRANCH and GF_DEVELOP_BRANCH are empty"
  exit 1
fi

# Determine target branch based on type (using config values)
case "$BRANCH_TYPE" in
  feature) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
  release) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
  hotfix)  TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
  *)       TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
esac

echo "✓ Branch: $CURRENT (type: $BRANCH_TYPE)"
echo "✓ Target: $TARGET_BRANCH"
```

### 3. Check Prerequisites

```bash
# Ensure branch is pushed
git fetch origin
REMOTE_EXISTS=$(git branch -r --list "origin/$CURRENT")
[ -z "$REMOTE_EXISTS" ] && {
  echo "Branch not pushed to remote. Pushing..."
  git push -u origin $CURRENT

  # CRITICAL: Verify push and update tracking refs
  git fetch origin $CURRENT:refs/remotes/origin/$CURRENT --force --quiet
  LOCAL_SHA=$(git rev-parse HEAD)
  REMOTE_SHA=$(git rev-parse origin/$CURRENT)
  if [ "$LOCAL_SHA" != "$REMOTE_SHA" ]; then
    echo "⚠️ Push verification failed - local/remote mismatch"
    STOP
  fi
  echo "✅ Push verified - branch in sync"
}

# Check for uncommitted changes
DIRTY=$(git status --porcelain | wc -l)
[ "$DIRTY" -gt 0 ] && {
  echo "⚠️ Uncommitted changes detected"
  echo "→ Run /gitflow commit first"
  STOP
}

# Check if PR already exists
EXISTING_PR=$(gh pr list --head "$CURRENT" --json number --jq '.[0].number' 2>/dev/null)
[ -n "$EXISTING_PR" ] && {
  echo "PR #$EXISTING_PR already exists for this branch"
  echo "→ View: gh pr view $EXISTING_PR"
  STOP
}
```

### 4. Run Pre-PR Checks

```bash
# Build check (multi-runtime detection)
echo "Running build check..."
if [ -f "*.sln" ] || ls *.csproj 2>/dev/null | head -1 > /dev/null; then
  dotnet build --no-restore 2>&1 || {
    echo "❌ .NET build failed. Fix before creating PR."
    STOP
  }
  # Migration check
  echo "Checking migrations..."
  dotnet ef migrations list 2>&1 || echo "No migrations or EF Core not configured"
elif [ -f "package.json" ]; then
  npm run build 2>&1 || {
    echo "❌ npm build failed. Fix before creating PR."
    STOP
  }
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
  echo "Python project detected — skipping build check"
else
  echo "⚠️ No known build system detected — skipping build check"
fi
```

### 5. Generate PR Content

**Title:**
```bash
BRANCH_NAME=$(echo $CURRENT | sed 's/.*\///')
BRANCH_TYPE=$(echo $CURRENT | cut -d'/' -f1)

case "$BRANCH_TYPE" in
  feature) TITLE="feat: $BRANCH_NAME" ;;
  hotfix)  TITLE="fix: $BRANCH_NAME" ;;
  release) TITLE="release: v$GF_VERSION" ;;
esac
```

**Body:**
```markdown
## Summary

{Auto-generated from commit messages}

## Changes

{List of files changed with categories}

## Testing

- [ ] Build passes
- [ ] Unit tests pass
- [ ] Manual testing completed

## EF Core Migrations

{Migration status: None | Added | Modified}

---

🤖 Generated with [Claude Code](https://claude.ai/code)
```

### 6. Create Pull Request

**GitHub:**
```bash
gh pr create \
  --title "$TITLE" \
  --body "$(cat <<'EOF'
{PR_BODY}
EOF
)" \
  --base "$TARGET_BRANCH" \
  --head "$CURRENT"

PR_URL=$(gh pr view --json url --jq '.url')
PR_NUMBER=$(gh pr view --json number --jq '.number')
```

**Azure DevOps:**
```bash
az repos pr create \
  --title "$TITLE" \
  --description "{PR_BODY}" \
  --source-branch "$CURRENT" \
  --target-branch "$TARGET_BRANCH" \
  --repository "$AZURE_REPO" \
  --project "$AZURE_PROJECT" \
  --org "https://dev.azure.com/$AZURE_ORG"

PR_ID=$(az repos pr list --source-branch "$CURRENT" --query "[0].pullRequestId" -o tsv)
```

### 7. Add Labels (GitHub)

```bash
if [ "$GIT_PROVIDER" = "github" ]; then
  case "$BRANCH_TYPE" in
    feature) gh pr edit $PR_NUMBER --add-label "enhancement" ;;
    hotfix)  gh pr edit $PR_NUMBER --add-label "bug,priority" ;;
    release) gh pr edit $PR_NUMBER --add-label "release" ;;
  esac
fi
```

### 8. Store PR Info

```bash
# Persist PR info for merge step (uses config path for portability)
CONFIG_DIR=$(dirname "$GF_CONFIG_FILE")
cat > "$CONFIG_DIR/cache/pr-state.json" << EOF
{
  "pr_number": "$PR_NUMBER",
  "pr_url": "$PR_URL",
  "source_branch": "$CURRENT",
  "target_branch": "$TARGET_BRANCH",
  "git_provider": "$GIT_PROVIDER",
  "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
echo "✓ PR state saved to $CONFIG_DIR/cache/pr-state.json"
```

### 9. Summary

```
╔══════════════════════════════════════════════════════════════════╗
║                    PULL REQUEST CREATED                           ║
╠══════════════════════════════════════════════════════════════════╣
║  PR:     #{PR_NUMBER}                                             ║
║  Title:  {TITLE}                                                  ║
║  URL:    {PR_URL}                                                 ║
╠══════════════════════════════════════════════════════════════════╣
║  Source: {CURRENT}                                                ║
║  Target: {TARGET_BRANCH}                                          ║
╠══════════════════════════════════════════════════════════════════╣
║  Checks:                                                          ║
║  - Build: ✅                                                      ║
║  - Migrations: {status}                                           ║
╠══════════════════════════════════════════════════════════════════╣
║  NEXT STEPS:                                                      ║
║  1. Wait for CI checks                                            ║
║  2. Request review                                                ║
║  3. After approval: /gitflow merge                                ║
╚══════════════════════════════════════════════════════════════════╝
```

---

## ERROR HANDLING:

| Error | Solution |
|-------|----------|
| Branch not pushed | Auto-push before PR |
| PR already exists | Show existing PR |
| Build fails | Fix and re-run |
| No git provider | Manual PR creation |

---

## SUCCESS CRITERIA:

- PR created with proper target
- Title and body generated
- Labels added (if GitHub)
- PR number stored for merge step

## NEXT STEP:

Wait for review, then `/gitflow merge`.
