Skip to content
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

feat: set review data to github actions output #853

Merged
merged 8 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/docs/usage-guide/automations_and_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,15 @@ Specifically, start by setting the following environment variables:
github_action_config.auto_review: "true" # enable\disable auto review
github_action_config.auto_describe: "true" # enable\disable auto describe
github_action_config.auto_improve: "true" # enable\disable auto improve
github_action_config.enable_output: "true" # enable\disable github actions output parameter
```
`github_action_config.auto_review`, `github_action_config.auto_describe` and `github_action_config.auto_improve` are used to enable/disable automatic tools that run when a new PR is opened.
If not set, the default configuration is for all three tools to run automatically when a new PR is opened.

`github_action_config.enable_output` are used to enable/disable github actions [output parameter](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-docker-container-and-javascript-actions) (default is `true`).
Review result is output as JSON to `steps.{step-id}.outputs.review` property.
The JSON structure is equivalent to the yaml data structure defined in [pr_reviewer_prompts.toml](https://github.com/idubnori/pr-agent/blob/main/pr_agent/settings/pr_reviewer_prompts.toml).

Note that you can give additional config parameters by adding environment variables to `.github/workflows/pr_agent.yml`, or by using a `.pr_agent.toml` [configuration file](https://pr-agent-docs.codium.ai/usage-guide/configuration_options/#global-configuration-file) in the root of your repo

For example, you can set an environment variable: `pr_description.publish_labels=false`, or add a `.pr_agent.toml` file with the following content:
Expand Down
13 changes: 13 additions & 0 deletions pr_agent/algo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import difflib
import json
import os
import re
import textwrap
from datetime import datetime
Expand Down Expand Up @@ -661,3 +662,15 @@ def find_line_number_of_relevant_line_in_file(diff_files: List[FilePatchInfo],
absolute_position = start2 + delta - 1
break
return position, absolute_position

def github_action_output(output_data: dict, key_name: str):
try:
if not get_settings().get('github_action_config.enable_output', False):
return

key_data = output_data.get(key_name, {})
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
print(f"{key_name}={json.dumps(key_data, indent=None, ensure_ascii=False)}", file=fh)
except Exception as e:
get_logger().error(f"Failed to write to GitHub Action output: {e}")
return
2 changes: 2 additions & 0 deletions pr_agent/servers/github_action_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ async def run_action():
get_settings().set("OPENAI.ORG", OPENAI_ORG)
get_settings().set("GITHUB.USER_TOKEN", GITHUB_TOKEN)
get_settings().set("GITHUB.DEPLOYMENT_TYPE", "user")
enable_output = get_setting_or_env("GITHUB_ACTION_CONFIG.ENABLE_OUTPUT", True)
get_settings().set("GITHUB_ACTION_CONFIG.ENABLE_OUTPUT", enable_output)

# Load the event payload
try:
Expand Down
1 change: 1 addition & 0 deletions pr_agent/settings/configuration.toml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ try_fix_invalid_inline_comments = true
# auto_review = true # set as env var in .github/workflows/pr-agent.yaml
# auto_describe = true # set as env var in .github/workflows/pr-agent.yaml
# auto_improve = true # set as env var in .github/workflows/pr-agent.yaml
# enable_output = true # set as env var in .github/workflows/pr-agent.yaml

[github_app]
# these toggles allows running the github app from custom deployments
Expand Down
3 changes: 2 additions & 1 deletion pr_agent/tools/pr_reviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
from pr_agent.algo.token_handler import TokenHandler
from pr_agent.algo.utils import convert_to_markdown, load_yaml, ModelType
from pr_agent.algo.utils import convert_to_markdown, github_action_output, load_yaml, ModelType
from pr_agent.config_loader import get_settings
from pr_agent.git_providers import get_git_provider
from pr_agent.git_providers.git_provider import IncrementalPR, get_main_pr_language
Expand Down Expand Up @@ -192,6 +192,7 @@ def _prepare_pr_review(self) -> str:
data = load_yaml(self.prediction.strip(),
keys_fix_yaml=["estimated_effort_to_review_[1-5]:", "security_concerns:", "possible_issues:",
"relevant_file:", "relevant_line:", "suggestion:"])
github_action_output(data, 'review')

if 'code_feedback' in data:
code_feedback = data['code_feedback']
Expand Down
50 changes: 50 additions & 0 deletions tests/unittest/test_github_action_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
import json
from pr_agent.algo.utils import get_settings, github_action_output

class TestGitHubOutput:
def test_github_action_output_enabled(self, monkeypatch, tmp_path):
get_settings().set('GITHUB_ACTION_CONFIG.ENABLE_OUTPUT', True)
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
output_data = {'key1': {'value1': 1, 'value2': 2}}
key_name = 'key1'

github_action_output(output_data, key_name)

with open(str(tmp_path / 'output'), 'r') as f:
env_value = f.read()

actual_key = env_value.split('=')[0]
actual_data = json.loads(env_value.split('=')[1])

assert actual_key == key_name
assert actual_data == output_data[key_name]

def test_github_action_output_disabled(self, monkeypatch, tmp_path):
get_settings().set('GITHUB_ACTION_CONFIG.ENABLE_OUTPUT', False)
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
output_data = {'key1': {'value1': 1, 'value2': 2}}
key_name = 'key1'

github_action_output(output_data, key_name)

assert not os.path.exists(str(tmp_path / 'output'))

def test_github_action_output_notset(self, monkeypatch, tmp_path):
# not set config
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
output_data = {'key1': {'value1': 1, 'value2': 2}}
key_name = 'key1'

github_action_output(output_data, key_name)

assert not os.path.exists(str(tmp_path / 'output'))

def test_github_action_output_error_case(self, monkeypatch, tmp_path):
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
output_data = None # invalid data
key_name = 'key1'

github_action_output(output_data, key_name)

assert not os.path.exists(str(tmp_path / 'output'))
Loading