129 lines
4.1 KiB
Bash
Executable File
129 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
# Script to pull task documentation files from a GitHub issue to local task directory
|
|
# Usage: ./pull.sh <issue-url-or-number>
|
|
# Pulls SPEC.md, PLAN.md, TEST_PLAN.md, COMMIT_MESSAGE.md from issue comments
|
|
# Automatically creates directory as tasks/{issue-number}-{title-slug}
|
|
|
|
if [ $# -lt 1 ]; then
|
|
echo "Usage: $0 <issue-url-or-number>"
|
|
echo ""
|
|
echo "Arguments:"
|
|
echo " issue-url-or-number GitHub issue URL or issue number"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 188"
|
|
echo " $0 https://github.com/<github-user>/<repo-name>/issues/188"
|
|
echo ""
|
|
echo "The script will automatically create a directory named:"
|
|
echo " tasks/{issue-number}-{title-slug}"
|
|
exit 1
|
|
fi
|
|
|
|
ISSUE_INPUT="$1"
|
|
|
|
# Detect GitHub repository from git remote or environment
|
|
SCRIPT_DIR="$(dirname "$0")"
|
|
# shellcheck source=lib-repo-detect.sh
|
|
source "$SCRIPT_DIR/lib-repo-detect.sh"
|
|
|
|
# Normalize the issue URL/number
|
|
if [[ $ISSUE_INPUT =~ ^https?://github\.com/ ]]; then
|
|
ISSUE_URL="$ISSUE_INPUT"
|
|
else
|
|
# Need repo info for building URL from issue number
|
|
if ! detect_github_repo; then
|
|
exit 1
|
|
fi
|
|
ISSUE_URL="https://github.com/$REPO_OWNER/$REPO_NAME/issues/$ISSUE_INPUT"
|
|
fi
|
|
|
|
# Parse the URL to extract owner, repo, and issue number
|
|
if [[ $ISSUE_URL =~ github\.com/([^/]+)/([^/]+)/issues/([0-9]+) ]]; then
|
|
OWNER="${BASH_REMATCH[1]}"
|
|
REPO="${BASH_REMATCH[2]}"
|
|
ISSUE_NUM="${BASH_REMATCH[3]}"
|
|
else
|
|
echo "Error: Invalid GitHub issue URL"
|
|
echo "Expected format: https://github.com/owner/repo/issues/NUMBER"
|
|
exit 1
|
|
fi
|
|
|
|
REPO_FULL="$OWNER/$REPO"
|
|
|
|
# Fetch the issue title from GitHub
|
|
echo "📥 Fetching issue #$ISSUE_NUM from $REPO_FULL..."
|
|
ISSUE_TITLE=$(gh api repos/$REPO_FULL/issues/$ISSUE_NUM --jq '.title')
|
|
|
|
if [ -z "$ISSUE_TITLE" ]; then
|
|
echo "Error: Could not fetch issue title"
|
|
exit 1
|
|
fi
|
|
|
|
# Convert title to URL-safe slug
|
|
# - Convert to lowercase
|
|
# - Replace spaces and special characters with dashes
|
|
# - Remove consecutive dashes
|
|
# - Trim leading/trailing dashes
|
|
SLUG=$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//')
|
|
|
|
# Create task directory as tasks/{issue-number}-{slug}
|
|
TASK_DIR="tasks/$ISSUE_NUM-$SLUG"
|
|
mkdir -p "$TASK_DIR"
|
|
|
|
echo "📥 Pulling task files from GitHub issue #$ISSUE_NUM: \"$ISSUE_TITLE\""
|
|
echo "📁 Task directory: $TASK_DIR"
|
|
echo ""
|
|
|
|
# Function to pull a file from GitHub
|
|
pull_file() {
|
|
local file=$1
|
|
local marker=$2
|
|
local file_path="$TASK_DIR/$file"
|
|
|
|
echo "Pulling $file..."
|
|
|
|
# Fetch the comment with the matching marker and extract the content
|
|
# Use startswith to match the exact marker (not substrings like PLAN_MARKER vs TEST_PLAN_MARKER)
|
|
comment_body=$(gh api repos/$REPO_FULL/issues/$ISSUE_NUM/comments \
|
|
--jq ".[] | select(.body | startswith(\"<!-- $marker -->\")) | .body" 2>/dev/null || echo "")
|
|
|
|
if [ -z "$comment_body" ]; then
|
|
echo " ⏭️ Skipping $file (not found on issue)"
|
|
return
|
|
fi
|
|
|
|
# Extract the content between the markdown code fences
|
|
# Handle both plain markdown blocks and those wrapped in <details> tags
|
|
if echo "$comment_body" | grep -q '<details>'; then
|
|
# For content in <details>, extract from ```markdown to </details>, then remove first line and last 2 lines
|
|
extracted=$(echo "$comment_body" | sed -n '/```markdown/,/<\/details>/p' | sed '1d' | sed '$d' | sed '$d')
|
|
else
|
|
# For unwrapped content, extract between ```markdown and the LAST ``` (to handle nested code blocks)
|
|
# This is trickier - we need to find the matching closing fence
|
|
# For now, use a simple approach: extract from ```markdown to end, then find the last ``` and trim from there
|
|
extracted=$(echo "$comment_body" | awk '/```markdown/{flag=1; next} /^```$/ && flag{exit} flag')
|
|
fi
|
|
|
|
if [ -z "$extracted" ]; then
|
|
echo " ⚠️ Warning: Could not extract content from $file comment"
|
|
return
|
|
fi
|
|
|
|
# Write to file
|
|
echo "$extracted" > "$file_path"
|
|
echo " ✓ Pulled to $file"
|
|
}
|
|
|
|
# Pull all four files
|
|
pull_file "SPEC.md" "SPEC_MARKER"
|
|
pull_file "PLAN.md" "PLAN_MARKER"
|
|
pull_file "TEST_PLAN.md" "TEST_PLAN_MARKER"
|
|
pull_file "COMMIT_MESSAGE.md" "COMMIT_MESSAGE_MARKER"
|
|
|
|
echo ""
|
|
echo "✅ Pull complete!"
|
|
echo "Task directory: $TASK_DIR"
|