diff --git a/.claude/commands/create-pr.md b/.claude/commands/create-pr.md new file mode 100644 index 0000000..12d3d03 --- /dev/null +++ b/.claude/commands/create-pr.md @@ -0,0 +1,93 @@ +Create a GitHub pull request for the current branch, writing the title and description from the actual work done in this session — not reconstructed from the diff. + +## Why this command exists + +The previous flow outsourced PR-description authoring to a GitHub Action that only saw the diff and commit messages. It could not know _why_ the changes were made, so it frequently described things that weren't true. Those inaccurate descriptions then fed `@claude` reviews, compounding the bad information. This command fixes that at the root: **you author the description here, where the full context of what was done and why is available.** + +This is the RoboSystems Python client — a type-safe, async-ready Python SDK generated against the RoboSystems API. Tooling is driven by `just`, not npm. + +## Instructions + +### 1. Preflight + +Run these checks before touching anything: + +```bash +# Current and target branches +CURRENT=$(git branch --show-current) +TARGET=${1:-main} # override target via the first argument +``` + +- **Never PR from the default branch.** If `CURRENT` is `main` (or `master`/`staging`), stop and tell the user to switch to a feature branch first. +- **Source ≠ target.** If `CURRENT == TARGET`, stop. +- **Uncommitted changes.** Run `git status --porcelain`. If there are uncommitted/staged changes, surface them and ask whether to commit them (respecting the repo's commit rules — never on `main`, no `git add -A`, stage files by name) or proceed without them. The PR description must reflect committed state. +- **Existing PR.** Check `gh pr list --head "$CURRENT" --base "$TARGET" --json url,number`. If a PR already exists, do **not** create a duplicate — offer to update its title/body with `gh pr edit` instead. +- **Push the branch.** `gh pr create` requires the branch on the remote. Ensure it's pushed: `git push -u origin "$CURRENT"` (the user invoking `/create-pr` is the explicit, in-the-moment request that authorizes pushing _this feature branch_ — this is the one push allowed without a separate ask; never push `main`). + +### 2. Gather the real change context + +This is the whole point — ground the description in what actually happened: + +- **Primary source: this session.** Use what was actually changed and why from the conversation context. This is the information the old GHA workflow never had. +- **Corroborate against the branch:** + ```bash + git log --oneline "$TARGET".."$CURRENT" # commits on this branch + git diff --stat "$TARGET"..."$CURRENT" # files + churn + git diff "$TARGET"..."$CURRENT" # full diff — read it, don't guess + ``` +- **Hard rule — no confabulation.** Every claim in the description must be supported by the diff. If you didn't touch the auth client, don't write "auth improvements." If a behavior isn't in the diff, don't mention it. When the session context and the diff disagree, the diff wins and you investigate the discrepancy. +- **Generated code.** Much of `robosystems_client/` is generated from the OpenAPI spec via `just generate-sdk`. If a change is a regeneration, say so plainly rather than narrating individual model edits as if hand-written. + +### 3. Compose the PR + +- **Type** — derive from the branch prefix (`feature/` → feat, `bugfix/`/`fix/` → fix, `hotfix/` → fix, `chore/` → chore, `refactor/` → refactor, `release/` → release). Default to `feat` if unprefixed. +- **Title** — concise (~50–72 chars), conventional-commit style, e.g. `feat(clients): add streaming query helper`. Match the style in `git log`. +- **Body** — markdown, only sections that apply: + - **Summary** — 1–3 sentences: what this PR does and why. + - **Changes** — bullets grouped by area/file/module, describing real edits. + - **Testing** — state truthfully what was run. If `just test-all` (or a subset like `just test` / `just lint` / `just typecheck`) was run this session, say so and give the result. If nothing was run, say "Not run" — never claim passing tests that weren't executed. + - **Notes / Follow-ups** — optional: deferred items, risks, related issues, SDK-regeneration implications. +- **Attribution** — attribute to the user only. Do **not** add a "Generated with Claude Code" footer or a `Co-Authored-By: Claude` trailer (per `CLAUDE.local.md`). Include such a line only if the user explicitly asks. + +### 4. Create the PR + +Write the body to a temp file to avoid shell-escaping problems, then: + +```bash +gh pr create \ + --base "$TARGET" \ + --head "$CURRENT" \ + --title "" \ + --body-file /tmp/pr-body.md +``` + +Print the resulting PR URL. + +### 5. Optional Claude review + +Only if the user explicitly asks (e.g. passes `review` / `--review` in arguments), request a review: + +```bash +gh pr comment <number> --body "@claude please review this PR" +``` + +Otherwise leave it off — the description is now accurate, and the user can run `/pr-review` locally (full context) or `@claude` manually when ready. Do not request review by default. + +## Output + +After creating the PR, report: + +1. The PR URL. +2. A one-line summary of the title. +3. Target ← source branches. +4. Whether a Claude review was requested. + +## Arguments + +`$ARGUMENTS` may contain: + +- A target branch (default `main`). +- `review` / `--review` to auto-request a `@claude` review. +- Freeform guidance on what to emphasize in the description. + +$ARGUMENTS diff --git a/.github/workflows/create-pr.yml b/.github/workflows/create-pr.yml deleted file mode 100644 index 7f34fa8..0000000 --- a/.github/workflows/create-pr.yml +++ /dev/null @@ -1,387 +0,0 @@ -name: Create Claude PR - -on: - workflow_dispatch: - inputs: - source_branch: - description: "Source branch to create PR from (defaults to current branch)" - required: false - type: string - target_branch: - description: "Target branch to merge into" - required: true - type: choice - options: - - main - default: main - pr_type: - description: "Type of PR" - required: true - type: choice - options: - - release - - feature - - bugfix - - hotfix - default: release - claude_review: - description: "Request Claude review automatically" - required: false - type: boolean - default: true - -jobs: - create-pr: - runs-on: ubuntu-latest - timeout-minutes: 10 - env: - # ACTIONS_TOKEN (PAT) preferred - PRs created with github.token won't trigger CI workflows - GH_TOKEN: ${{ secrets.ACTIONS_TOKEN || github.token }} - steps: - - name: Check token configuration - run: | - if [ -z "${{ secrets.ACTIONS_TOKEN }}" ]; then - echo "::warning::ACTIONS_TOKEN not set - using github.token as fallback" - echo "" - echo "⚠️ PRs created with github.token have limitations:" - echo " - Won't trigger on:pull_request workflows (CI won't run automatically)" - echo " - May be blocked by branch protection rules" - echo "" - echo "To enable full functionality, set ACTIONS_TOKEN secret:" - echo " gh secret set ACTIONS_TOKEN" - else - echo "✅ Using ACTIONS_TOKEN for full PR functionality" - fi - - - name: Checkout - uses: actions/checkout@v4 - with: - # ACTIONS_TOKEN preferred for pushing to protected branches - token: ${{ secrets.ACTIONS_TOKEN || github.token }} - fetch-depth: 0 - - - name: Determine source branch - id: source-branch - run: | - if [ -n "${{ inputs.source_branch }}" ]; then - SOURCE_BRANCH="${{ inputs.source_branch }}" - echo "Using specified source branch: $SOURCE_BRANCH" - git checkout "$SOURCE_BRANCH" - else - SOURCE_BRANCH=$(git branch --show-current) - echo "Using current branch: $SOURCE_BRANCH" - fi - echo "source_branch=$SOURCE_BRANCH" >> $GITHUB_OUTPUT - - - name: Validate branches - id: validate - run: | - SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}" - TARGET_BRANCH="${{ inputs.target_branch }}" - - echo "Source branch: $SOURCE_BRANCH" - echo "Target branch: $TARGET_BRANCH" - - # Check if source branch exists - if ! git show-ref --verify --quiet refs/heads/$SOURCE_BRANCH && ! git show-ref --verify --quiet refs/remotes/origin/$SOURCE_BRANCH; then - echo "❌ Source branch $SOURCE_BRANCH does not exist" - exit 1 - fi - - # Check if target branch exists - if ! git show-ref --verify --quiet refs/heads/$TARGET_BRANCH && ! git show-ref --verify --quiet refs/remotes/origin/$TARGET_BRANCH; then - echo "❌ Target branch $TARGET_BRANCH does not exist" - exit 1 - fi - - # Check if branches are different - if [ "$SOURCE_BRANCH" = "$TARGET_BRANCH" ]; then - echo "❌ Source and target branches cannot be the same" - exit 1 - fi - - echo "✅ Branch validation passed" - - - name: Analyze changes with Claude - id: analyze - run: | - SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}" - TARGET_BRANCH="${{ inputs.target_branch }}" - PR_TYPE="${{ inputs.pr_type }}" - - # Get commit range for analysis - git fetch origin $TARGET_BRANCH - COMMIT_RANGE="origin/$TARGET_BRANCH...$SOURCE_BRANCH" - - # Get diff stats (limit output to prevent memory issues) - DIFF_STATS=$(git diff --stat --no-color $COMMIT_RANGE | head -50 | sed 's/`//g') # Limit to 50 lines - FILES_CHANGED=$(git diff --name-only $COMMIT_RANGE | wc -l) - COMMITS_COUNT=$(git rev-list --count $COMMIT_RANGE) - - # Get commit messages (limit to recent commits) - COMMIT_MESSAGES=$(git log --oneline --no-color $COMMIT_RANGE | head -20 | sed 's/`//g') # Limit to 20 commits - - # Get detailed changes (limit to prevent memory issues) - DETAILED_CHANGES=$(git diff $COMMIT_RANGE --name-status --no-color | head -100 | sed 's/`//g') # Limit to 100 files - - # Create analysis prompt for Claude - cat << 'EOF' > /tmp/pr_analysis_prompt.txt - I need you to analyze the following git changes and create a comprehensive PR title and description. - - **Context:** - - Source Branch: ${SOURCE_BRANCH} - - Target Branch: ${TARGET_BRANCH} - - PR Type: ${PR_TYPE} - - Files Changed: ${FILES_CHANGED} - - Commits: ${COMMITS_COUNT} - - **Commit Messages:** - ${COMMIT_MESSAGES} - - **Diff Statistics:** - ${DIFF_STATS} - - **Detailed Changes:** - ${DETAILED_CHANGES} - - Please provide: - 1. A concise, descriptive PR title (50-72 characters) - 2. A comprehensive PR description with: - - Summary of changes - - Key accomplishments - - Breaking changes (if any) - - Testing notes - - Infrastructure considerations (avoid mentioning specific script paths or commands) - - Format the response as: - TITLE: [your title here] - - DESCRIPTION: - [your description here] - EOF - - # Create the final prompt by writing directly to a file (avoiding envsubst issues) - cat > /tmp/pr_analysis_prompt_final.txt << PROMPT_EOF - I need you to analyze the following git changes and create a comprehensive PR title and description. - - **Context:** - - Source Branch: $SOURCE_BRANCH - - Target Branch: $TARGET_BRANCH - - PR Type: $PR_TYPE - - Files Changed: $FILES_CHANGED - - Commits: $COMMITS_COUNT - - **Commit Messages:** - $COMMIT_MESSAGES - - **Diff Statistics:** - $DIFF_STATS - - **Detailed Changes:** - $DETAILED_CHANGES - - Please provide: - 1. A concise, descriptive PR title (50-72 characters) - 2. A comprehensive PR description with: - - Summary of changes - - Key accomplishments - - Breaking changes (if any) - - Testing notes - - Infrastructure considerations (avoid mentioning specific script paths or commands) - - Format the response as: - TITLE: [your title here] - - DESCRIPTION: - [your description here] - PROMPT_EOF - mv /tmp/pr_analysis_prompt_final.txt /tmp/pr_analysis_prompt.txt - - echo "analysis_prompt_file=/tmp/pr_analysis_prompt.txt" >> $GITHUB_OUTPUT - echo "commit_range=$COMMIT_RANGE" >> $GITHUB_OUTPUT - echo "files_changed=$FILES_CHANGED" >> $GITHUB_OUTPUT - echo "commits_count=$COMMITS_COUNT" >> $GITHUB_OUTPUT - - - name: Call Claude API - id: claude - run: | - # Call Claude API with the analysis prompt - PROMPT=$(cat /tmp/pr_analysis_prompt.txt) - - # Create a proper JSON payload using jq to handle escaping - PAYLOAD=$(jq -n \ - --arg model "${{ vars.CLAUDE_MODEL || 'claude-sonnet-4-6' }}" \ - --arg content "$PROMPT" \ - '{ - "model": $model, - "max_tokens": 4000, - "messages": [ - { - "role": "user", - "content": $content - } - ] - }') - - # Retry logic with exponential backoff - MAX_RETRIES=3 - RETRY_COUNT=0 - RETRY_DELAY=5 - - while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - RESPONSE=$(curl -s -X POST "https://api.anthropic.com/v1/messages" \ - -H "Content-Type: application/json" \ - -H "x-api-key: ${{ secrets.ANTHROPIC_API_KEY }}" \ - -H "anthropic-version: 2023-06-01" \ - -d "$PAYLOAD") - - # Check for API errors - if echo "$RESPONSE" | jq -e '.error' > /dev/null; then - ERROR_TYPE=$(echo "$RESPONSE" | jq -r '.error.type // "unknown"') - ERROR_MSG=$(echo "$RESPONSE" | jq -r '.error.message // "Unknown error"') - - # Check if it's a rate limit or overload error - if [[ "$ERROR_TYPE" == "overloaded_error" ]] || [[ "$ERROR_TYPE" == "rate_limit_error" ]] || [[ "$ERROR_MSG" == *"Overloaded"* ]]; then - RETRY_COUNT=$((RETRY_COUNT + 1)) - if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then - echo "⚠️ Claude API overloaded (attempt $RETRY_COUNT/$MAX_RETRIES). Retrying in ${RETRY_DELAY}s..." - sleep $RETRY_DELAY - RETRY_DELAY=$((RETRY_DELAY * 2)) # Exponential backoff - continue - else - echo "❌ Claude API error after $MAX_RETRIES attempts: $ERROR_MSG" - echo "Using fallback PR description..." - # Set a fallback description - PR_TITLE="PR: ${{ steps.source-branch.outputs.source_branch }} → ${{ inputs.target_branch }}" - PR_DESCRIPTION="Automated PR from ${{ steps.source-branch.outputs.source_branch }} to ${{ inputs.target_branch }}"$'\n\n'"**Type:** ${{ inputs.pr_type }}"$'\n'"**Files Changed:** ${{ steps.analyze.outputs.files_changed }}"$'\n'"**Commits:** ${{ steps.analyze.outputs.commits_count }}"$'\n\n'"Please review the changes in the Files tab." - break - fi - else - echo "❌ Claude API error: $ERROR_MSG" - exit 1 - fi - else - # Success - break out of retry loop - break - fi - done - - # Only process Claude response if we didn't use fallback - if [ -z "$PR_TITLE" ]; then - # Check for successful response - if echo "$RESPONSE" | jq -e '.content[0].text' > /dev/null; then - # Extract title and description from Claude's response - CLAUDE_OUTPUT=$(echo "$RESPONSE" | jq -r '.content[0].text') - - # Parse the title and description - PR_TITLE=$(echo "$CLAUDE_OUTPUT" | grep "^TITLE:" | sed 's/^TITLE: //') - PR_DESCRIPTION=$(echo "$CLAUDE_OUTPUT" | sed -n '/^DESCRIPTION:/,$ p' | sed '1d') - - # Validate that Claude returned meaningful content - if [ -z "$PR_TITLE" ] || [ -z "$PR_DESCRIPTION" ]; then - echo "⚠️ Claude returned empty title or description, using fallback" - PR_TITLE="PR: ${{ steps.source-branch.outputs.source_branch }} → ${{ inputs.target_branch }}" - PR_DESCRIPTION="Automated PR from ${{ steps.source-branch.outputs.source_branch }} to ${{ inputs.target_branch }}" - PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"**Type:** ${{ inputs.pr_type }}" - PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n'"**Files Changed:** ${{ steps.analyze.outputs.files_changed }}" - PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n'"**Commits:** ${{ steps.analyze.outputs.commits_count }}" - PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"Please review the changes in the Files tab." - fi - else - echo "⚠️ Invalid Claude response format, using fallback" - PR_TITLE="PR: ${{ steps.source-branch.outputs.source_branch }} → ${{ inputs.target_branch }}" - PR_DESCRIPTION="Automated PR from ${{ steps.source-branch.outputs.source_branch }} to ${{ inputs.target_branch }}" - PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"**Type:** ${{ inputs.pr_type }}" - PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"Please review the changes in the Files tab." - fi - fi - - # Save to outputs (escape for JSON) - { - echo "pr_title<<EOF" - echo "$PR_TITLE" - echo "EOF" - } >> $GITHUB_OUTPUT - - { - echo "pr_description<<EOF" - echo "$PR_DESCRIPTION" - echo "EOF" - } >> $GITHUB_OUTPUT - - echo "✅ Claude analysis completed" - - - name: Create Pull Request - id: create-pr - env: - CLAUDE_PR_TITLE: ${{ steps.claude.outputs.pr_title }} - CLAUDE_PR_DESCRIPTION: ${{ steps.claude.outputs.pr_description }} - run: | - SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}" - TARGET_BRANCH="${{ inputs.target_branch }}" - - # Use environment variables to safely handle Claude's output - PR_TITLE="$CLAUDE_PR_TITLE" - PR_DESCRIPTION="$CLAUDE_PR_DESCRIPTION" - - # Check if PR already exists - EXISTING_PR=$(gh pr list --head "$SOURCE_BRANCH" --base "$TARGET_BRANCH" --json url --jq '.[0].url' 2>/dev/null || echo "") - - if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then - echo "✅ PR already exists: $EXISTING_PR" - echo "pr_url=$EXISTING_PR" >> $GITHUB_OUTPUT - PR_URL="$EXISTING_PR" - else - # Create PR description with Claude analysis + footer - cat > /tmp/pr_description.txt << EOF - $PR_DESCRIPTION - - --- - 🤖 Generated with [Claude Code](https://claude.ai/code) - - **Branch Info:** - - Source: \`$SOURCE_BRANCH\` - - Target: \`$TARGET_BRANCH\` - - Type: ${{ inputs.pr_type }} - - Co-Authored-By: Claude <noreply@anthropic.com> - EOF - - FINAL_PR_DESCRIPTION=$(cat /tmp/pr_description.txt) - - # Create the PR - PR_URL=$(gh pr create \ - --title "$PR_TITLE" \ - --body "$FINAL_PR_DESCRIPTION" \ - --base "$TARGET_BRANCH" \ - --head "$SOURCE_BRANCH") - - echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT - echo "✅ Pull Request created: $PR_URL" - fi - - - name: Request Claude review - if: ${{ inputs.claude_review }} - run: | - PR_NUMBER=$(echo "${{ steps.create-pr.outputs.pr_url }}" | sed 's/.*pull\///') - - gh pr comment "$PR_NUMBER" --body "@claude please review this PR" - echo "✅ Claude review requested" - - - name: Create summary - run: | - SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}" - TARGET_BRANCH="${{ inputs.target_branch }}" - PR_URL="${{ steps.create-pr.outputs.pr_url }}" - - echo "## 🚀 Claude-Powered PR Created" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**PR URL:** [$PR_URL]($PR_URL)" >> $GITHUB_STEP_SUMMARY - echo "**Source:** \`$SOURCE_BRANCH\`" >> $GITHUB_STEP_SUMMARY - echo "**Target:** \`$TARGET_BRANCH\`" >> $GITHUB_STEP_SUMMARY - echo "**Type:** ${{ inputs.pr_type }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### PR Details" >> $GITHUB_STEP_SUMMARY - echo "**Title:** ${{ steps.claude.outputs.pr_title }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**Commits:** ${{ steps.analyze.outputs.commit_range }}" >> $GITHUB_STEP_SUMMARY diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ce241c7..1ddfd14 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -73,12 +73,6 @@ "command": "just create-feature ${input:branchType} ${input:branchName} ${input:baseBranch} ${input:updateDependencies}", "problemMatcher": [] }, - { - "label": "Create PR", - "type": "shell", - "command": "just create-pr ${input:targetBranch} ${input:claudeReview}", - "problemMatcher": [] - }, { "label": "Create Release", "type": "shell", @@ -127,19 +121,6 @@ "default": "yes", "options": ["yes", "no"] }, - { - "id": "targetBranch", - "type": "promptString", - "description": "Choose target branch:", - "default": "main" - }, - { - "id": "claudeReview", - "type": "pickString", - "description": "Request Claude review automatically:", - "default": "true", - "options": ["true", "false"] - }, { "id": "apiUrl", "type": "promptString", diff --git a/bin/create-feature.sh b/bin/create-feature.sh index 1f62153..870c02e 100755 --- a/bin/create-feature.sh +++ b/bin/create-feature.sh @@ -93,7 +93,7 @@ echo "📝 Next steps:" echo " 1. Make your changes and commit them" echo " 2. Push your changes: git push" echo " 3. Create a PR: gh pr create --base $BASE_BRANCH --title \"Your PR title\" --body \"Your PR description\"" -echo " or use: just create-pr $BASE_BRANCH $BRANCH_TYPE" +echo " or in a Claude Code session: /create-pr" # Check if we had stashed changes and auto-apply them if git stash list | grep -q "Auto-stash before creating branch $FULL_BRANCH"; then diff --git a/bin/create-pr.sh b/bin/create-pr.sh deleted file mode 100755 index fb05aa4..0000000 --- a/bin/create-pr.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash -set -e - -# Create PR script using GitHub Actions -# Analyzes current branch changes and creates a comprehensive PR with Claude -# Usage: ./bin/tools/create-pr.sh [target_branch] [claude_review] - -# Default values -TARGET_BRANCH=${1:-main} -CLAUDE_REVIEW=${2:-true} - -# Get current branch -CURRENT_BRANCH=$(git branch --show-current) - -# Validate current branch is not target branch -if [ "$CURRENT_BRANCH" = "$TARGET_BRANCH" ]; then - echo "❌ Cannot create PR: you're currently on the target branch ($TARGET_BRANCH)" - echo "Switch to your feature/release branch first: git checkout <your-branch>" - exit 1 -fi - -# Validate target branch (only main is allowed as target) -if [[ "$TARGET_BRANCH" != "main" ]]; then - echo "❌ Invalid target branch: $TARGET_BRANCH. Only 'main' is allowed as target." - exit 1 -fi - -# Determine PR type from branch prefix -if [[ "$CURRENT_BRANCH" == release/* ]]; then - PR_TYPE="release" -elif [[ "$CURRENT_BRANCH" == feature/* ]]; then - PR_TYPE="feature" -elif [[ "$CURRENT_BRANCH" == bugfix/* ]]; then - PR_TYPE="bugfix" -elif [[ "$CURRENT_BRANCH" == hotfix/* ]]; then - PR_TYPE="hotfix" -else - # Default to feature for any other branch names - PR_TYPE="feature" - echo "⚠️ Could not determine PR type from branch name '$CURRENT_BRANCH', defaulting to 'feature'" -fi - -# Validate Claude review parameter -if [[ "$CLAUDE_REVIEW" != "true" && "$CLAUDE_REVIEW" != "false" ]]; then - echo "❌ Invalid claude_review value: $CLAUDE_REVIEW. Use 'true' or 'false'." - exit 1 -fi - -echo "🤖 Creating Claude-powered PR..." -echo "📋 Details:" -echo " Source Branch: $CURRENT_BRANCH" -echo " Target Branch: $TARGET_BRANCH" -echo " PR Type: $PR_TYPE" -echo " Claude Review: $CLAUDE_REVIEW" -echo "" - -# Check for uncommitted changes -if ! git diff --quiet || ! git diff --cached --quiet; then - echo "⚠️ You have uncommitted changes. Please commit or stash them first." - echo "" - echo "Uncommitted files:" - git status --porcelain - exit 1 -fi - -# Push current branch to remote if needed -echo "📤 Ensuring current branch is pushed to remote..." -if ! git show-ref --verify --quiet refs/remotes/origin/$CURRENT_BRANCH; then - echo "Branch $CURRENT_BRANCH doesn't exist on remote. Pushing..." - git push -u origin $CURRENT_BRANCH -else - echo "Pushing latest changes..." - git push origin $CURRENT_BRANCH -fi - -echo "" -echo "🚀 Triggering Claude analysis workflow..." - -# Trigger the GitHub Actions workflow -gh workflow run create-pr.yml \ - --field source_branch="$CURRENT_BRANCH" \ - --field target_branch="$TARGET_BRANCH" \ - --field pr_type="$PR_TYPE" \ - --field claude_review="$CLAUDE_REVIEW" - -echo "⏳ Waiting for Claude to analyze changes and create PR..." - -# Wait for workflow to complete and find the PR -MAX_ATTEMPTS=30 # 5 minutes with 10-second intervals -ATTEMPT=1 - -while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do - echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Checking for created PR..." - - # Check if the workflow run failed - LATEST_RUN_STATUS=$(gh run list --workflow=create-pr.yml --limit=1 --json status --jq '.[0].status' 2>/dev/null || echo "") - if [ "$LATEST_RUN_STATUS" = "failure" ] || [ "$LATEST_RUN_STATUS" = "cancelled" ]; then - echo "❌ GitHub Actions workflow failed or was cancelled" - echo "Check the workflow run details:" - echo " gh run list --workflow=create-pr.yml" - echo " gh run view --workflow=create-pr.yml" - echo "" - echo "You can create the PR manually:" - echo " gh pr create --base $TARGET_BRANCH --head $CURRENT_BRANCH" - exit 1 - fi - - # Check if PR exists from current branch to target - PR_URL=$(gh pr list --head "$CURRENT_BRANCH" --base "$TARGET_BRANCH" --json url --jq '.[0].url' 2>/dev/null || echo "") - - if [ -n "$PR_URL" ] && [ "$PR_URL" != "null" ]; then - echo "✅ PR created successfully!" - echo "🔗 PR URL: $PR_URL" - echo "" - echo "🎉 Claude has analyzed your changes and created a comprehensive PR" - echo "📝 Review the PR description and make any necessary adjustments" - - # Try to open PR in browser - if command -v open >/dev/null 2>&1; then - echo "🌐 Opening PR in browser..." - open "$PR_URL" - elif command -v xdg-open >/dev/null 2>&1; then - echo "🌐 Opening PR in browser..." - xdg-open "$PR_URL" - else - echo "💡 Open the PR manually: $PR_URL" - fi - - exit 0 - fi - - if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then - echo "❌ Timeout: PR was not created after 5 minutes" - echo "Check the GitHub Actions workflow status:" - echo " gh run list --workflow=create-pr.yml" - echo "" - echo "You can also create the PR manually:" - echo " gh pr create --base $TARGET_BRANCH --head $CURRENT_BRANCH" - exit 1 - fi - - echo "PR not yet created, waiting 10 seconds..." - sleep 10 - ATTEMPT=$((ATTEMPT + 1)) -done diff --git a/justfile b/justfile index ea1dcfc..7e9014f 100644 --- a/justfile +++ b/justfile @@ -59,10 +59,6 @@ create-feature branch_type="feature" branch_name="" base_branch="main" update="y create-release type="patch": bin/create-release.sh {{type}} -# Create PR -create-pr target_branch="main" claude_review="true": - bin/create-pr.sh {{target_branch}} {{claude_review}} - # Clean up development artifacts clean: rm -rf .pytest_cache