-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Feat: Add auto formatting bot #14927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
georgereuben
wants to merge
11
commits into
apache:main
Choose a base branch
from
georgereuben:feat/auto-format-bot
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
9aced53
add auto format workflow
georgereuben 1d72bbf
add reactions
georgereuben 62ba4f0
replace inline scripts with gh cli
georgereuben 4293ca3
add repo flag to gh pr commands
georgereuben 884cbde
fix: modify reactions to use double-quotes
georgereuben 57fc7a5
fix: add input field for reactions
georgereuben 147c1ba
allow PR author to trigger the workflow
georgereuben 6e48c4b
update get-changed-files to use trusted action
georgereuben 81fa2c8
Add direct commit conditional flow for PRs from forked repos
georgereuben 88f6a35
replace get-changed-files step with gh cli script
georgereuben e53f3f6
replace JDK setup with Lucene's prepare for build action
georgereuben File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,312 @@ | ||
name: Auto Format Bot | ||
|
||
on: | ||
issue_comment: | ||
types: [created] | ||
|
||
env: | ||
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
jobs: | ||
format-check: | ||
# Only run on pull requests when the bot is mentioned | ||
if: | | ||
github.event.issue.pull_request && | ||
contains(github.event.comment.body, '/format-fix apply') | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 30 | ||
|
||
permissions: | ||
contents: write | ||
pull-requests: write | ||
issues: write | ||
|
||
steps: | ||
- name: Check permissions | ||
run: | | ||
PR_AUTHOR=$(gh pr view ${{ github.event.issue.number }} --repo ${{ github.repository }} --json author --jq '.author.login') | ||
|
||
PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission' 2>/dev/null || echo "none") | ||
|
||
# only allow if user is PR author OR has admin/write repository access | ||
if [[ "${{ github.actor }}" == "$PR_AUTHOR" ]] || [[ "$PERMISSION" == "admin" ]] || [[ "$PERMISSION" == "write" ]]; then | ||
echo "Permission granted: User @${{ github.actor }} can run the format bot" | ||
if [[ "${{ github.actor }}" == "$PR_AUTHOR" ]]; then | ||
echo " - Reason: PR author" | ||
fi | ||
if [[ "$PERMISSION" == "admin" ]] || [[ "$PERMISSION" == "write" ]]; then | ||
echo " - Reason: Repository $PERMISSION access" | ||
fi | ||
else | ||
echo "Error: User @${{ github.actor }} does not have permission to run the format bot." | ||
echo "Required: Be the PR author OR have admin/write repository access." | ||
exit 1 | ||
fi | ||
|
||
- name: Add workflow started reaction | ||
run: | | ||
gh api repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \ | ||
--method POST \ | ||
--input - <<< '{"content":"eyes"}' | ||
|
||
- name: Get PR details and checkout | ||
run: | | ||
# Get PR details | ||
PR_DATA=$(gh pr view ${{ github.event.issue.number }} --repo ${{ github.repository }} --json headRefName,headRepository,headRepositoryOwner) | ||
HEAD_REF=$(echo "$PR_DATA" | jq -r '.headRefName') | ||
HEAD_REPO=$(echo "$PR_DATA" | jq -r '.headRepository.name') | ||
HEAD_OWNER=$(echo "$PR_DATA" | jq -r '.headRepositoryOwner.login') | ||
|
||
echo "head_ref=$HEAD_REF" >> $GITHUB_ENV | ||
echo "head_repo_full=$HEAD_OWNER/$HEAD_REPO" >> $GITHUB_ENV | ||
|
||
- name: Detect if PR is from fork | ||
run: | | ||
HEAD_OWNER=$(echo "${{ env.head_repo_full }}" | cut -d'/' -f1) | ||
REPO_OWNER="${{ github.repository_owner }}" | ||
|
||
if [[ "$HEAD_OWNER" != "$REPO_OWNER" ]]; then | ||
echo "is_fork=true" >> $GITHUB_ENV | ||
echo "PR is from fork: ${{ env.head_repo_full }}" | ||
else | ||
echo "is_fork=false" >> $GITHUB_ENV | ||
echo "PR is from same repository" | ||
fi | ||
|
||
- name: Checkout PR code | ||
uses: actions/checkout@v4 | ||
with: | ||
repository: ${{ env.head_repo_full }} | ||
ref: ${{ env.head_ref }} | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
fetch-depth: 0 | ||
|
||
- uses: ./.github/actions/prepare-for-build | ||
|
||
#this replaces ana06/get-changed-files@v2.3.0 since it doesn't support issue comment triggers | ||
- name: Get changed files | ||
id: changed-files | ||
run: | | ||
echo "Getting changed files for PR #${{ github.event.issue.number }}..." | ||
|
||
ALL_FILES=$(gh pr diff ${{ github.event.issue.number }} --name-only --repo ${{ github.repository }}) | ||
|
||
FILTERED_FILES=$(echo "$ALL_FILES" | grep -E '\.(java|gradle|groovy|md|properties|xml|py|sh|bat|cmd)$' || true) | ||
|
||
echo "All changed files:" | ||
echo "$ALL_FILES" | ||
echo | ||
echo "Filtered files for formatting check:" | ||
echo "$FILTERED_FILES" | ||
|
||
echo "all<<EOF" >> $GITHUB_OUTPUT | ||
echo "$ALL_FILES" >> $GITHUB_OUTPUT | ||
echo "EOF" >> $GITHUB_OUTPUT | ||
|
||
echo "filtered<<EOF" >> $GITHUB_OUTPUT | ||
echo "$FILTERED_FILES" >> $GITHUB_OUTPUT | ||
echo "EOF" >> $GITHUB_OUTPUT | ||
|
||
- name: Initial validation | ||
id: initial-validation | ||
continue-on-error: true | ||
run: | | ||
echo "Running initial validation..." | ||
./gradlew check -x test | ||
|
||
- name: Fix formatting issues | ||
if: steps.initial-validation.outcome == 'failure' | ||
run: | | ||
echo "Fixing formatting issues..." | ||
./gradlew tidy | ||
|
||
- name: Check if formatting fixes were made | ||
if: steps.initial-validation.outcome == 'failure' | ||
id: check_changes | ||
run: | | ||
git add . | ||
if git diff --staged --quiet; then | ||
echo "No formatting changes were made" | ||
echo "changes_made=false" >> $GITHUB_OUTPUT | ||
else | ||
echo "Formatting changes were made" | ||
echo "changes_made=true" >> $GITHUB_OUTPUT | ||
echo "Changed files:" | ||
git diff --staged --name-only | ||
fi | ||
|
||
- name: Create fix branch and commit (same-repo) | ||
if: steps.initial-validation.outcome == 'failure' && steps.check_changes.outputs.changes_made == 'true' && env.is_fork == 'false' | ||
id: create_fix_branch | ||
run: | | ||
# Create a new branch for the fixes | ||
fix_branch="format-fixes-${{ env.head_ref }}-$(date +%s)" | ||
echo "fix_branch=$fix_branch" >> $GITHUB_OUTPUT | ||
echo "fix_branch=$fix_branch" >> $GITHUB_ENV | ||
|
||
git config --local user.email "action@github.com" | ||
git config --local user.name "Auto Format Bot" | ||
|
||
git checkout -b "$fix_branch" | ||
git commit -m "Apply automatic formatting fixes | ||
|
||
Fixes applied by @auto-format-bot in response to: | ||
${{ github.event.comment.html_url }} | ||
|
||
Original PR: #${{ github.event.issue.number }} | ||
|
||
Changes applied: | ||
$(git diff --name-only HEAD~1)" | ||
|
||
git push origin "$fix_branch" | ||
|
||
- name: Commit directly to fork PR | ||
if: steps.initial-validation.outcome == 'failure' && steps.check_changes.outputs.changes_made == 'true' && env.is_fork == 'true' | ||
id: commit_to_fork | ||
run: | | ||
git config --local user.email "action@github.com" | ||
git config --local user.name "Auto Format Bot" | ||
|
||
git commit -m "Apply automatic formatting fixes | ||
|
||
Fixes applied by @auto-format-bot in response to: | ||
${{ github.event.comment.html_url }} | ||
|
||
Original PR: #${{ github.event.issue.number }} | ||
|
||
Changes applied: | ||
$(git diff --name-only HEAD~1)" | ||
|
||
git push origin "${{ env.head_ref }}" | ||
|
||
- name: Final validation | ||
run: | | ||
echo "Running final validation..." | ||
./gradlew check -x test | ||
|
||
- name: Create PR for fixes (same-repo only) | ||
if: steps.initial-validation.outcome == 'failure' && steps.check_changes.outputs.changes_made == 'true' && env.is_fork == 'false' | ||
id: create_pr | ||
run: | | ||
PR_BODY="## Automatic Formatting Fixes | ||
|
||
This PR applies automatic formatting fixes to address validation failures in #${{ github.event.issue.number }}. | ||
|
||
### 📝 Details | ||
- **Triggered by**: ${{ github.event.comment.html_url }} | ||
- **Original PR**: #${{ github.event.issue.number }} | ||
- **Fix branch**: \`${{ env.fix_branch }}\` | ||
|
||
### 🚀 Next Steps | ||
Review and merge this PR to apply the formatting fixes to the original branch. | ||
|
||
--- | ||
*This PR was created automatically by the Auto Format Bot*" | ||
|
||
PR_URL=$(gh pr create \ | ||
--repo ${{ github.repository }} \ | ||
--title "Apply formatting fixes to #${{ github.event.issue.number }}" \ | ||
--body "$PR_BODY" \ | ||
--base "${{ env.head_ref }}" \ | ||
--head "${{ env.fix_branch }}") | ||
|
||
PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$') | ||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT | ||
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT | ||
|
||
- name: Add success reaction | ||
if: success() | ||
run: | | ||
# Add success reaction | ||
gh api repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \ | ||
--method POST \ | ||
--input - <<< '{"content":"+1"}' | ||
|
||
- name: Comment on PR with success (fixes applied to same-repo) | ||
if: success() && steps.initial-validation.outcome == 'failure' && steps.check_changes.outputs.changes_made == 'true' && env.is_fork == 'false' | ||
run: | | ||
gh pr comment ${{ github.event.issue.number }} --repo ${{ github.repository }} --body "## Formatting Fixes Applied | ||
|
||
The formatting bot has successfully created a PR with formatting fixes! | ||
|
||
### 📝 Details | ||
- **Triggered by**: ${{ github.event.comment.html_url }} | ||
- **Fix PR**: #${{ steps.create_pr.outputs.pr_number }} | ||
|
||
### 🚀 Next Steps | ||
Review and merge PR #${{ steps.create_pr.outputs.pr_number }} to apply the formatting fixes to this branch. | ||
|
||
--- | ||
*This was performed automatically by the Auto Format Bot*" | ||
|
||
- name: Comment on PR with success (fixes applied to fork) | ||
if: success() && steps.initial-validation.outcome == 'failure' && steps.check_changes.outputs.changes_made == 'true' && env.is_fork == 'true' | ||
run: | | ||
gh pr comment ${{ github.event.issue.number }} --repo ${{ github.repository }} --body "## Formatting Fixes Applied | ||
|
||
The formatting bot has commited the formatting fixes to this PR! | ||
|
||
### 📝 Details | ||
- **Triggered by**: ${{ github.event.comment.html_url }} | ||
- **Action taken**: Direct commit to this PR branch | ||
|
||
--- | ||
*This was performed automatically by the Auto Format Bot*" | ||
|
||
- name: Comment on PR with success (no fixes needed) | ||
if: success() && steps.initial-validation.outcome == 'success' | ||
run: | | ||
gh pr comment ${{ github.event.issue.number }} --repo ${{ github.repository }} --body "## No Formatting Issues Found | ||
|
||
The formatting bot has validated this PR and found no issues! | ||
|
||
### 📝 Details | ||
- **Triggered by**: ${{ github.event.comment.html_url }} | ||
|
||
The PR is ready for review! | ||
|
||
--- | ||
*This was performed automatically by the Auto Format Bot*" | ||
|
||
- name: Comment on PR with success (fixes made but no changes) | ||
if: success() && steps.initial-validation.outcome == 'failure' && steps.check_changes.outputs.changes_made == 'false' | ||
run: | | ||
gh pr comment ${{ github.event.issue.number }} --repo ${{ github.repository }} --body "## Formatting Issues Detected (No Auto-fixes Available) | ||
|
||
The formatting bot found issues but was unable to automatically fix them. | ||
|
||
### 📝 Details | ||
- **Triggered by**: ${{ github.event.comment.html_url }} | ||
|
||
**Recommendation**: Review the validation failures manually and apply fixes as needed. | ||
|
||
--- | ||
*This was performed automatically by the Auto Format Bot*" | ||
|
||
- name: Add failure reaction | ||
if: failure() | ||
run: | | ||
# Add failure reaction | ||
gh api repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \ | ||
--method POST \ | ||
--input - <<< '{"content":"-1"}' | ||
|
||
- name: Comment on PR with failure | ||
if: failure() | ||
run: | | ||
gh pr comment ${{ github.event.issue.number }} --repo ${{ github.repository }} --body "## Formatting Failed | ||
|
||
The formatting bot encountered issues while processing this PR. | ||
|
||
### Next Steps: | ||
1. Check the workflow logs for specific error details | ||
2. Fix any issues manually if needed | ||
3. Re-trigger the bot with \`/format-fix apply\` | ||
|
||
### 📝 Details | ||
- **Triggered by**: ${{ github.event.comment.html_url }} | ||
- **Files processed**: ${{ steps.changed-files.outputs.all || 'None detected' }} | ||
|
||
--- | ||
*This was performed automatically by the Auto Format Bot*" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.