[FEATURE] Configuration file-based ACL for /agentready assess command #27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: AgentReady Dev - Issue to Draft PR | |
| on: | |
| issues: | |
| types: [opened, labeled] | |
| issue_comment: | |
| types: [created] | |
| pull_request_review_comment: | |
| types: [created] | |
| workflow_dispatch: | |
| inputs: | |
| issue_number: | |
| description: 'Issue number to convert to PR' | |
| required: true | |
| type: number | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| id-token: write | |
| actions: read | |
| jobs: | |
| issue-to-pr: | |
| # Trigger on issue opened, labeled with 'ready-for-pr', or @agentready-dev mentions | |
| if: | | |
| (github.event_name == 'issues' && github.event.action == 'opened') || | |
| (github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'ready-for-pr') || | |
| (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@agentready-dev')) || | |
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@agentready-dev')) || | |
| github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Get issue context | |
| id: issue-context | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| let issueNumber; | |
| let isCommentTrigger = false; | |
| let commentBody = ''; | |
| if (context.eventName === 'workflow_dispatch') { | |
| issueNumber = context.payload.inputs.issue_number; | |
| } else if (context.eventName === 'issue_comment' || context.eventName === 'pull_request_review_comment') { | |
| // Extract issue/PR number from comment event | |
| if (context.payload.issue) { | |
| issueNumber = context.payload.issue.number; | |
| } else if (context.payload.pull_request) { | |
| issueNumber = context.payload.pull_request.number; | |
| } | |
| isCommentTrigger = true; | |
| commentBody = context.payload.comment?.body || ''; | |
| } else { | |
| issueNumber = context.payload.issue.number; | |
| } | |
| // Fetch issue details | |
| const issue = await github.rest.issues.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| }); | |
| // Check if this is already a PR | |
| if (issue.data.pull_request) { | |
| core.setOutput('is_pr', 'true'); | |
| core.setOutput('pr_number', issueNumber); | |
| } else { | |
| core.setOutput('is_pr', 'false'); | |
| } | |
| // Check if PR already exists for this issue | |
| const prs = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'all', | |
| head: `${context.repo.owner}:feat/issue-${issueNumber}`, | |
| }); | |
| // Also check for any PR mentioning this issue | |
| const allPrs = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'all', | |
| }); | |
| const linkedPr = allPrs.data.find(pr => | |
| pr.body?.includes(`#${issueNumber}`) || | |
| pr.title?.includes(`#${issueNumber}`) | |
| ); | |
| core.setOutput('issue_number', issueNumber); | |
| core.setOutput('issue_title', issue.data.title); | |
| core.setOutput('issue_body', issue.data.body || ''); | |
| core.setOutput('issue_author', issue.data.user.login); | |
| core.setOutput('is_comment_trigger', isCommentTrigger.toString()); | |
| core.setOutput('comment_body', commentBody); | |
| core.setOutput('existing_pr_number', linkedPr?.number?.toString() || prs.data[0]?.number?.toString() || ''); | |
| core.setOutput('skip_pr_creation', (linkedPr || prs.data[0]) ? 'true' : 'false'); | |
| return { | |
| issueNumber, | |
| title: issue.data.title, | |
| body: issue.data.body || '', | |
| author: issue.data.user.login, | |
| isCommentTrigger, | |
| commentBody, | |
| }; | |
| - name: Checkout repository | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Initialize activity log | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' | |
| id: init-log | |
| run: | | |
| mkdir -p .github/agentready-dev-logs | |
| LOG_FILE=".github/agentready-dev-logs/activity-$(date +%Y%m%d-%H%M%S)-${{ github.run_id }}.jsonl" | |
| echo "log_file=$LOG_FILE" >> $GITHUB_OUTPUT | |
| echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"event\":\"workflow_started\",\"run_id\":\"${{ github.run_id }}\",\"event_name\":\"${{ github.event_name }}\"}" >> "$LOG_FILE" | |
| # Ensure analysis files directory exists and is writable | |
| mkdir -p .github/agentready-dev-logs | |
| touch .github/agentready-dev-logs/.gitkeep | |
| - name: Log context | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' | |
| run: | | |
| echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"agent\":\"context_gatherer\",\"action\":\"gathered_issue_context\",\"issue_number\":\"${{ steps.issue-context.outputs.issue_number }}\",\"is_pr\":\"${{ steps.issue-context.outputs.is_pr }}\",\"skip_pr_creation\":\"${{ steps.issue-context.outputs.skip_pr_creation }}\"}" >> "${{ steps.init-log.outputs.log_file }}" | |
| - name: Configure Git | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' || steps.issue-context.outputs.is_comment_trigger == 'true' | |
| run: | | |
| git config user.name "agentready-dev[bot]" | |
| git config user.email "agentready-dev[bot]@users.noreply.github.com" | |
| - name: Analyze issue and determine action | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' | |
| id: analyze-issue | |
| uses: anthropics/claude-code-action@v1 | |
| env: | |
| LOG_FILE: ${{ steps.init-log.outputs.log_file }} | |
| ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: | | |
| You are the @agentready-dev agent. Analyze this issue to determine if it makes sense to create a draft PR. | |
| Issue #${{ steps.issue-context.outputs.issue_number }}: ${{ steps.issue-context.outputs.issue_title }} | |
| Issue body: | |
| ${{ steps.issue-context.outputs.issue_body }} | |
| First, run the /review-agentready command to analyze this issue. Use the review process to evaluate: | |
| 1. Is this issue actionable and well-defined enough for implementation? | |
| 2. Are there security concerns that need addressing first? | |
| 3. Does this align with AgentReady project goals? | |
| 4. What would be the implementation approach? | |
| Based on your analysis, decide: | |
| - If it makes sense to create a draft PR: Write "create_pr" (without quotes) to .github/agentready-dev-logs/analysis-decision.txt | |
| - If it doesn't make sense: Write "provide_feedback" (without quotes) to .github/agentready-dev-logs/analysis-decision.txt | |
| IMPORTANT: | |
| - Write ONLY the value (create_pr or provide_feedback), NOT "OUTPUT=value" | |
| - You MUST create these files using bash commands. Example: | |
| echo "create_pr" > .github/agentready-dev-logs/analysis-decision.txt | |
| echo "Your reasoning here" > .github/agentready-dev-logs/analysis-reasoning.txt | |
| echo "branch-name" > .github/agentready-dev-logs/analysis-branch.txt | |
| Write your reasoning (2-3 lines max) to .github/agentready-dev-logs/analysis-reasoning.txt | |
| Write a short branch name suggestion (e.g., "add-feature-x" or "fix-bug-y") to .github/agentready-dev-logs/analysis-branch.txt | |
| CRITICAL: You must create all three files (.github/agentready-dev-logs/analysis-decision.txt, analysis-reasoning.txt, and analysis-branch.txt) using bash echo commands. | |
| Do NOT post any comment yet - you will self-review your analysis first. | |
| - name: Verify analysis files exist | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' | |
| id: verify-analysis-files | |
| run: | | |
| if [ ! -f .github/agentready-dev-logs/analysis-decision.txt ]; then | |
| echo "ERROR: analysis-decision.txt not found. The 'Analyze issue and determine action' step failed to create required files." >&2 | |
| echo "This indicates Claude Code Action did not complete successfully." >&2 | |
| exit 1 | |
| fi | |
| if [ ! -f .github/agentready-dev-logs/analysis-reasoning.txt ]; then | |
| echo "ERROR: analysis-reasoning.txt not found. The 'Analyze issue and determine action' step failed to create required files." >&2 | |
| echo "This indicates Claude Code Action did not complete successfully." >&2 | |
| exit 1 | |
| fi | |
| echo "✅ Analysis files verified" | |
| echo "files_exist=true" >> $GITHUB_OUTPUT | |
| - name: Extract analysis decision | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.verify-analysis-files.outputs.files_exist == 'true' | |
| id: extract-decision | |
| run: | | |
| DECISION=$(cat .github/agentready-dev-logs/analysis-decision.txt | tr -d '\n' | head -c 50) | |
| # Remove "OUTPUT=" prefix if present | |
| DECISION=$(echo "$DECISION" | sed 's/^OUTPUT=//' | sed 's/^output=//') | |
| # Extract just the value (create_pr or provide_feedback) | |
| DECISION=$(echo "$DECISION" | grep -oE "(create_pr|provide_feedback)" | head -1) | |
| if [ -z "$DECISION" ]; then | |
| echo "ERROR: Invalid decision value in analysis-decision.txt. Expected 'create_pr' or 'provide_feedback'." >&2 | |
| exit 1 | |
| fi | |
| echo "decision=$DECISION" >> $GITHUB_OUTPUT | |
| REASONING=$(cat .github/agentready-dev-logs/analysis-reasoning.txt) | |
| echo "reasoning<<EOF" >> $GITHUB_OUTPUT | |
| echo "$REASONING" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| if [ -f .github/agentready-dev-logs/analysis-branch.txt ]; then | |
| BRANCH_SUGGESTION=$(cat .github/agentready-dev-logs/analysis-branch.txt | tr -d '\n' | head -c 50) | |
| echo "branch_suggestion=$BRANCH_SUGGESTION" >> $GITHUB_OUTPUT | |
| else | |
| echo "branch_suggestion=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Self-review issue analysis | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.extract-decision.outputs.decision != '' && steps.verify-analysis-files.outputs.files_exist == 'true' | |
| id: self-review-analysis | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: | | |
| Self-review the issue analysis using the /review-agentready command. | |
| Re-read the original issue #${{ steps.issue-context.outputs.issue_number }} and your analysis. | |
| Read the decision file: cat .github/agentready-dev-logs/analysis-decision.txt | |
| Read the reasoning file: cat .github/agentready-dev-logs/analysis-reasoning.txt | |
| Check the issue itself for: | |
| 1. Did you miss any security concerns in the issue description? | |
| 2. Are there implementation risks you didn't consider? | |
| 3. Is your analysis thorough and accurate? | |
| 4. Does your reasoning help humans make informed decisions? | |
| Track your self-review findings: | |
| - Write a summary of what you found/changed to .github/agentready-dev-logs/self-review-summary.txt | |
| - If you found issues: Describe what was missing and what you added | |
| - If no issues: State that the analysis was comprehensive | |
| If you find issues with your analysis that need to be added: | |
| - Update the decision/reasoning files with the improved analysis | |
| - After updating, write REVIEW_PASSED=true to .github/agentready-dev-logs/analysis-review-passed.txt | |
| If your analysis is comprehensive and accurate (no issues found): | |
| - Write REVIEW_PASSED=true to .github/agentready-dev-logs/analysis-review-passed.txt | |
| The goal is to ensure the issue is thoroughly analyzed before proceeding. Only write REVIEW_PASSED=true after you've verified the analysis is complete and accurate. | |
| Do NOT post any comment yet. | |
| - name: Check review result | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.extract-decision.outputs.decision != '' | |
| id: check-review | |
| run: | | |
| if [ -f .github/agentready-dev-logs/analysis-review-passed.txt ]; then | |
| REVIEW_PASSED=$(cat .github/agentready-dev-logs/analysis-review-passed.txt | tr -d '\n' | grep -i "true" || echo "false") | |
| echo "review_passed=$REVIEW_PASSED" >> $GITHUB_OUTPUT | |
| else | |
| echo "review_passed=true" >> $GITHUB_OUTPUT | |
| fi | |
| # Re-read decision in case it was updated during review | |
| if [ -f .github/agentready-dev-logs/analysis-decision.txt ]; then | |
| DECISION=$(cat .github/agentready-dev-logs/analysis-decision.txt | tr -d '\n' | head -c 50) | |
| # Remove "OUTPUT=" prefix if present | |
| DECISION=$(echo "$DECISION" | sed 's/^OUTPUT=//' | sed 's/^output=//') | |
| # Extract just the value (create_pr or provide_feedback) | |
| DECISION=$(echo "$DECISION" | grep -oE "(create_pr|provide_feedback)" | head -1) | |
| if [ -z "$DECISION" ]; then | |
| DECISION="${{ steps.extract-decision.outputs.decision }}" | |
| fi | |
| echo "final_decision=$DECISION" >> $GITHUB_OUTPUT | |
| else | |
| echo "final_decision=${{ steps.extract-decision.outputs.decision }}" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Extract self-review summary | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' | |
| id: extract-self-review | |
| run: | | |
| if [ -f .github/agentready-dev-logs/self-review-summary.txt ]; then | |
| SUMMARY=$(cat .github/agentready-dev-logs/self-review-summary.txt) | |
| echo "self_review_summary<<EOF" >> $GITHUB_OUTPUT | |
| echo "$SUMMARY" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| else | |
| echo "self_review_summary=Self-review completed - no changes needed" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Handle feedback (no PR creation) | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'provide_feedback' | |
| uses: actions/github-script@v8 | |
| env: | |
| LOG_FILE: ${{ steps.init-log.outputs.log_file }} | |
| ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} | |
| FEEDBACK: ${{ steps.extract-decision.outputs.reasoning }} | |
| SELF_REVIEW_SUMMARY: ${{ steps.extract-self-review.outputs.self_review_summary }} | |
| with: | |
| script: | | |
| const logEntry = { | |
| timestamp: new Date().toISOString(), | |
| agent: 'feedback_handler', | |
| action: 'provided_feedback', | |
| issue_number: parseInt(process.env.ISSUE_NUMBER), | |
| feedback: process.env.FEEDBACK, | |
| }; | |
| // Append to log file | |
| const fs = require('fs'); | |
| fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); | |
| // Build self-review section | |
| const selfReviewSection = process.env.SELF_REVIEW_SUMMARY && process.env.SELF_REVIEW_SUMMARY !== 'Self-review completed - no changes needed' | |
| ? `\n\n---\n<details><summary>Self-review results</summary>\n\n${process.env.SELF_REVIEW_SUMMARY}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>` | |
| : `\n\n---\n<details><summary>Self-review results</summary>\n\n✅ Analysis verified - no changes needed during self-review.\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>`; | |
| // Post brief, structured comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: parseInt(process.env.ISSUE_NUMBER), | |
| body: `🤖 **@agentready-dev Analysis**\n\n${process.env.FEEDBACK}${selfReviewSection}\n\n*Generated by @agentready-dev workflow*`, | |
| }); | |
| - name: Get default branch | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' | |
| id: default-branch | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name') | |
| echo "branch=$DEFAULT_BRANCH" >> $GITHUB_OUTPUT | |
| - name: Create feature branch | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' | |
| id: create-branch | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} | |
| ISSUE_TITLE: ${{ steps.issue-context.outputs.issue_title }} | |
| BRANCH_SUGGESTION: ${{ steps.extract-decision.outputs.branch_suggestion || 'implementation' }} | |
| DEFAULT_BRANCH: ${{ steps.default-branch.outputs.branch }} | |
| LOG_FILE: ${{ steps.init-log.outputs.log_file }} | |
| run: | | |
| # Generate branch name: feat/issue#-short-description | |
| # Clean and shorten issue title for branch name | |
| CLEAN_TITLE=$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g' | cut -c1-50) | |
| BRANCH_NAME="feat/issue${ISSUE_NUMBER}-${CLEAN_TITLE}" | |
| # Use suggestion if provided and shorter | |
| if [ -n "$BRANCH_SUGGESTION" ] && [ "$BRANCH_SUGGESTION" != "implementation" ] && [ "$BRANCH_SUGGESTION" != "" ]; then | |
| CLEAN_SUGGESTION=$(echo "$BRANCH_SUGGESTION" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g') | |
| BRANCH_NAME="feat/issue${ISSUE_NUMBER}-${CLEAN_SUGGESTION}" | |
| fi | |
| # Checkout default branch and ensure it's up to date | |
| git checkout "${DEFAULT_BRANCH}" | |
| git pull origin "${DEFAULT_BRANCH}" | |
| # Create and checkout new branch | |
| git checkout -b "${BRANCH_NAME}" | |
| # Create initial commit with issue reference | |
| mkdir -p .github/pr-placeholders | |
| echo "# Issue #${ISSUE_NUMBER}" > ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" | |
| echo "" >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" | |
| echo "This draft PR was automatically created from issue #${ISSUE_NUMBER}." >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" | |
| echo "" >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" | |
| echo "**Original Issue:** #${ISSUE_NUMBER}" >> ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" | |
| git add ".github/pr-placeholders/issue-${ISSUE_NUMBER}.md" | |
| git commit -m "chore: create draft PR branch for issue #${ISSUE_NUMBER}" | |
| # Push the branch | |
| git push origin "${BRANCH_NAME}" | |
| echo "branch_name=${BRANCH_NAME}" >> $GITHUB_OUTPUT | |
| # Log activity | |
| echo "{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"agent\":\"branch_creator\",\"action\":\"created_branch\",\"issue_number\":\"${ISSUE_NUMBER}\",\"branch_name\":\"${BRANCH_NAME}\"}" >> "$LOG_FILE" | |
| - name: Create draft Pull Request | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' | |
| id: create-pr | |
| uses: actions/github-script@v8 | |
| env: | |
| ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} | |
| ISSUE_TITLE: ${{ steps.issue-context.outputs.issue_title }} | |
| ISSUE_BODY: ${{ steps.issue-context.outputs.issue_body }} | |
| BRANCH_NAME: ${{ steps.create-branch.outputs.branch_name }} | |
| DEFAULT_BRANCH: ${{ steps.default-branch.outputs.branch }} | |
| ANALYSIS_SUMMARY: ${{ steps.extract-decision.outputs.reasoning }} | |
| LOG_FILE: ${{ steps.init-log.outputs.log_file }} | |
| with: | |
| script: | | |
| const issueNumber = parseInt(process.env.ISSUE_NUMBER); | |
| const issueTitle = process.env.ISSUE_TITLE; | |
| const issueBody = process.env.ISSUE_BODY || ''; | |
| const branchName = process.env.BRANCH_NAME; | |
| const defaultBranch = process.env.DEFAULT_BRANCH; | |
| const analysisSummary = process.env.ANALYSIS_SUMMARY || ''; | |
| // Create PR title and body | |
| const prTitle = `[Draft] Issue #${issueNumber}: ${issueTitle}`; | |
| const prBody = `## 🤖 Auto-generated Draft PR\n\n` + | |
| `This draft PR was automatically created from issue #${issueNumber}.\n\n` + | |
| `**Original Issue:** #${issueNumber}\n\n` + | |
| `**Analysis Summary:**\n${analysisSummary}\n\n` + | |
| `---\n\n` + | |
| `${issueBody}\n\n` + | |
| `---\n\n` + | |
| `*This PR was automatically created by the [@agentready-dev workflow](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/workflows/agentready-dev-issue-pr.yml).*\n` + | |
| `*[View activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})*`; | |
| // Create the draft PR | |
| const pr = await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: prTitle, | |
| body: prBody, | |
| head: branchName, | |
| base: defaultBranch, | |
| draft: true, | |
| maintainer_can_modify: true, | |
| }); | |
| console.log(`Created draft PR #${pr.data.number}: ${pr.data.html_url}`); | |
| // Log activity | |
| const fs = require('fs'); | |
| const logEntry = { | |
| timestamp: new Date().toISOString(), | |
| agent: 'pr_creator', | |
| action: 'created_draft_pr', | |
| issue_number: issueNumber, | |
| pr_number: pr.data.number, | |
| branch_name: branchName, | |
| }; | |
| fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); | |
| // Review the PR using review-agentready.md | |
| // This will be done in the next step | |
| core.setOutput('pr_number', pr.data.number); | |
| core.setOutput('pr_url', pr.data.html_url); | |
| return { | |
| prNumber: pr.data.number, | |
| prUrl: pr.data.html_url, | |
| }; | |
| - name: Review draft PR code | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' && steps.create-pr.outputs.pr_number != '' | |
| id: review-pr-code | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: | | |
| Run the /review-agentready command on pull request #${{ steps.create-pr.outputs.pr_number }}. | |
| Review the actual CODE in the PR, focusing on: | |
| - AgentReady attribute compliance | |
| - Security issues (take special care) | |
| - Code quality and correctness | |
| - Best practices | |
| Generate a brief, structured review comment (2-3 lines summary, use collapsible sections for details). | |
| Write the review to .github/agentready-dev-logs/pr-review.txt | |
| Also save a copy of the review to .github/agentready-dev-logs/pr-review-initial.txt before self-review. | |
| Use: cp .github/agentready-dev-logs/pr-review.txt .github/agentready-dev-logs/pr-review-initial.txt | |
| Do NOT post the comment yet - you will self-review the CODE first. | |
| - name: Self-review the PR code | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' && steps.create-pr.outputs.pr_number != '' | |
| id: self-review-pr-code | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: | | |
| Self-review the actual CODE in pull request #${{ steps.create-pr.outputs.pr_number }} using the /review-agentready command. | |
| Check the code itself for: | |
| 1. Security vulnerabilities (path traversal, injection, etc.) | |
| 2. Code quality issues (bugs, logic errors, edge cases) | |
| 3. AgentReady attribute compliance | |
| 4. Best practices violations | |
| Track your self-review findings: | |
| - Write a summary of what you found/changed to .github/agentready-dev-logs/pr-self-review-summary.txt | |
| - Compare the initial review (.github/agentready-dev-logs/pr-review-initial.txt) with your findings | |
| - If you found additional issues: Describe what was missing and what you added | |
| - If no issues: State that the review was comprehensive | |
| Compare your findings with the review in .github/agentready-dev-logs/pr-review.txt. | |
| If you find additional issues in the code that weren't in the review, update the review file. | |
| If the code review is comprehensive and accurate, write REVIEW_PASSED=true to .github/agentready-dev-logs/pr-review-passed.txt. | |
| If you found issues that need to be added to the review, update .github/agentready-dev-logs/pr-review.txt and write REVIEW_PASSED=true. | |
| The goal is to ensure the CODE is thoroughly reviewed before showing it to humans. Only write REVIEW_PASSED=true after you've verified the review is complete and accurate. | |
| Do NOT post any comment yet. | |
| - name: Extract PR review | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' | |
| id: extract-pr-review | |
| run: | | |
| if [ -f .github/agentready-dev-logs/pr-review.txt ]; then | |
| REVIEW=$(cat .github/agentready-dev-logs/pr-review.txt) | |
| echo "review<<EOF" >> $GITHUB_OUTPUT | |
| echo "$REVIEW" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| else | |
| echo "review=Review completed" >> $GITHUB_OUTPUT | |
| fi | |
| if [ -f .github/agentready-dev-logs/pr-review-passed.txt ]; then | |
| REVIEW_PASSED=$(cat .github/agentready-dev-logs/pr-review-passed.txt | tr -d '\n' | grep -i "true" || echo "false") | |
| echo "review_passed=$REVIEW_PASSED" >> $GITHUB_OUTPUT | |
| else | |
| echo "review_passed=true" >> $GITHUB_OUTPUT | |
| fi | |
| if [ -f .github/agentready-dev-logs/pr-self-review-summary.txt ]; then | |
| SELF_REVIEW_SUMMARY=$(cat .github/agentready-dev-logs/pr-self-review-summary.txt) | |
| echo "self_review_summary<<EOF" >> $GITHUB_OUTPUT | |
| echo "$SELF_REVIEW_SUMMARY" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| else | |
| echo "self_review_summary=Self-review completed - no changes needed" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Post PR review and link to issue | |
| if: steps.issue-context.outputs.skip_pr_creation != 'true' && steps.check-review.outputs.review_passed == 'true' && steps.check-review.outputs.final_decision == 'create_pr' && steps.extract-pr-review.outputs.review_passed == 'true' && steps.self-review-pr-code.outputs.REVIEW_PASSED == 'true' | |
| uses: actions/github-script@v8 | |
| env: | |
| LOG_FILE: ${{ steps.init-log.outputs.log_file }} | |
| ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} | |
| PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} | |
| PR_URL: ${{ steps.create-pr.outputs.pr_url }} | |
| REVIEW_OUTPUT: ${{ steps.extract-pr-review.outputs.review }} | |
| SELF_REVIEW_SUMMARY: ${{ steps.extract-pr-review.outputs.self_review_summary }} | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const issueNumber = parseInt(process.env.ISSUE_NUMBER); | |
| const prNumber = parseInt(process.env.PR_NUMBER); | |
| const prUrl = process.env.PR_URL; | |
| const reviewOutput = process.env.REVIEW_OUTPUT; | |
| const selfReviewSummary = process.env.SELF_REVIEW_SUMMARY; | |
| // Build self-review section | |
| const selfReviewSection = selfReviewSummary && selfReviewSummary !== 'Self-review completed - no changes needed' | |
| ? `\n\n---\n<details><summary>Self-review results</summary>\n\n${selfReviewSummary}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>` | |
| : `\n\n---\n<details><summary>Self-review results</summary>\n\n✅ Code review verified - no changes needed during self-review.\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>`; | |
| // Post review on PR | |
| const prComment = `🤖 **@agentready-dev PR Review**\n\n${reviewOutput}${selfReviewSection}\n\n*Generated by @agentready-dev workflow*`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: prComment, | |
| }); | |
| // Link PR to issue | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| body: `🔀 **Draft PR created:** #${prNumber}\n\n${prUrl}\n\n---\n*Generated by @agentready-dev workflow*`, | |
| }); | |
| // Log activity | |
| const logEntry = { | |
| timestamp: new Date().toISOString(), | |
| agent: 'comment_poster', | |
| action: 'posted_pr_review_and_linked_issue', | |
| issue_number: issueNumber, | |
| pr_number: prNumber, | |
| }; | |
| fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); | |
| - name: Handle ad-hoc analysis request | |
| if: steps.issue-context.outputs.is_comment_trigger == 'true' | |
| id: analyze-comment | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: | | |
| You are the @agentready-dev agent. Someone requested analysis with: "${{ steps.issue-context.outputs.comment_body }}" | |
| Issue/PR context: | |
| - Issue/PR #${{ steps.issue-context.outputs.issue_number }} | |
| - Title: ${{ steps.issue-context.outputs.issue_title }} | |
| - Body: ${{ steps.issue-context.outputs.issue_body }} | |
| If this is a PR (is_pr=${{ steps.issue-context.outputs.is_pr }}), run the /review-agentready command on the CODE in the PR. | |
| If this is an issue, analyze the issue description and proposed implementation using the review-agentready.md process. | |
| Provide a brief, structured analysis (2-3 lines summary, use collapsible sections for details). | |
| Focus on what a reviewer would need to know. | |
| Write analysis to .github/agentready-dev-logs/adhoc-analysis.txt | |
| Do NOT post any comment yet - you will self-review the CODE/issue first. | |
| - name: Self-review ad-hoc analysis | |
| if: steps.issue-context.outputs.is_comment_trigger == 'true' | |
| id: self-review-comment | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: | | |
| Self-review the actual CODE or issue using the /review-agentready command. | |
| If this is a PR (is_pr=${{ steps.issue-context.outputs.is_pr }}), review the CODE in PR #${{ steps.issue-context.outputs.issue_number }} again. | |
| If this is an issue, re-read issue #${{ steps.issue-context.outputs.issue_number }}. | |
| Read your analysis file: cat .github/agentready-dev-logs/adhoc-analysis.txt | |
| Track your self-review findings: | |
| - Write a summary of what you found/changed to .github/agentready-dev-logs/adhoc-self-review-summary.txt | |
| - If you found issues: Describe what was missing and what you added | |
| - If no issues: State that the analysis was comprehensive | |
| Check for: | |
| 1. Security issues you might have missed in the code/issue | |
| 2. Code quality problems or bugs you didn't catch | |
| 3. Important details that reviewers need to know | |
| 4. Is your analysis thorough and accurate? | |
| If you find issues you missed, update .github/agentready-dev-logs/adhoc-analysis.txt and write REVIEW_PASSED=true. | |
| If your analysis is comprehensive, write REVIEW_PASSED=true to .github/agentready-dev-logs/adhoc-analysis-passed.txt. | |
| The goal is to ensure the CODE/issue is thoroughly reviewed before showing it to humans. Only write REVIEW_PASSED=true after you've verified the analysis is complete and accurate. | |
| Do NOT post any comment yet. | |
| - name: Extract ad-hoc analysis | |
| if: steps.issue-context.outputs.is_comment_trigger == 'true' | |
| id: extract-analysis | |
| run: | | |
| if [ -f .github/agentready-dev-logs/adhoc-analysis.txt ]; then | |
| ANALYSIS=$(cat .github/agentready-dev-logs/adhoc-analysis.txt) | |
| echo "analysis<<EOF" >> $GITHUB_OUTPUT | |
| echo "$ANALYSIS" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| else | |
| echo "analysis=Analysis completed" >> $GITHUB_OUTPUT | |
| fi | |
| if [ -f .github/agentready-dev-logs/adhoc-analysis-passed.txt ]; then | |
| ANALYSIS_PASSED=$(cat .github/agentready-dev-logs/adhoc-analysis-passed.txt | tr -d '\n' | grep -i "true" || echo "false") | |
| echo "analysis_passed=$ANALYSIS_PASSED" >> $GITHUB_OUTPUT | |
| else | |
| echo "analysis_passed=true" >> $GITHUB_OUTPUT | |
| fi | |
| if [ -f .github/agentready-dev-logs/adhoc-self-review-summary.txt ]; then | |
| SELF_REVIEW_SUMMARY=$(cat .github/agentready-dev-logs/adhoc-self-review-summary.txt) | |
| echo "self_review_summary<<EOF" >> $GITHUB_OUTPUT | |
| echo "$SELF_REVIEW_SUMMARY" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| else | |
| echo "self_review_summary=Self-review completed - no changes needed" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Post ad-hoc analysis comment | |
| if: steps.issue-context.outputs.is_comment_trigger == 'true' && steps.extract-analysis.outputs.analysis_passed == 'true' | |
| uses: actions/github-script@v8 | |
| env: | |
| LOG_FILE: ${{ steps.init-log.outputs.log_file }} | |
| ISSUE_NUMBER: ${{ steps.issue-context.outputs.issue_number }} | |
| ANALYSIS_OUTPUT: ${{ steps.extract-analysis.outputs.analysis }} | |
| SELF_REVIEW_SUMMARY: ${{ steps.extract-analysis.outputs.self_review_summary }} | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const issueNumber = parseInt(process.env.ISSUE_NUMBER); | |
| const analysisOutput = process.env.ANALYSIS_OUTPUT; | |
| const selfReviewSummary = process.env.SELF_REVIEW_SUMMARY; | |
| // Build self-review section | |
| const selfReviewSection = selfReviewSummary && selfReviewSummary !== 'Self-review completed - no changes needed' | |
| ? `\n\n---\n<details><summary>Self-review results</summary>\n\n${selfReviewSummary}\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>` | |
| : `\n\n---\n<details><summary>Self-review results</summary>\n\n✅ Analysis verified - no changes needed during self-review.\n\n[View full activity log](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})\n</details>`; | |
| // Post brief, structured comment | |
| const comment = `🤖 **@agentready-dev Analysis**\n\n${analysisOutput}${selfReviewSection}\n\n*Generated by @agentready-dev workflow*`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| body: comment, | |
| }); | |
| // Log activity | |
| const logEntry = { | |
| timestamp: new Date().toISOString(), | |
| agent: 'analysis_agent', | |
| action: 'posted_adhoc_analysis', | |
| issue_number: issueNumber, | |
| }; | |
| fs.appendFileSync(process.env.LOG_FILE, JSON.stringify(logEntry) + '\n'); | |
| - name: Upload activity log | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: agentready-dev-activity-log-${{ github.run_id }} | |
| path: ${{ steps.init-log.outputs.log_file }} | |
| retention-days: 90 | |
| - name: Summary | |
| if: always() | |
| run: | | |
| if [ "${{ steps.issue-context.outputs.skip_pr_creation }}" == "true" ]; then | |
| echo "## ⚠️ Skipped" >> $GITHUB_STEP_SUMMARY | |
| if [ -n "${{ steps.issue-context.outputs.existing_pr_number }}" ]; then | |
| echo "PR already exists for this issue: #${{ steps.issue-context.outputs.existing_pr_number }}" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "Issue is already a PR or cannot be processed." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| elif [ "${{ steps.check-review.outputs.final_decision }}" == "provide_feedback" ]; then | |
| echo "## 💬 Feedback Provided" >> $GITHUB_STEP_SUMMARY | |
| echo "**Issue:** #${{ steps.issue-context.outputs.issue_number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "Feedback was posted to the issue." >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.check-review.outputs.final_decision }}" == "create_pr" ]; then | |
| echo "## ✅ Draft PR Created" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Issue:** #${{ steps.issue-context.outputs.issue_number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Draft PR:** #${{ steps.create-pr.outputs.pr_number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**URL:** ${{ steps.create-pr.outputs.pr_url }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "The draft PR has been created, reviewed, and linked to the issue." >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ steps.issue-context.outputs.is_comment_trigger }}" == "true" ]; then | |
| echo "## 🔍 Analysis Complete" >> $GITHUB_STEP_SUMMARY | |
| echo "**Issue/PR:** #${{ steps.issue-context.outputs.issue_number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "Analysis was posted as a comment." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "[View activity log artifact](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY |