change UI'e theme color to green #13
This file contains 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: Auto-Fix Tagged Issues with OpenHands | |
on: | |
workflow_call: | |
inputs: | |
issue_number: | |
required: true | |
type: number | |
secrets: | |
LLM_MODELS: | |
required: true | |
LLM_API_KEY: | |
required: true | |
LLM_BASE_URL: | |
required: false | |
PAT_TOKEN: | |
required: true | |
PAT_USERNAME: | |
required: true | |
issues: | |
types: [labeled] | |
permissions: | |
contents: write | |
pull-requests: write | |
issues: write | |
jobs: | |
auto-fix: | |
if: github.event_name == 'workflow_call' || github.event.label.name == 'fix-me' | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: '3.12' | |
- name: Check required environment variables | |
env: | |
LLM_MODELS: ${{ secrets.LLM_MODELS }} | |
LLM_API_KEY: ${{ secrets.LLM_API_KEY }} | |
LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} | |
PAT_TOKEN: ${{ secrets.PAT_TOKEN }} | |
PAT_USERNAME: ${{ secrets.PAT_USERNAME }} | |
run: | | |
required_vars=("LLM_MODELS" "LLM_API_KEY" "PAT_TOKEN" "PAT_USERNAME") | |
for var in "${required_vars[@]}"; do | |
if [ -z "${!var}" ]; then | |
echo "Error: Required environment variable $var is not set." | |
exit 1 | |
fi | |
done | |
- name: Set issue number | |
run: echo "ISSUE_NUMBER=${{ github.event.issue.number || inputs.issue_number }}" >> $GITHUB_ENV | |
- name: Comment on issue with start message | |
uses: actions/github-script@v7 | |
with: | |
github-token: ${{secrets.GITHUB_TOKEN}} | |
script: | | |
github.rest.issues.createComment({ | |
issue_number: ${{ env.ISSUE_NUMBER }}, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `OpenHands started fixing the issue! You can monitor the progress [here](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).` | |
}); | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install git+https://github.com/JiseungHong/openhands-resolver.git | |
- name: Attempt to resolve issue | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
LLM_MODELS: ${{ secrets.LLM_MODELS }} | |
LLM_API_KEY: ${{ secrets.LLM_API_KEY }} | |
LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} | |
PYTHONPATH: "" | |
run: | | |
cd /tmp && python -m openhands_resolver.resolve_issues \ | |
--repo ${{ github.repository }} \ | |
--issue-numbers ${{ env.ISSUE_NUMBER }} | |
- name: Check resolution results | |
id: check_results | |
run: | | |
if cd /tmp && grep -q '"success":true' output/output1.jsonl; then | |
echo "MODEL1_RESOLUTION_SUCCESS=true" >> $GITHUB_OUTPUT | |
else | |
echo "MODEL1_RESOLUTION_SUCCESS=false" >> $GITHUB_OUTPUT | |
fi | |
if cd /tmp && grep -q '"success":true' output/output2.jsonl; then | |
echo "MODEL2_RESOLUTION_SUCCESS=true" >> $GITHUB_OUTPUT | |
else | |
echo "MODEL2_RESOLUTION_SUCCESS=false" >> $GITHUB_OUTPUT | |
fi | |
- name: Create draft PR or branch | |
env: | |
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }} | |
LLM_MODELS: ${{ secrets.LLM_MODELS }} | |
LLM_API_KEY: ${{ secrets.LLM_API_KEY }} | |
LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} | |
PYTHONPATH: "" | |
run: | | |
if [ "${{ steps.check_result.outputs.MODEL1_RESOLUTION_SUCCESS }}" == "true" ]; then | |
cd /tmp && python -m openhands_resolver.send_pull_request \ | |
--issue-number ${{ env.ISSUE_NUMBER }} \ | |
--pr-type draft | tee pr_result1.txt && \ | |
--model-number 1 \ | |
grep "draft created" pr_result1.txt | sed 's/.*\///g' > pr_number1.txt | |
else | |
cd /tmp && python -m openhands_resolver.send_pull_request \ | |
--issue-number ${{ env.ISSUE_NUMBER }} \ | |
--pr-type branch \ | |
--model-number 1 \ | |
--send-on-failure | tee branch_result.txt && \ | |
grep "branch created" branch_result.txt | sed 's/.*\///g; s/.expand=1//g' > branch_name1.txt | |
fi | |
if [ "${{ steps.check_result.outputs.MODEL2_RESOLUTION_SUCCESS }}" == "true" ]; then | |
cd /tmp && python -m openhands_resolver.send_pull_request \ | |
--issue-number ${{ env.ISSUE_NUMBER }} \ | |
--pr-type draft | tee pr_result2.txt && \ | |
--model-number 2 \ | |
grep "draft created" pr_result2.txt | sed 's/.*\///g' > pr_number2.txt | |
else | |
cd /tmp && python -m openhands_resolver.send_pull_request \ | |
--issue-number ${{ env.ISSUE_NUMBER }} \ | |
--pr-type branch \ | |
--model-number 2 \ | |
--send-on-failure | tee branch_result.txt && \ | |
grep "branch created" branch_result.txt | sed 's/.*\///g; s/.expand=1//g' > branch_name2.txt | |
fi | |
- name: Comment on issue | |
uses: actions/github-script@v7 | |
with: | |
github-token: ${{secrets.GITHUB_TOKEN}} | |
script: | | |
const fs = require('fs'); | |
const issueNumber = ${{ env.ISSUE_NUMBER }}; | |
const success1 = "${{ steps.check_result.outputs.MODEL1_RESOLUTION_SUCCESS }}" === "true"; | |
let prNumber1 = ''; | |
let branchName1 = ''; | |
try { | |
if (success1) { | |
prNumber1 = fs.readFileSync('/tmp/pr_number1.txt', 'utf8').trim(); | |
} else { | |
branchName1 = fs.readFileSync('/tmp/branch_name1.txt', 'utf8').trim(); | |
} | |
} catch (error) { | |
console.error('Error reading file:', error); | |
} | |
if (success1 && prNumber1) { | |
github.rest.issues.createComment({ | |
issue_number: issueNumber, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `A potential fix has been generated and a draft PR #${prNumber1} has been created. Please review the changes.` | |
}); | |
} else if (!success1 && branchName1) { | |
github.rest.issues.createComment({ | |
issue_number: issueNumber, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `An attempt was made to automatically fix this issue, but it was unsuccessful. A branch named '${branchName1}' has been created with the attempted changes. You can view the branch [here](https://github.com/${context.repo.owner}/${context.repo.repo}/tree/${branchName1}). Manual intervention may be required.` | |
}); | |
} else { | |
github.rest.issues.createComment({ | |
issue_number: issueNumber, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `The workflow to fix this issue encountered an error. Please check the workflow logs for more information.` | |
}); | |
} | |
const success2 = "${{ steps.check_result.outputs.MODEL2_RESOLUTION_SUCCESS }}" === "true"; | |
let prNumber2 = ''; | |
let branchName2 = ''; | |
try { | |
if (success2) { | |
prNumber2 = fs.readFileSync('/tmp/pr_number2.txt', 'utf8').trim(); | |
} else { | |
branchName2 = fs.readFileSync('/tmp/branch_name2.txt', 'utf8').trim(); | |
} | |
} catch (error) { | |
console.error('Error reading file:', error); | |
} | |
if (success2 && prNumber2) { | |
github.rest.issues.createComment({ | |
issue_number: issueNumber, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `A potential fix has been generated and a draft PR #${prNumber2} has been created. Please review the changes.` | |
}); | |
} else if (!success2 && branchName2) { | |
github.rest.issues.createComment({ | |
issue_number: issueNumber, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `An attempt was made to automatically fix this issue, but it was unsuccessful. A branch named '${branchName2}' has been created with the attempted changes. You can view the branch [here](https://github.com/${context.repo.owner}/${context.repo.repo}/tree/${branchName2}). Manual intervention may be required.` | |
}); | |
} else { | |
github.rest.issues.createComment({ | |
issue_number: issueNumber, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
body: `The workflow to fix this issue encountered an error. Please check the workflow logs for more information.` | |
}); | |
} | |
- name: Upload /tmp/output directory as artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: output-directory | |
path: /tmp/output | |
if-no-files-found: warn | |