From e2b54894954e40b933023e51b77662f277e8c6b2 Mon Sep 17 00:00:00 2001 From: mrT23 Date: Mon, 7 Oct 2024 09:13:17 +0300 Subject: [PATCH] feat: add error handling for invalid repo settings configuration - Implement error handling for invalid TOML configurations in repo settings. - Log warnings and send comments to PRs when configuration errors occur. - Introduce `handle_configurations_errors` function to manage error reporting. - Ensure compatibility with different markdown formats for error messages. --- pr_agent/git_providers/utils.py | 61 +++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/pr_agent/git_providers/utils.py b/pr_agent/git_providers/utils.py index 8a9579cf..10beb1bb 100644 --- a/pr_agent/git_providers/utils.py +++ b/pr_agent/git_providers/utils.py @@ -27,18 +27,27 @@ def apply_repo_settings(pr_url): except Exception: pass + error_local = None if repo_settings: repo_settings_file = None - fd, repo_settings_file = tempfile.mkstemp(suffix='.toml') - os.write(fd, repo_settings) - new_settings = Dynaconf(settings_files=[repo_settings_file]) - for section, contents in new_settings.as_dict().items(): - section_dict = copy.deepcopy(get_settings().as_dict().get(section, {})) - for key, value in contents.items(): - section_dict[key] = value - get_settings().unset(section) - get_settings().set(section, section_dict, merge=False) - get_logger().info(f"Applying repo settings:\n{new_settings.as_dict()}") + category = 'local' + try: + fd, repo_settings_file = tempfile.mkstemp(suffix='.toml') + os.write(fd, repo_settings) + new_settings = Dynaconf(settings_files=[repo_settings_file]) + for section, contents in new_settings.as_dict().items(): + section_dict = copy.deepcopy(get_settings().as_dict().get(section, {})) + for key, value in contents.items(): + section_dict[key] = value + get_settings().unset(section) + get_settings().set(section, section_dict, merge=False) + get_logger().info(f"Applying repo settings:\n{new_settings.as_dict()}") + except Exception as e: + get_logger().warning(f"Failed to apply repo {category} settings, error: {str(e)}") + error_local = {'error': str(e), 'settings': repo_settings, 'category': category} + + if error_local: + handle_configurations_errors([error_local], git_provider) except Exception as e: get_logger().exception("Failed to apply repo settings", e) finally: @@ -49,10 +58,40 @@ def apply_repo_settings(pr_url): get_logger().error(f"Failed to remove temporary settings file {repo_settings_file}", e) # enable switching models with a short definition - if get_settings().config.model.lower()=='claude-3-5-sonnet': + if get_settings().config.model.lower() == 'claude-3-5-sonnet': set_claude_model() +def handle_configurations_errors(config_errors, git_provider): + try: + if not any(config_errors): + return + + for err in config_errors: + if err: + configuration_file_content = err['settings'].decode() + err_message = err['error'] + config_type = err['category'] + header = f"❌ **PR-Agent failed to apply '{config_type}' repo settings**" + body = f"{header}\n\nThe configuration file needs to be a valid [TOML](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/), please fix it.\n\n" + body += f"___\n\n**Error message:**\n`{err_message}`\n\n" + if git_provider.is_supported("gfm_markdown"): + body += f"\n\n
Configuration content:\n\n```toml\n{configuration_file_content}\n```\n\n
" + else: + body += f"\n\n**Configuration content:**\n\n```toml\n{configuration_file_content}\n```\n\n" + get_logger().warning(f"Sending a 'configuration error' comment to the PR", artifact={'body': body}) + # git_provider.publish_comment(body) + if hasattr(git_provider, 'publish_persistent_comment'): + git_provider.publish_persistent_comment(body, + initial_header=header, + update_header=False, + final_update_message=False) + else: + git_provider.publish_comment(body) + except Exception as e: + get_logger().exception(f"Failed to handle configurations errors", e) + + def set_claude_model(): """ set the claude-sonnet-3.5 model easily (even by users), just by stating: --config.model='claude-3-5-sonnet'