Add systematic tests for HelperVisitor Fluent API and ReferenceHolder population #183
Workflow file for this run
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
| # Automatic PR Code Cleanup using Sandbox Cleanup Application | |
| # This workflow automatically applies Eclipse JDT cleanup transformations to pull requests | |
| # Uses the composite action that wraps the sandbox cleanup application | |
| # | |
| # LIMITATIONS: | |
| # - This workflow has limited support for pull requests from forked repositories. | |
| # The default GITHUB_TOKEN does not have write permissions to push branches or create PRs in forks. | |
| # - For PRs from the main repository: Full functionality (cleanup PR created automatically) | |
| # - For PRs from forked repositories: Fallback mode (review comments + diff in PR comment) | |
| # The workflow will post review comments and provide a full diff for manual review. | |
| name: Auto PR Cleanup | |
| on: | |
| pull_request: | |
| types: [opened, synchronize] | |
| branches: [main] | |
| paths: | |
| - '**.java' | |
| workflow_dispatch: # Keep manual triggering as fallback | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| cleanup: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout PR branch | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.pull_request.head.ref }} | |
| repository: ${{ github.event.pull_request.head.repo.full_name }} | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| fetch-depth: 0 | |
| - name: Run Sandbox Cleanup | |
| uses: ./.github/actions/cleanup-action | |
| with: | |
| config-file: '.github/cleanup-profiles/standard.properties' | |
| source-dir: '.' | |
| verbose: 'true' | |
| - name: Check for changes | |
| id: check_changes | |
| run: | | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| git status --short | |
| else | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Collect change details | |
| id: changes | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| run: | | |
| # Anzahl geänderter Dateien | |
| CHANGED_FILES=$(git status --porcelain | wc -l) | |
| echo "changed_count=$CHANGED_FILES" >> $GITHUB_OUTPUT | |
| # Liste der geänderten Dateien (erste 20) | |
| CHANGED_LIST=$(git status --porcelain | awk '{print $2}' | head -20) | |
| echo "changed_list<<EOF" >> $GITHUB_OUTPUT | |
| echo "$CHANGED_LIST" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| # Diff-Statistik | |
| git add -A | |
| DIFF_STAT=$(git diff --cached --stat) | |
| echo "diff_stat<<EOF" >> $GITHUB_OUTPUT | |
| echo "$DIFF_STAT" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| # Kurze Diff-Vorschau (erste 100 Zeilen) | |
| DIFF_PREVIEW=$(git diff --cached --no-color | head -100) | |
| echo "diff_preview<<EOF" >> $GITHUB_OUTPUT | |
| echo "$DIFF_PREVIEW" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| - name: Create cleanup branch and commit changes | |
| id: create_branch | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # Create a unique cleanup branch name, sanitizing slashes in the base branch | |
| BASE_BRANCH="${{ github.event.pull_request.head.ref }}" | |
| SANITIZED_BASE_BRANCH="${BASE_BRANCH//\//-}" | |
| CLEANUP_BRANCH="cleanup/${SANITIZED_BASE_BRANCH}-${{ github.run_number }}" | |
| echo "cleanup_branch=$CLEANUP_BRANCH" >> $GITHUB_OUTPUT | |
| # Create and switch to cleanup branch | |
| git checkout -b "$CLEANUP_BRANCH" | |
| # Commit changes | |
| git add -A | |
| git commit -m "🧹 Cleanup: Apply Eclipse JDT transformations (${{ steps.changes.outputs.changed_count }} files)" \ | |
| -m "Changed files:" \ | |
| -m "${{ steps.changes.outputs.changed_list }}" | |
| # Push to remote | |
| git push origin "$CLEANUP_BRANCH" | |
| - name: Create cleanup PR | |
| id: create_pr | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const cleanupBranch = ${{ toJSON(steps.create_branch.outputs.cleanup_branch) }}; | |
| const baseBranch = ${{ toJSON(github.event.pull_request.head.ref) }}; | |
| const changedCount = ${{ toJSON(steps.changes.outputs.changed_count) }}; | |
| const diffStat = ${{ toJSON(steps.changes.outputs.diff_stat) }}; | |
| const changedList = ${{ toJSON(steps.changes.outputs.changed_list) }}; | |
| const diffPreview = ${{ toJSON(steps.changes.outputs.diff_preview) }}; | |
| const changedFiles = changedList.split('\n') | |
| .filter(f => f.trim()) | |
| .map(f => `- \`${f}\``) | |
| .join('\n'); | |
| // Create PR | |
| const prBody = '## 🧹 Sandbox Cleanup Proposal\n\n' + | |
| '**This is an automatically generated cleanup pull request.** You can:\n' + | |
| '- ✅ **Accept**: Merge this pull request\n' + | |
| '- ❌ **Decline**: Close this pull request without merging\n' + | |
| '- ✏️ **Modify**: Edit the files in this pull request before merging\n\n' + | |
| '### Summary\n' + | |
| `- **Changed files:** ${changedCount}\n` + | |
| `- **Diff stats:** ${diffStat}\n\n` + | |
| '### Changed files\n' + | |
| changedFiles + '\n\n' + | |
| '### Applied transformations\n' + | |
| '- ✨ Code formatting and import organization\n' + | |
| '- 📝 Added missing annotations (@Override, @Deprecated)\n' + | |
| '- 🧹 Removed unnecessary code (casts, unused variables)\n' + | |
| '- 🚀 Modernized code (lambdas, functional interfaces)\n' + | |
| '- 🔧 Applied sandbox-specific cleanups\n\n' + | |
| '### Diff preview\n' + | |
| '<details>\n' + | |
| '<summary>Click to show diff</summary>\n\n' + | |
| '```diff\n' + | |
| diffPreview + '\n' + | |
| '```\n' + | |
| '</details>\n\n' + | |
| '**Profile:** standard\n\n' + | |
| `**Target PR:** #${{ github.event.pull_request.number }}`; | |
| try { | |
| const { data: newPR } = await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: `🧹 Cleanup for PR #${{ github.event.pull_request.number }}: ${changedCount} files`, | |
| head: cleanupBranch, | |
| base: baseBranch, | |
| body: prBody | |
| }); | |
| core.setOutput('pr_number', newPR.number); | |
| core.setOutput('pr_url', newPR.html_url); | |
| core.setOutput('pr_created', 'true'); | |
| return newPR.number; | |
| } catch (error) { | |
| core.setOutput('pr_created', 'false'); | |
| core.setOutput('error_message', error.message); | |
| core.warning(`Failed to create cleanup PR: ${error.message}`); | |
| // Note: This workflow does not support forked repositories due to GITHUB_TOKEN permissions. | |
| // For forked PRs, the cleanup changes are available in the branch but no PR can be created. | |
| return null; | |
| } | |
| - name: Create review comments for fork fallback | |
| id: create_review | |
| if: steps.check_changes.outputs.has_changes == 'true' && steps.create_pr.outputs.pr_created != 'true' | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const changedList = ${{ toJSON(steps.changes.outputs.changed_list) }}; | |
| const diffPreview = ${{ toJSON(steps.changes.outputs.diff_preview) }}; | |
| // Get the list of files that were changed | |
| const changedFiles = changedList.split('\n').filter(f => f.trim()); | |
| // Parse diff to extract file changes and create review comments | |
| const diffLines = diffPreview.split('\n'); | |
| const comments = []; | |
| let currentFile = null; | |
| let currentHunk = null; | |
| let lineNumber = 0; | |
| for (const line of diffLines) { | |
| // Match file headers like "diff --git a/file b/file" | |
| const fileMatch = line.match(/^diff --git a\/(.*) b\/(.*)/); | |
| if (fileMatch) { | |
| currentFile = fileMatch[2]; | |
| continue; | |
| } | |
| // Match hunk headers like "@@ -1,2 +3,4 @@" | |
| const hunkMatch = line.match(/^@@ -(\d+),?\d* \+(\d+),?\d* @@/); | |
| if (hunkMatch && currentFile) { | |
| lineNumber = parseInt(hunkMatch[2]); | |
| continue; | |
| } | |
| // Track line numbers for additions (lines starting with +) | |
| if (line.startsWith('+') && !line.startsWith('+++') && currentFile && lineNumber > 0) { | |
| // Limit to first 10 files and 3 comments per file to avoid spam | |
| const fileComments = comments.filter(c => c.path === currentFile); | |
| if (comments.length < 10 && fileComments.length < 3) { | |
| comments.push({ | |
| path: currentFile, | |
| line: lineNumber, | |
| body: `🧹 Cleanup suggestion: This line was modified by the automatic cleanup process.` | |
| }); | |
| } | |
| } | |
| // Increment line number for context and additions | |
| if (!line.startsWith('-') || line.startsWith('---')) { | |
| lineNumber++; | |
| } | |
| } | |
| // Create a review with comments if we have any | |
| if (comments.length > 0) { | |
| try { | |
| const review = await github.rest.pulls.createReview({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number, | |
| event: 'COMMENT', | |
| body: '🧹 **Automatic cleanup suggestions**\n\n' + | |
| 'The cleanup process identified improvements to your code. ' + | |
| 'Since this is from a forked repository, I cannot create a cleanup PR, ' + | |
| 'but I\'ve added review comments showing the suggested changes.\n\n' + | |
| '**Note**: Due to diff preview limitations, only a sample of changes are shown. ' + | |
| 'For the complete diff, see the comment below.', | |
| comments: comments | |
| }); | |
| core.setOutput('review_created', 'true'); | |
| core.setOutput('review_id', review.data.id); | |
| return review.data.id; | |
| } catch (error) { | |
| core.warning(`Failed to create review: ${error.message}`); | |
| core.setOutput('review_created', 'false'); | |
| return null; | |
| } | |
| } else { | |
| core.info('No suitable locations found for review comments'); | |
| core.setOutput('review_created', 'false'); | |
| return null; | |
| } | |
| - name: Comment on original PR | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const prCreated = '${{ steps.create_pr.outputs.pr_created }}'; | |
| const cleanupPrNumber = '${{ steps.create_pr.outputs.pr_number }}'; | |
| const cleanupPrUrl = '${{ steps.create_pr.outputs.pr_url }}'; | |
| const changedCount = '${{ steps.changes.outputs.changed_count }}'; | |
| const errorMessage = '${{ steps.create_pr.outputs.error_message }}'; | |
| const cleanupBranch = '${{ steps.create_branch.outputs.cleanup_branch }}'; | |
| const reviewCreated = '${{ steps.create_review.outputs.review_created }}'; | |
| const diffStat = ${{ toJSON(steps.changes.outputs.diff_stat) }}; | |
| const changedList = ${{ toJSON(steps.changes.outputs.changed_list) }}; | |
| const diffPreview = ${{ toJSON(steps.changes.outputs.diff_preview) }}; | |
| let commentBody; | |
| if (prCreated === 'true' && cleanupPrNumber) { | |
| // Success case: PR was created | |
| commentBody = `## 🧹 Cleanup suggestions available\n\n` + | |
| `The automatic cleanup process analyzed **${changedCount} files** and found improvements.\n\n` + | |
| `### 📋 Cleanup PR: #${cleanupPrNumber}\n` + | |
| `🔗 ${cleanupPrUrl}\n\n` + | |
| `### Your options:\n` + | |
| `1. ✅ **Accept all changes**: Merge PR #${cleanupPrNumber}\n` + | |
| `2. ✏️ **Adjust the changes**: Edit the files in PR #${cleanupPrNumber} and then merge\n` + | |
| `3. ❌ **Reject the changes**: Close PR #${cleanupPrNumber} and continue with your original PR\n\n` + | |
| `The cleanup PR contains detailed information about all proposed changes.`; | |
| } else { | |
| // Failure case: PR creation failed (likely due to fork permissions) | |
| const changedFiles = changedList.split('\n') | |
| .filter(f => f.trim()) | |
| .map(f => `- \`${f}\``) | |
| .join('\n'); | |
| commentBody = `## 🧹 Cleanup suggestions available\n\n` + | |
| `The automatic cleanup process analyzed **${changedCount} files** and found improvements.\n\n` + | |
| `⚠️ **Note**: A cleanup PR could not be automatically created. This typically occurs when:\n` + | |
| `- The original PR is from a forked repository (GITHUB_TOKEN lacks write permissions to forks)\n` + | |
| `- There are API permission or rate limit issues\n\n`; | |
| if (reviewCreated === 'true') { | |
| commentBody += `### ✅ Review comments created\n` + | |
| `I've added review comments showing suggested changes on specific lines. ` + | |
| `Check the "Files changed" tab to see the suggestions.\n\n`; | |
| } | |
| commentBody += `### Summary\n` + | |
| `- **Changed files:** ${changedCount}\n` + | |
| `- **Diff stats:** ${diffStat}\n\n` + | |
| `### Changed files\n` + | |
| changedFiles + '\n\n' + | |
| `### Diff preview\n` + | |
| `<details>\n` + | |
| `<summary>Click to show diff</summary>\n\n` + | |
| `\`\`\`diff\n` + | |
| diffPreview + `\n` + | |
| `\`\`\`\n` + | |
| `</details>\n\n` + | |
| `### Manual review options:\n` + | |
| `1. **Review the diff above** and manually apply changes you want\n` + | |
| `2. **Check the cleanup branch**: \`${cleanupBranch}\`\n` + | |
| ` - Fetch: \`git fetch origin ${cleanupBranch}\`\n` + | |
| ` - Compare: \`git diff ${cleanupBranch}\`\n` + | |
| ` - Cherry-pick specific changes if desired\n\n` + | |
| `**Error details**: ${errorMessage || 'Unknown error'}`; | |
| } | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: commentBody | |
| }); | |