Skip to content

Add systematic tests for HelperVisitor Fluent API and ReferenceHolder population #183

Add systematic tests for HelperVisitor Fluent API and ReferenceHolder population

Add systematic tests for HelperVisitor Fluent API and ReferenceHolder population #183

Workflow file for this run

# 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
});