382 lines
10 KiB
Markdown
382 lines
10 KiB
Markdown
---
|
|
name: gh-item-add
|
|
description: Add issues, PRs, or draft items to projects with field assignment
|
|
tools: Bash, AskUserQuestion, TodoWrite
|
|
model: inherit
|
|
---
|
|
|
|
# Add Item to GitHub Project
|
|
|
|
This command guides you through adding items to GitHub Projects with proper field configuration.
|
|
|
|
## Instructions
|
|
|
|
### Step 1: Identify Target Project
|
|
|
|
Ask the user which project to add items to:
|
|
|
|
```bash
|
|
# List available projects using Python for safe JSON parsing
|
|
gh project list --owner "@me" --format json | python3 -c "
|
|
import json, sys
|
|
projects = json.load(sys.stdin)
|
|
for p in projects:
|
|
print(f\"#{p.get('number')} - {p.get('title')}\")
|
|
"
|
|
|
|
# For organization
|
|
gh project list --owner "org-name" --format json | python3 -c "
|
|
import json, sys
|
|
projects = json.load(sys.stdin)
|
|
for p in projects:
|
|
print(f\"#{p.get('number')} - {p.get('title')}\")
|
|
"
|
|
```
|
|
|
|
Get the project ID:
|
|
```bash
|
|
PROJECT_ID=$(gh project list --owner "@me" --format json | python3 -c "
|
|
import json, sys
|
|
projects = json.load(sys.stdin)
|
|
target_number = <number> # Replace with actual number
|
|
for p in projects:
|
|
if p.get('number') == target_number:
|
|
print(p.get('id', ''))
|
|
break
|
|
")
|
|
```
|
|
|
|
### Step 2: Determine Item Type
|
|
|
|
Ask the user what type of item to add:
|
|
|
|
1. **Existing Issue**: Add issue from this or another repository
|
|
2. **Existing PR**: Add pull request from this or another repository
|
|
3. **Draft Item**: Create new draft item (no issue created)
|
|
|
|
### Step 3A: Add Existing Issue or PR
|
|
|
|
If adding existing issue/PR:
|
|
|
|
1. **Get the URL or number**:
|
|
- Ask user for issue/PR number or full URL
|
|
- If just number provided, construct URL: `https://github.com/<owner>/<repo>/issues/<number>`
|
|
|
|
2. **Add to project**:
|
|
```bash
|
|
gh project item-add <project-number> --owner "<owner>" --url <issue-or-pr-url>
|
|
```
|
|
|
|
3. **Capture item ID** from output or query:
|
|
```bash
|
|
ITEM_ID=$(gh project item-list <project-number> --owner "@me" --format json --limit 100 | python3 -c "
|
|
import json, sys
|
|
data = json.load(sys.stdin)
|
|
target_url = '<url>' # Replace with actual URL
|
|
for item in data.get('items', []):
|
|
if item.get('content', {}).get('url') == target_url:
|
|
print(item.get('id', ''))
|
|
break
|
|
")
|
|
```
|
|
|
|
### Step 3B: Create Draft Item
|
|
|
|
If creating draft item:
|
|
|
|
1. **Get title and body**:
|
|
- Ask user for item title (required)
|
|
- Ask user for item description/body (optional)
|
|
|
|
2. **Create draft**:
|
|
```bash
|
|
DRAFT_RESPONSE=$(gh project item-create <project-number> --owner "@me" \
|
|
--title "<title>" \
|
|
--body "<body>" \
|
|
--format json)
|
|
|
|
ITEM_ID=$(echo "$DRAFT_RESPONSE" | python3 -c "import json, sys; print(json.load(sys.stdin).get('id', ''))")
|
|
```
|
|
|
|
3. **Note**: Draft items can be converted to issues later when ready
|
|
|
|
### Step 4: Get Project Fields
|
|
|
|
Fetch available fields for the project:
|
|
|
|
```bash
|
|
FIELDS=$(gh project field-list <project-number> --owner "@me" --format json)
|
|
|
|
# Show fields to user using Python
|
|
echo "$FIELDS" | python3 -c "
|
|
import json, sys
|
|
fields = json.load(sys.stdin)
|
|
for field in fields:
|
|
print(f\"- {field.get('name')} ({field.get('dataType')})\")
|
|
"
|
|
```
|
|
|
|
### Step 5: Set Initial Field Values
|
|
|
|
Ask user which fields to set initially (optional but recommended):
|
|
|
|
#### Set Status
|
|
```bash
|
|
# Get Status field ID and options using Python
|
|
echo "$FIELDS" > /tmp/gh_fields.json
|
|
|
|
STATUS_FIELD=$(python3 -c "
|
|
import json
|
|
with open('/tmp/gh_fields.json') as f:
|
|
fields = json.load(f)
|
|
for field in fields:
|
|
if field.get('name') == 'Status':
|
|
print(field.get('id', ''))
|
|
break
|
|
")
|
|
|
|
# Show options to user
|
|
python3 -c "
|
|
import json
|
|
with open('/tmp/gh_fields.json') as f:
|
|
fields = json.load(f)
|
|
for field in fields:
|
|
if field.get('name') == 'Status':
|
|
for option in field.get('options', []):
|
|
print(f\"{option.get('name')}: {option.get('id')}\")
|
|
break
|
|
"
|
|
|
|
# Then update (after user selects option):
|
|
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
|
|
--field-id $STATUS_FIELD --single-select-option-id <option-id>
|
|
```
|
|
|
|
#### Set Priority
|
|
```bash
|
|
PRIORITY_FIELD=$(python3 -c "
|
|
import json
|
|
with open('/tmp/gh_fields.json') as f:
|
|
fields = json.load(f)
|
|
for field in fields:
|
|
if field.get('name') == 'Priority':
|
|
print(field.get('id', ''))
|
|
break
|
|
")
|
|
|
|
# Show options
|
|
python3 -c "
|
|
import json
|
|
with open('/tmp/gh_fields.json') as f:
|
|
fields = json.load(f)
|
|
for field in fields:
|
|
if field.get('name') == 'Priority':
|
|
for option in field.get('options', []):
|
|
print(f\"{option.get('name')}: {option.get('id')}\")
|
|
break
|
|
"
|
|
|
|
# Update after selection
|
|
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
|
|
--field-id $PRIORITY_FIELD --single-select-option-id <option-id>
|
|
```
|
|
|
|
#### Set Other Fields (as applicable)
|
|
|
|
**Number field** (e.g., Story Points):
|
|
```bash
|
|
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
|
|
--field-id <field-id> --number <value>
|
|
```
|
|
|
|
**Date field** (e.g., Due Date):
|
|
```bash
|
|
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
|
|
--field-id <field-id> --date "YYYY-MM-DD"
|
|
```
|
|
|
|
**Text field** (e.g., Owner):
|
|
```bash
|
|
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
|
|
--field-id <field-id> --text "<value>"
|
|
```
|
|
|
|
**Iteration field** (e.g., Sprint):
|
|
```bash
|
|
# Get iteration ID (complex, may need GraphQL)
|
|
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
|
|
--field-id <field-id> --iteration-id <iteration-id>
|
|
```
|
|
|
|
### Step 6: Verify Addition
|
|
|
|
Confirm the item was added successfully:
|
|
|
|
```bash
|
|
# View the item in the project using Python
|
|
gh project item-list <project-number> --owner "@me" --format json --limit 100 | python3 -c "
|
|
import json, sys
|
|
data = json.load(sys.stdin)
|
|
target_id = '$ITEM_ID'
|
|
|
|
for item in data.get('items', []):
|
|
if item.get('id') == target_id:
|
|
content = item.get('content', {})
|
|
result = {
|
|
'title': content.get('title'),
|
|
'type': content.get('type'),
|
|
'url': content.get('url'),
|
|
'fieldValues': item.get('fieldValues', [])
|
|
}
|
|
print(json.dumps(result, indent=2))
|
|
break
|
|
"
|
|
```
|
|
|
|
### Step 7: Provide Summary
|
|
|
|
Generate a clear summary for the user:
|
|
|
|
```markdown
|
|
## Item Added Successfully!
|
|
|
|
### Item Details
|
|
- **Title**: [Item Title]
|
|
- **Type**: [Issue/PR/Draft]
|
|
- **URL**: [URL if applicable]
|
|
- **Added to**: [Project Name] (#[Project Number])
|
|
|
|
### Initial Field Values
|
|
- Status: [Value]
|
|
- Priority: [Value]
|
|
- [Other fields set...]
|
|
|
|
### Next Steps
|
|
|
|
1. **View in Project**: [Project URL]
|
|
2. **Update Additional Fields**: Use project UI or:
|
|
- Set iteration/sprint
|
|
- Add estimation (story points)
|
|
- Assign team member
|
|
3. **Start Work**: Move to "In Progress" when ready
|
|
4. **Link to PR**: When you create a PR for this issue
|
|
|
|
### Quick Commands
|
|
- View project: `/gh-project-view`
|
|
- Update fields: Use project-manager agent
|
|
- View item details: `gh issue view <number>` or `gh pr view <number>`
|
|
```
|
|
|
|
## Batch Adding Items
|
|
|
|
If user wants to add multiple items:
|
|
|
|
1. **Get list of items to add**:
|
|
- From issue search: `gh issue list --repo owner/repo --label feature --limit 20`
|
|
- From PR list: `gh pr list --repo owner/repo --limit 20`
|
|
- From user input: Array of issue numbers
|
|
|
|
2. **Loop through items**:
|
|
```bash
|
|
for ISSUE_NUM in $ISSUES; do
|
|
ISSUE_URL="https://github.com/<owner>/<repo>/issues/$ISSUE_NUM"
|
|
gh project item-add <project-number> --owner "@me" --url $ISSUE_URL
|
|
echo "Added issue #$ISSUE_NUM"
|
|
done
|
|
```
|
|
|
|
3. **Set common fields** (if requested):
|
|
- Get all newly added item IDs
|
|
- Apply same field values to all
|
|
- Report batch results
|
|
|
|
## Smart Field Assignment
|
|
|
|
Suggest field values based on context:
|
|
|
|
### Auto-Priority from Issue Labels
|
|
```bash
|
|
# If issue has 'critical' or 'blocking' label → P0
|
|
# If issue has 'bug' or 'urgent' label → P1
|
|
# If issue has 'enhancement' label → P2
|
|
# Default → P3
|
|
|
|
LABELS=$(gh issue view <number> --json labels --jq '.labels[].name')
|
|
if echo $LABELS | grep -q "critical\|blocking"; then
|
|
SUGGESTED_PRIORITY="P0"
|
|
elif echo $LABELS | grep -q "bug\|urgent"; then
|
|
SUGGESTED_PRIORITY="P1"
|
|
else
|
|
SUGGESTED_PRIORITY="P2"
|
|
fi
|
|
```
|
|
|
|
### Auto-Status from Issue State
|
|
```bash
|
|
# If issue is OPEN → Backlog or Todo
|
|
# If PR is OPEN → In Review
|
|
# If closed → Done or Archived
|
|
|
|
ISSUE_STATE=$(gh issue view <number> --json state --jq '.state')
|
|
if [ "$ISSUE_STATE" = "OPEN" ]; then
|
|
SUGGESTED_STATUS="Backlog"
|
|
else
|
|
SUGGESTED_STATUS="Done"
|
|
fi
|
|
```
|
|
|
|
## Important Notes
|
|
|
|
- **Item IDs vs Issue Numbers**: Item IDs are project-specific identifiers, different from issue numbers
|
|
- **Field IDs**: Must fetch field IDs for each project, they're not universal
|
|
- **Option IDs**: Single-select fields require option IDs, not option names
|
|
- **Permissions**: Ensure 'project' scope is enabled: `gh auth status`
|
|
- **Rate Limits**: When batch adding, respect API rate limits (pause if needed)
|
|
|
|
## Definition of Done
|
|
|
|
- [ ] Target project identified
|
|
- [ ] Item type determined (issue/PR/draft)
|
|
- [ ] Item added to project successfully
|
|
- [ ] Item ID captured
|
|
- [ ] Initial field values set (at minimum: Status, Priority)
|
|
- [ ] Addition verified
|
|
- [ ] Comprehensive summary provided
|
|
- [ ] Next steps documented
|
|
|
|
## Error Handling
|
|
|
|
- If project not found: List available projects, let user choose
|
|
- If issue/PR not found: Verify URL/number, check repository access
|
|
- If item already in project: Report duplicate, ask if should update fields
|
|
- If field update fails: Verify field ID and option ID are correct
|
|
- If permission denied: Check project access and gh auth scopes
|
|
|
|
## Special Cases
|
|
|
|
### Converting Draft to Issue
|
|
|
|
When user is ready to convert draft to real issue:
|
|
|
|
```bash
|
|
# This requires GraphQL API call (gh CLI doesn't have direct command)
|
|
# Provide instructions for manual conversion via GitHub UI
|
|
# Or use gh api graphql with mutation
|
|
```
|
|
|
|
### Linking PR to Issue Item
|
|
|
|
When adding a PR that closes an issue already in the project:
|
|
- Note the relationship
|
|
- Suggest linking them in descriptions
|
|
- Consider setting up automation for status sync
|
|
|
|
### Cross-Repository Items
|
|
|
|
When adding items from different repositories:
|
|
- Verify project is linked to target repository: `gh project link`
|
|
- If not linked, link it first
|
|
- Then add items
|
|
|
|
Remember: Proper field assignment at addition time saves triage work later. Take the extra minute to set Status and Priority correctly from the start.
|