From 0c8caa050ffa9b20b90bb6c7f98bd060e01d8788 Mon Sep 17 00:00:00 2001 From: centdix <40307056+centdix@users.noreply.github.com> Date: Wed, 14 May 2025 16:36:01 +0200 Subject: [PATCH] internal: Fixes on aider flow + add review flow (#5737) * add flow for aider review * add aider conventions, use ubicloud, ignore files * better if * use cursor rules * restrict to aider prs * fix --- .aiderignore | 3 + .github/workflows/aider-after-review.yaml | 170 ++++++++++++++++++++++ .github/workflows/aider.yaml | 44 ++++-- .gitignore | 2 + 4 files changed, 207 insertions(+), 12 deletions(-) create mode 100644 .aiderignore create mode 100644 .github/workflows/aider-after-review.yaml diff --git a/.aiderignore b/.aiderignore new file mode 100644 index 0000000000..0dca6eac77 --- /dev/null +++ b/.aiderignore @@ -0,0 +1,3 @@ +/* +!/backend/ +!/frontend/ \ No newline at end of file diff --git a/.github/workflows/aider-after-review.yaml b/.github/workflows/aider-after-review.yaml new file mode 100644 index 0000000000..6ae15bfc18 --- /dev/null +++ b/.github/workflows/aider-after-review.yaml @@ -0,0 +1,170 @@ +name: Aider Auto-fix PR Review Change Requests + +on: + pull_request_review: + types: [submitted] + +jobs: + auto-fix-review: + if: github.event.review.state == 'changes_requested' && contains(github.event.pull_request.title, '[Aider PR]') + runs-on: ubicloud-standard-8 + permissions: + contents: write + pull-requests: write + env: + GEMINI_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WINDMILL_TOKEN: ${{ secrets.WINDMILL_TOKEN }} + + steps: + - name: Harden Runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit + + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Git User + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Checkout PR Branch + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "PR review trigger: Checking out PR branch..." + PR_NUMBER=${{ github.event.pull_request.number }} + PR_HEAD_REF=$(gh pr view $PR_NUMBER --json headRefName -q .headRefName --repo $GITHUB_REPOSITORY) + if [[ -z "$PR_HEAD_REF" || "$PR_HEAD_REF" == "null" ]]; then + echo "::error::Could not determine PR head branch for PR #$PR_NUMBER via gh CLI." + exit 1 + fi + echo "Checking out PR head branch: $PR_HEAD_REF for PR #$PR_NUMBER" + git fetch origin "refs/heads/${PR_HEAD_REF}:refs/remotes/origin/${PR_HEAD_REF}" --no-tags + git checkout "$PR_HEAD_REF" + echo "Successfully checked out branch $(git rev-parse --abbrev-ref HEAD)" + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install Aider and Dependencies + run: | + python -m pip install aider-install; aider-install + pip install -U google-generativeai + sudo apt-get update && sudo apt-get install -y jq + + - name: Generate Prompt from Review + id: generate_prompt + shell: bash + run: | + mkdir -p .github/aider + PROMPT_FILE_PATH=".github/aider/review-prompt.txt" + + # Get PR review body + REVIEW_BODY="${{ github.event.review.body }}" + PR_NUMBER="${{ github.event.pull_request.number }}" + + # Get PR description for context NOT USED FOR NOW + # PR_DETAILS=$(gh pr view $PR_NUMBER --json title,body --repo $GITHUB_REPOSITORY) + # PR_TITLE=$(echo "$PR_DETAILS" | jq -r .title) + # PR_BODY=$(echo "$PR_DETAILS" | jq -r .body) + + # Get all PR review comments + REVIEW_COMMENTS=$(gh pr view $PR_NUMBER --json reviews -q '.reviews[] | select(.state == "CHANGES_REQUESTED") | .body' --repo $GITHUB_REPOSITORY) + REVIEW_BODY_Q=$(printf '%q' "$REVIEW_BODY") + + # Update query to get review comments from all review types, not just "CHANGES_REQUESTED" + ALL_REVIEW_COMMENTS=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/comments \ + | jq '[.[] | {diff_hunk: .diff_hunk, path: .path, body: .body}]') + + BASE_PROMPT="Fix the following issues in the PR based on the review feedback. The review body is prepended with REVIEW. The review comments are prepended with REVIEW_COMMENTS. The review body and comments are separated by a blank line." + printf "%s\nREVIEW:\n%s\nREVIEW_COMMENTS:\n%s" \ + "$BASE_PROMPT" "$REVIEW_BODY_Q" "$ALL_REVIEW_COMMENTS" > "$PROMPT_FILE_PATH" + echo "PROMPT_FILE_PATH=$PROMPT_FILE_PATH" >> $GITHUB_OUTPUT + + - name: Run Aider with review prompt + run: | + aider \ + --read .cursor/rules/rust-best-practices.mdc \ + --read .cursor/rules/svelte5-best-practices.mdc \ + --model gemini/gemini-2.5-pro-preview-05-06 \ + --message-file .github/aider/review-prompt.txt \ + --yes \ + --no-check-update \ + --auto-commits \ + --no-analytics \ + --no-gitignore \ + | tee .github/aider/aider-output.txt || true + echo "Aider command completed. Output saved to .github/aider/aider-output.txt" + # Check if there are any changes to commit + if [[ -z "$(git status --porcelain)" ]]; then + echo "No changes detected after running Aider." + exit 0 + fi + + - name: Clean up prompt file + if: always() + run: rm -f .github/aider/review-prompt.txt + + - name: Commit and Push Changes + id: commit_and_push + if: ${{ success() }} + run: | + CURRENT_BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD) + echo "Attempting to push changes to PR branch $CURRENT_BRANCH_NAME for PR #${{ github.event.pull_request.number }}" + + # Pull latest changes to avoid rejection due to non-fast-forward + git pull origin $CURRENT_BRANCH_NAME + + if git push origin $CURRENT_BRANCH_NAME; then + echo "Push to $CURRENT_BRANCH_NAME successful." + echo "CHANGES_APPLIED=true" >> $GITHUB_OUTPUT + else + echo "::warning::Push to PR branch $CURRENT_BRANCH_NAME failed." + echo "CHANGES_APPLIED=false" >> $GITHUB_OUTPUT + fi + + - name: Comment on PR + if: success() + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUM: ${{ github.event.pull_request.number }} + run: | + # Create comment body in a temporary file to avoid command line length limits + if [[ "${{ steps.commit_and_push.outputs.CHANGES_APPLIED }}" == "true" ]]; then + cat > /tmp/pr-comment.md << EOL + 🤖 I've automatically addressed the feedback based on the review. + + ## Aider Output + \`\`\` + $(cat .github/aider/aider-output.txt || echo 'No output available') + \`\`\` + + Please review the changes and let me know if further adjustments are needed. + EOL + else + cat > /tmp/pr-comment.md << EOL + 🤖 I attempted to address the review feedback, but no modifications were made. + + ## Aider Output + \`\`\` + $(cat .github/aider/aider-output.txt || echo 'No output available') + \`\`\` + + Please review the output and provide additional guidance if needed. + EOL + fi + + # Use the file for comment body + gh pr comment $PR_NUM --body-file /tmp/pr-comment.md diff --git a/.github/workflows/aider.yaml b/.github/workflows/aider.yaml index 466d5e218c..bc337b640e 100644 --- a/.github/workflows/aider.yaml +++ b/.github/workflows/aider.yaml @@ -6,7 +6,7 @@ on: jobs: auto-fix: - runs-on: ubuntu-latest + runs-on: ubicloud-standard-8 if: | github.event_name == 'issue_comment' && contains(github.event.comment.body, '/aider') && @@ -264,6 +264,8 @@ jobs: run: | echo "Files identified by probe-chat: ${{ env.FILES_TO_EDIT }}" aider \ + --read .cursor/rules/rust-best-practices.mdc \ + --read .cursor/rules/svelte5-best-practices.mdc \ ${{ env.FILES_TO_EDIT }} \ --model gemini/gemini-2.5-pro-preview-05-06 \ --message-file .github/aider/issue-prompt.txt \ @@ -271,7 +273,8 @@ jobs: --no-check-update \ --auto-commits \ --no-analytics \ - --no-stream > .github/aider/aider-output.txt 2>&1 || true + --no-gitignore \ + | tee .github/aider/aider-output.txt || true echo "Aider command completed. Output saved to .github/aider/aider-output.txt" - name: Clean up prompt file @@ -284,12 +287,23 @@ jobs: run: | if [[ -z "${{ github.event.issue.pull_request }}" ]]; then BRANCH_NAME="aider-fix-issue-${{ github.event.issue.number }}" - git checkout -b $BRANCH_NAME - echo "Created branch $BRANCH_NAME for issue #${{ github.event.issue.number }}" + + # Check if branch exists remotely + if git ls-remote --heads origin $BRANCH_NAME | grep -q $BRANCH_NAME; then + echo "Branch $BRANCH_NAME already exists remotely, fetching it" + git fetch origin $BRANCH_NAME + git checkout $BRANCH_NAME + git pull origin $BRANCH_NAME + else + echo "Creating new branch $BRANCH_NAME" + git checkout -b $BRANCH_NAME + fi + + echo "Created/checked out branch $BRANCH_NAME for issue #${{ github.event.issue.number }}" git push origin $BRANCH_NAME - echo "Pushed to new branch $BRANCH_NAME" + echo "Pushed to branch $BRANCH_NAME" echo "PR_BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT - echo "CHANGES_APPLIED_MESSAGE=Aider changes pushed to new branch $BRANCH_NAME." >> $GITHUB_OUTPUT + echo "CHANGES_APPLIED_MESSAGE=Aider changes pushed to branch $BRANCH_NAME." >> $GITHUB_OUTPUT else CURRENT_BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD) echo "Attempting to push changes to PR branch $CURRENT_BRANCH_NAME for PR #${{ github.event.issue.number }}" @@ -310,13 +324,19 @@ jobs: PR_BRANCH: ${{ steps.commit_and_push.outputs.PR_BRANCH_NAME }} ISSUE_NUM: ${{ github.event.issue.number }} run: | + # Create PR description in a temporary file to avoid command line length limits + cat > /tmp/pr-description.md << EOL + This PR was created automatically by Aider to fix issue #${ISSUE_NUM}. + + ## Aider Output + \`\`\` + $(cat .github/aider/aider-output.txt || echo "No output available") + \`\`\` + EOL + + # Create PR using the file for the body content gh pr create \ --title "[Aider PR] Add fixes for issue #${ISSUE_NUM}" \ - --body "This PR was created automatically by Aider to fix issue #${ISSUE_NUM}. - - ## Aider Output - \`\`\` - $(cat .github/aider/aider-output.txt || echo "No output available") - \`\`\`" \ + --body-file /tmp/pr-description.md \ --head "$PR_BRANCH" \ --base main diff --git a/.gitignore b/.gitignore index b157a1679a..5136fb8aca 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ CaddyfileRemoteMalo .vscode .dev-docker-wrapper* backend/.minio-data +.aider* +!.aiderignore \ No newline at end of file