diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml index ee409d7..021cae4 100644 --- a/.github/workflows/review.yml +++ b/.github/workflows/review.yml @@ -1,4 +1,4 @@ -name: Test OpenHands AI Action +name: Review Pull Request on: pull_request: @@ -7,7 +7,7 @@ on: - 'action.yml' jobs: - test-action: + review-pr: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -19,9 +19,41 @@ jobs: run: git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} > pr_diff.txt - name: Upload PR Diff Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pr-diff path: pr_diff.txt + - name: Validate GitHub Token + env: + REVIEW_BOT_GITHUB_TOKEN: ${{ secrets.REVIEW_BOT_GITHUB_TOKEN }} + shell: bash + run: | + if [ -z "$REVIEW_BOT_GITHUB_TOKEN" ]; then + echo "::error::REVIEW_BOT_GITHUB_TOKEN secret is not set or is empty. Please configure it in repository/organization secrets." + exit 1 + else + echo "REVIEW_BOT_GITHUB_TOKEN is set." + fi + + - name: Automatically Review Pull Request + id: openhands_valid + uses: ./ + with: + prompt: | + You are a coding expert that reviews pull requests and provides feedback. + Please execute the following steps: + 1. Verify that the environment variable GITHUB_TOKEN is set, if not stop and report an error. + 2. Review the current pull request ${{ github.event.pull_request.number }} + 3. if the PR needs code changes,send an overall PR review comment and each individual line-level comment to Github using Github REST API. + or else if the PR is overall good without needing any code changes, + just send an overall comment and a PR approval to Github using Github REST API. + llm_api_key: ${{ secrets.LLM_API_KEY }} + log_all_events: "true" + github_token: ${{ secrets.REVIEW_BOT_GITHUB_TOKEN }} + additional_env: | + { + "SELECTED_REPO": "${{ github.repository }}" + } + \ No newline at end of file diff --git a/.openhands/microagents/knowledge/review_pr.md b/.openhands/microagents/knowledge/review_pr.md new file mode 100644 index 0000000..1945c1e --- /dev/null +++ b/.openhands/microagents/knowledge/review_pr.md @@ -0,0 +1,154 @@ +--- +name: review_pr +type: task +version: 1.0.1 +agent: CodeActAgent +triggers: + - review pr + - review pull request + - pr review + - code review +inputs: + - name: PR_NUMBER + description: 'The number of the pull request to review (e.g., 158)' + required: true +--- + +# PR Review Task + +This task guides you through reviewing pull requests in ${{ SELECTED_REPO }} according to project standards. + +## Finding file changes +When reviewing file changes, instead of diffing with default branch such as `main` please diff against the base branch of the PR. + +## Review Steps and Guidelines for Each Step + +A high quality code review addresses 3 aspects: + +1. is it the appropriate problem (goal)? (Pass 1) +2. is it the concise and optimal solution? (Pass 2) +3. is it the high quality implementation? (Pass 3) + +For each pass, if needed, you will submit a PR-level comment and multiple line-level suggested changes via Github API. + +When everything is done, you will submit a Github pull request review to approve the PR via Github API. + +### **Review Pass 1: Is it the appropriate problem (goal)?**: +- Review the PR description and linked issues, +- Summarize the files changes and see if the PR description matches the changes +- If the PR description is not aligned with the changes, ask the author to clarify the goal of the PR +- If the PR description is aligned with the changes, proceed based on the understanding of the goal and the overall repository, +comment on whether the goal is the right goal. The right goal of a PR should be + - aligned with the overall repository goals, + - not duplicating an existing functionality + - should leverage the existing code and architecture unless it's intended for a upgrade/replacement/refactor + - should not reinvent the wheel: suggest using popular open source libraries if they exist + - should not over engineer: suggest using simple solutions if they exist + - should not over generalize such as extracting a piece of code logic into a library / component when they are only being used in one place + - should have proper sizing (not too big, not too small). + +Send *PR-level comment* to ask for clarification on the goal of the PR. ONLY proceed to next Review Pass if the goal is appropriate, otherwise wait for the author to respond. + +### **Review Pass 2: Is it the concise and optimal solution?**: + - Understand whether the commit is a small change that fixes a bug or a larger change that implements a new feature/component or refactors code. + - If it's a small change, skip architectural feedback, proceed to next step. + - If it's a larger change, provide feedback on the architectural choices made. + - Summarize the key goal and the solution to that key goal implemented in the PR + - Check if the author provided documentations about major design decisions + - Summarize the design decisions made by author + - Check completenesss: suggest alternative approaches if applicable, and create a table to compare the pros and cons of each approach + +Send *PR-level comment* to ask for clarification on the solution of the PR. ONLY proceed to next Review Pass if the solution is concise and optimal, otherwise wait for the author to respond. + +### **Review Pass 3: Is it the high quality implementation?**: +- Verify changes follow `.coderabbit.yaml` rules +- Suggest the right implementation if the current implementation is not the right one +- Suggest improvements to the code structure, naming conventions, and documentation +- Check for proper error handling +- Ensure consistent formatting +- Check completeness: suggest other part of the code that needs to be updated to complete the implementation. + +- **Documentation**: + - Verify README/docstring updates + - Check for new configuration needs + +- **Testing**: + - Confirm adequate test coverage + - If unit tests should be added, suggest the right tests to add + - Verify tests pass + +Send *line-level suggested change* to ask for fixing the implementation of the PR. ONLY proceed to next Review Pass if the implementation is high quality, otherwise wait for the author to respond. + +## Using Github API + +Please note: use markdown in the comment or reply for better readability if it's more than a plain text. + +### This is how you send *PR-level comment* with Github API + +```bash +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/OWNER/REPO/pulls/PULL_NUMBER/comments \ +-d '{ "body": "[COMMENT]", "commit_id": "'$(git rev-parse HEAD)'", "path": "[FILE_PATH]", "start_line": [START_LINE_NUMBER],"start_side":"[START_SIDE]","line": [LINE_NUMBER],"side":"[SIDE]"}' +``` + +Note: even for PR-level comment, you still need to provide the `commit_id`, `path`, and `line` to specify the comment location so that the comment will be shown in the PR page in the most relevant location. + +### This is how you send a *line-level suggested change* with github API + +```bash +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/OWNER/REPO/pulls/PULL_NUMBER/comments \ +-d '{ "body": "suggestion\n[SUGGESTED_CODE_WITH_ESCAPED_NEWLINES]\n", "commit_id": "'$(git rev-parse HEAD)'", "path": "[FILE_PATH]", "start_line": [START_LINE_NUMBER],"start_side":"[START_SIDE]","line": [LINE_NUMBER],"side":"[SIDE]"}' +``` + +### This is how you make a reply to a review comment + +```bash +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/OWNER/REPO/pulls/PULL_NUMBER/comments/COMMENT_ID/replies \ + -d '{"body":"[REPLY]"}' +``` + +### This is how you request changes to a PR + +```bash +# Example, use your own data +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/OWNER/REPO/pulls/PULL_NUMBER/reviews \ + -d '{"commit_id":"ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091","body":"This is close to perfect! Please address the suggested inline change.","event":"REQUEST_CHANGES","comments":[{"path":"file.md","position":6,"body":"Please add more information here, and fix this typo."}]}' +``` + +### This is how you approve a PR + +```bash +# Example, use your own data +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/OWNER/REPO/pulls/PULL_NUMBER/reviews \ + -d '{"commit_id":"ecdd80bb57125d7ba9641ffaa4d7d2c19d3f3091","body":"Great stuff!","event":"APPROVE","comments":[...]}' +``` + +## Reference Documents +- `./coderabbit.yaml` for review standards +- [Github API: Create a review comment](https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#create-a-review-comment) +- [Github API: Create a reply for a review comment](https://docs.github.com/en/rest/pulls/comments?apiVersion=2022-11-28#create-a-reply-for-a-review-comment) +- [Create a review](https://docs.github.com/en/rest/pulls/reviews?apiVersion=2022-11-28#create-a-review) diff --git a/.openhands/microagents/repo.md b/.openhands/microagents/repo.md new file mode 100644 index 0000000..35fa428 --- /dev/null +++ b/.openhands/microagents/repo.md @@ -0,0 +1,11 @@ +--- +name: repo +type: repo +agent: CodeActAgent +--- + +This repo contains the code for the Namefi Astra project. It is a web application that allows users to manage their domains and subdomains. Read ./README.md for more information. + +## Interacting with Github: use the Github API and GITHUB_TOKEN + +When interacting with github, use the github API and GITHUB_TOKEN. Do NOT use the github CLI and do NOT navigate to github.com with the web browser. \ No newline at end of file diff --git a/.openhands/setup.sh b/.openhands/setup.sh new file mode 100644 index 0000000..26fe7ab --- /dev/null +++ b/.openhands/setup.sh @@ -0,0 +1,3 @@ +#!/bin/bash +git config --global user.name "D3Serve Dev Team (via OpenHands)" +git config --global user.email "dev-team@d3serve.xyz" \ No newline at end of file diff --git a/CLI.md b/CLI.md new file mode 100644 index 0000000..9486969 --- /dev/null +++ b/CLI.md @@ -0,0 +1,63 @@ +# OpenHands Docker CLI Usage + +You can run the OpenHands agent via Docker with the following command and options: + +```sh +# Example Docker run command + +docker run -it \ + --pull=always \ + -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.33-nikolaik \ + -e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \ + -e LLM_API_KEY=$LLM_API_KEY \ + -e LLM_MODEL=$LLM_MODEL \ + -e LOG_ALL_EVENTS=true \ + -v $WORKSPACE_BASE:/opt/workspace_base \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v ~/.openhands-state:/.openhands-state \ + --add-host host.docker.internal:host-gateway \ + --name openhands-app-$(date +%Y%m%d%H%M%S) \ + docker.all-hands.dev/all-hands-ai/openhands:0.33 \ + python -m openhands.core.main --help +``` + +## OpenHands CLI Flags + +``` +usage: main.py [-h] [-v] [--config-file CONFIG_FILE] [-d DIRECTORY] [-t TASK] [-f FILE] [-c AGENT_CLS] [-i MAX_ITERATIONS] [-b MAX_BUDGET_PER_TASK] [--eval-output-dir EVAL_OUTPUT_DIR] [--eval-n-limit EVAL_N_LIMIT] [--eval-num-workers EVAL_NUM_WORKERS] + [--eval-note EVAL_NOTE] [-l LLM_CONFIG] [--agent-config AGENT_CONFIG] [-n NAME] [--eval-ids EVAL_IDS] [--no-auto-continue] [--selected-repo SELECTED_REPO] + +Run the agent via CLI + +options: + -h, --help show this help message and exit + -v, --version Show version information + --config-file CONFIG_FILE + Path to the config file (default: config.toml in the current directory) + -d DIRECTORY, --directory DIRECTORY + The working directory for the agent + -t TASK, --task TASK The task for the agent to perform + -f FILE, --file FILE Path to a file containing the task. Overrides -t if both are provided. + -c AGENT_CLS, --agent-cls AGENT_CLS + Name of the default agent to use + -i MAX_ITERATIONS, --max-iterations MAX_ITERATIONS + The maximum number of iterations to run the agent + -b MAX_BUDGET_PER_TASK, --max-budget-per-task MAX_BUDGET_PER_TASK + The maximum budget allowed per task, beyond which the agent will stop. + --eval-output-dir EVAL_OUTPUT_DIR + The directory to save evaluation output + --eval-n-limit EVAL_N_LIMIT + The number of instances to evaluate + --eval-num-workers EVAL_NUM_WORKERS + The number of workers to use for evaluation + --eval-note EVAL_NOTE + The note to add to the evaluation directory + -l LLM_CONFIG, --llm-config LLM_CONFIG + Replace default LLM ([llm] section in config.toml) config with the specified LLM config, e.g. "llama3" for [llm.llama3] section in config.toml + --agent-config AGENT_CONFIG + Replace default Agent ([agent] section in config.toml) config with the specified Agent config, e.g. "CodeAct" for [agent.CodeAct] section in config.toml + -n NAME, --name NAME Session name + --eval-ids EVAL_IDS The comma-separated list (in quotes) of IDs of the instances to evaluate + --no-auto-continue Disable auto-continue responses in headless mode (i.e. headless will read from stdin instead of auto-continuing) + --selected-repo SELECTED_REPO + GitHub repository to clone (format: owner/repo) \ No newline at end of file diff --git a/action.yml b/action.yml index fa5a6a0..2e07c56 100644 --- a/action.yml +++ b/action.yml @@ -39,6 +39,14 @@ inputs: These will be available in the container as environment variables. required: false default: '{}' + cli_args: + description: 'Additional CLI arguments to pass to the OpenHands agent' + required: false + default: '' + github_token: + description: 'GitHub token for API access (will be passed as GITHUB_TOKEN env var)' + required: false + default: '' runs: using: 'composite' @@ -64,6 +72,8 @@ runs: LOG_ALL_EVENTS: ${{ inputs.log_all_events }} ADDITIONAL_ENV: ${{ inputs.additional_env }} PROMPT: ${{ inputs.prompt }} + CLI_ARGS: ${{ inputs.cli_args }} + GITHUB_TOKEN: ${{ inputs.github_token }} run: | # Parse additional environment variables from JSON if [ "$ADDITIONAL_ENV" != "{}" ]; then @@ -75,12 +85,21 @@ runs: echo "No additional environment variables provided" fi + # Add GITHUB_TOKEN to EXTRA_ENV_ARGS if provided + if [ ! -z "$GITHUB_TOKEN" ]; then + EXTRA_ENV_ARGS="$EXTRA_ENV_ARGS -e GITHUB_TOKEN=$GITHUB_TOKEN" + echo "GITHUB_TOKEN will be passed to the container." + else + echo "GITHUB_TOKEN was not provided or is empty, not adding to EXTRA_ENV_ARGS." + fi + # Run Docker command with all environment variables + echo "Final EXTRA_ENV_ARGS (including GITHUB_TOKEN if set): $EXTRA_ENV_ARGS" echo "Running OpenHands with the following environment variables:" echo "- LLM_MODEL: $LLM_MODEL" echo "- LOG_ALL_EVENTS: $LOG_ALL_EVENTS" - echo "- Additional variables: $EXTRA_ENV_ARGS" echo "- Prompt: $PROMPT" + echo "- CLI Arguments: $CLI_ARGS" # Execute the task docker run -i \ @@ -95,4 +114,4 @@ runs: -v /var/run/docker.sock:/var/run/docker.sock \ --add-host host.docker.internal:host-gateway \ ${{ inputs.openhands_image }} \ - python -m openhands.core.main -t "${PROMPT}" \ No newline at end of file + python -m openhands.core.main -t "Run export GITHUB_TOKEN=$GITHUB_TOKEN and then ${PROMPT}" $CLI_ARGS \ No newline at end of file