diff --git a/.github/workflows/pr-review-by-openhands.yml b/.github/workflows/pr-review-by-openhands.yml deleted file mode 100644 index 68be2d315f..0000000000 --- a/.github/workflows/pr-review-by-openhands.yml +++ /dev/null @@ -1,65 +0,0 @@ ---- -name: PR Review by OpenHands - -on: - # Use pull_request for same-repo PRs so workflow changes can self-verify in PRs. - pull_request: - types: [opened, ready_for_review, labeled, review_requested] - # Use pull_request_target for fork PRs. - # The bot token used here is intentionally scoped to PR review operations, - # so the remaining blast radius is bounded even though PR content is untrusted. - pull_request_target: - types: [opened, ready_for_review, labeled, review_requested] - -permissions: - contents: read - pull-requests: write - issues: write - -jobs: - pr-review: - # Run on same-repo PRs via pull_request and on fork PRs via pull_request_target. - # Trigger when one of the following conditions is met: - # 1. A new non-draft PR is opened by a non-first-time contributor, OR - # 2. A draft PR is converted to ready for review by a non-first-time contributor, OR - # 3. The 'review-this' label is added, OR - # 4. openhands-agent or all-hands-bot is requested as a reviewer - # Note: FIRST_TIME_CONTRIBUTOR and NONE PRs require manual trigger via label/reviewer request. - if: | - ( - ( - github.event_name == 'pull_request' && - github.event.pull_request.head.repo.full_name == github.repository - ) || - ( - github.event_name == 'pull_request_target' && - github.event.pull_request.head.repo.full_name != github.repository - ) - ) && - ( - (github.event.action == 'opened' && github.event.pull_request.draft == false && github.event.pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR' && github.event.pull_request.author_association != 'NONE') || - (github.event.action == 'ready_for_review' && github.event.pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR' && github.event.pull_request.author_association != 'NONE') || - (github.event.action == 'labeled' && github.event.label.name == 'review-this') || - ( - github.event.action == 'review_requested' && - ( - github.event.requested_reviewer.login == 'openhands-agent' || - github.event.requested_reviewer.login == 'all-hands-bot' - ) - ) - ) - concurrency: - group: pr-review-${{ github.event.pull_request.number }} - cancel-in-progress: true - runs-on: ubuntu-24.04 - steps: - - name: Run PR Review - uses: OpenHands/extensions/plugins/pr-review@main - with: - llm-model: litellm_proxy/openai/gpt-5.5 - llm-base-url: https://llm-proxy.app.all-hands.dev - # Enable experimental sub-agent delegation for file-level reviews - use-sub-agents: 'true' - llm-api-key: ${{ secrets.LLM_API_KEY }} - github-token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC || github.token }} - lmnr-api-key: ${{ secrets.LMNR_SKILLS_API_KEY }} diff --git a/.github/workflows/pr-review-evaluation.yml b/.github/workflows/pr-review-evaluation.yml deleted file mode 100644 index 3239596c13..0000000000 --- a/.github/workflows/pr-review-evaluation.yml +++ /dev/null @@ -1,85 +0,0 @@ ---- -name: PR Review Evaluation - -# This workflow evaluates how well PR review comments were addressed. -# It runs when a PR is closed to assess review effectiveness. -# -# Security note: pull_request_target is safe here because: -# 1. Only triggers on PR close (not on code changes) -# 2. Does not checkout PR code - only downloads artifacts from trusted workflow runs -# 3. Runs evaluation scripts from the extensions repo, not from the PR - -on: - pull_request_target: - types: [closed] - -permissions: - contents: read - pull-requests: read - -jobs: - evaluate: - runs-on: ubuntu-24.04 - env: - PR_NUMBER: ${{ github.event.pull_request.number }} - REPO_NAME: ${{ github.repository }} - PR_MERGED: ${{ github.event.pull_request.merged }} - - steps: - - name: Download review trace artifact - id: download-trace - uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 - continue-on-error: true - with: - workflow: pr-review-by-openhands.yml - name: pr-review-trace-${{ github.event.pull_request.number }} - path: trace-info - search_artifacts: true - if_no_artifact_found: warn - - - name: Check if trace file exists - id: check-trace - run: | - if [ -f "trace-info/laminar_trace_info.json" ]; then - echo "trace_exists=true" >> $GITHUB_OUTPUT - echo "Found trace file for PR #$PR_NUMBER" - else - echo "trace_exists=false" >> $GITHUB_OUTPUT - echo "No trace file found for PR #$PR_NUMBER - skipping evaluation" - fi - - # Always checkout main branch for security - cannot test script changes in PRs - - name: Checkout extensions repository - if: steps.check-trace.outputs.trace_exists == 'true' - uses: actions/checkout@v6 - with: - repository: OpenHands/extensions - path: extensions - - - name: Set up Python - if: steps.check-trace.outputs.trace_exists == 'true' - uses: actions/setup-python@v6 - with: - python-version: '3.12' - - - name: Install dependencies - if: steps.check-trace.outputs.trace_exists == 'true' - run: pip install lmnr - - - name: Run evaluation - if: steps.check-trace.outputs.trace_exists == 'true' - env: - # Script expects LMNR_PROJECT_API_KEY; org secret is named LMNR_SKILLS_API_KEY - LMNR_PROJECT_API_KEY: ${{ secrets.LMNR_SKILLS_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - python extensions/plugins/pr-review/scripts/evaluate_review.py \ - --trace-file trace-info/laminar_trace_info.json - - - name: Upload evaluation logs - uses: actions/upload-artifact@v7 - if: always() && steps.check-trace.outputs.trace_exists == 'true' - with: - name: pr-review-evaluation-${{ github.event.pull_request.number }} - path: '*.log' - retention-days: 30 diff --git a/AGENTS.md b/AGENTS.md index e0f0c8c4b2..9df0c84929 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -115,7 +115,7 @@ When reviewing code, provide constructive feedback: - Anthropic malformed tool-use/tool-result history errors (for example, missing or duplicated ``tool_result`` blocks) are intentionally mapped to a dedicated `LLMMalformedConversationHistoryError` and caught separately in `Agent.step()`, so recovery can still use condensation while logs preserve that this was malformed history rather than a true context-window overflow. - AgentSkills progressive disclosure goes through `AgentContext.get_system_message_suffix()` into ``, and `openhands.sdk.context.skills.to_prompt()` truncates each prompt description to 1024 characters because the AgentSkills specification caps `description` at 1-1024 characters. - Workspace-wide uv resolver guardrails belong in the repository root `[tool.uv]` table. When `exclude-newer` is configured there, `uv lock` persists it into the root `uv.lock` `[options]` section as both an absolute cutoff and `exclude-newer-span`, and `uv sync --frozen` continues to use that locked workspace state. -- `pr-review-by-openhands` delegates to `OpenHands/extensions/plugins/pr-review@main`. Repo-specific reviewer instructions live in `.agents/skills/custom-codereview-guide.md`, and because task-trigger matching is substring-based, that `/codereview` skill is also auto-injected for the workflow's `/codereview-roasted` prompt. +- PR code review is handled via OpenHands Cloud automation (not a GitHub Actions workflow). Repo-specific reviewer instructions live in `.agents/skills/custom-codereview-guide.md`. The automation triggers on `ready_for_review` (established contributors), when `all-hands-bot` is requested as a reviewer, and when the `review-this` label is added. - Release PR reviewer guidance now requires checking the latest PR-specific `Run tests`, `Run Examples Scripts`, and `Run Integration Tests` results/comments before approval; if any are missing, stale, ambiguous, skipped, or failing, the bot should leave a COMMENT and defer to human maintainer review. - Directory-based runnable examples under `examples/` should expose their entrypoint as `main.py`, and `tests/examples/test_examples.py` should explicitly list the example directory in `_TARGET_DIRECTORIES` so the non-recursive example workflow collects it without accidentally running helper modules. - The duplicate-issue automation scripts should validate `owner/repo` arguments before interpolating GitHub API paths, handle per-issue auto-close failures without aborting the whole batch, and keep `app_conversation_id` paths unquoted because OpenHands conversation IDs are already canonicalized for those endpoints.