mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-04 12:50:38 +08:00
Merge branch 'main' into main
This commit is contained in:
@ -74,7 +74,7 @@ to
|
|||||||
|
|
||||||
New tool [/Implement](https://qodo-merge-docs.qodo.ai/tools/implement/) (💎), which converts human code review discussions and feedback into ready-to-commit code changes.
|
New tool [/Implement](https://qodo-merge-docs.qodo.ai/tools/implement/) (💎), which converts human code review discussions and feedback into ready-to-commit code changes.
|
||||||
|
|
||||||
<kbd><img src="https://www.qodo.ai/images/pr_agent/implement1.png" width="512"></kbd>
|
<kbd><img src="https://www.qodo.ai/images/pr_agent/implement1.png?v=2" width="512"></kbd>
|
||||||
|
|
||||||
|
|
||||||
### Jan 1, 2025
|
### Jan 1, 2025
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
## Local and global metadata injection with multi-stage analysis
|
## Local and global metadata injection with multi-stage analysis
|
||||||
(1)
|
1\.
|
||||||
Qodo Merge initially retrieves for each PR the following data:
|
Qodo Merge initially retrieves for each PR the following data:
|
||||||
|
|
||||||
- PR title and branch name
|
- PR title and branch name
|
||||||
@ -11,7 +11,7 @@ Qodo Merge initially retrieves for each PR the following data:
|
|||||||
!!! tip "Tip: Organization-level metadata"
|
!!! tip "Tip: Organization-level metadata"
|
||||||
In addition to the inputs above, Qodo Merge can incorporate supplementary preferences provided by the user, like [`extra_instructions` and `organization best practices`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices). This information can be used to enhance the PR analysis.
|
In addition to the inputs above, Qodo Merge can incorporate supplementary preferences provided by the user, like [`extra_instructions` and `organization best practices`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices). This information can be used to enhance the PR analysis.
|
||||||
|
|
||||||
(2)
|
2\.
|
||||||
By default, the first command that Qodo Merge executes is [`describe`](https://qodo-merge-docs.qodo.ai/tools/describe/), which generates three types of outputs:
|
By default, the first command that Qodo Merge executes is [`describe`](https://qodo-merge-docs.qodo.ai/tools/describe/), which generates three types of outputs:
|
||||||
|
|
||||||
- PR Type (e.g. bug fix, feature, refactor, etc)
|
- PR Type (e.g. bug fix, feature, refactor, etc)
|
||||||
@ -49,8 +49,8 @@ __old hunk__
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
(3) The entire PR files that were retrieved are also used to expand and enhance the PR context (see [Dynamic Context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/)).
|
3\. The entire PR files that were retrieved are also used to expand and enhance the PR context (see [Dynamic Context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/)).
|
||||||
|
|
||||||
|
|
||||||
(4) All the metadata described above represents several level of cumulative analysis - ranging from hunk level, to file level, to PR level, to organization level.
|
4\. All the metadata described above represents several level of cumulative analysis - ranging from hunk level, to file level, to PR level, to organization level.
|
||||||
This comprehensive approach enables Qodo Merge AI models to generate more precise and contextually relevant suggestions and feedback.
|
This comprehensive approach enables Qodo Merge AI models to generate more precise and contextually relevant suggestions and feedback.
|
||||||
|
@ -14,6 +14,5 @@ An example result:
|
|||||||
|
|
||||||
{width=750}
|
{width=750}
|
||||||
|
|
||||||
**Notes**
|
!!! note "Language that are currently supported:"
|
||||||
|
Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.
|
|
||||||
|
@ -38,20 +38,20 @@ where `https://real_link_to_image` is the direct link to the image.
|
|||||||
Note that GitHub has a built-in mechanism of pasting images in comments. However, pasted image does not provide a direct link.
|
Note that GitHub has a built-in mechanism of pasting images in comments. However, pasted image does not provide a direct link.
|
||||||
To get a direct link to an image, we recommend using the following scheme:
|
To get a direct link to an image, we recommend using the following scheme:
|
||||||
|
|
||||||
1) First, post a comment that contains **only** the image:
|
1\. First, post a comment that contains **only** the image:
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
2) Quote reply to that comment:
|
2\. Quote reply to that comment:
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
3) In the screen opened, type the question below the image:
|
3\. In the screen opened, type the question below the image:
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
4) Post the comment, and receive the answer:
|
4\. Post the comment, and receive the answer:
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ Results obtained with the prompt above:
|
|||||||
|
|
||||||
## Configuration options
|
## Configuration options
|
||||||
|
|
||||||
`prompt`: the prompt for the tool. It should be a multi-line string.
|
- `prompt`: the prompt for the tool. It should be a multi-line string.
|
||||||
|
|
||||||
`num_code_suggestions_per_chunk`: number of code suggestions provided by the 'custom_prompt' tool, per chunk. Default is 4.
|
- `num_code_suggestions_per_chunk`: number of code suggestions provided by the 'custom_prompt' tool, per chunk. Default is 4.
|
||||||
|
|
||||||
`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true.
|
- `enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true.
|
||||||
|
@ -143,7 +143,7 @@ The marker `pr_agent:type` will be replaced with the PR type, `pr_agent:summary`
|
|||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
→
|
becomes
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ You can state a name of a specific component in the PR to get documentation only
|
|||||||
- `docs_style`: The exact style of the documentation (for python docstring). you can choose between: `google`, `numpy`, `sphinx`, `restructuredtext`, `plain`. Default is `sphinx`.
|
- `docs_style`: The exact style of the documentation (for python docstring). you can choose between: `google`, `numpy`, `sphinx`, `restructuredtext`, `plain`. Default is `sphinx`.
|
||||||
- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...".
|
- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...".
|
||||||
|
|
||||||
**Notes**
|
!!! note "Notes"
|
||||||
|
- The following languages are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
- Language that are currently fully supported: Python, Java, C++, JavaScript, TypeScript, C#.
|
|
||||||
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
|
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
|
||||||
|
@ -10,8 +10,9 @@ It leverages LLM technology to transform PR comments and review suggestions into
|
|||||||
|
|
||||||
### For Reviewers
|
### For Reviewers
|
||||||
|
|
||||||
Reviewers can request code changes by: <br>
|
Reviewers can request code changes by:
|
||||||
1. Selecting the code block to be modified. <br>
|
|
||||||
|
1. Selecting the code block to be modified.
|
||||||
2. Adding a comment with the syntax:
|
2. Adding a comment with the syntax:
|
||||||
```
|
```
|
||||||
/implement <code-change-description>
|
/implement <code-change-description>
|
||||||
@ -46,7 +47,8 @@ You can reference and implement changes from any comment by:
|
|||||||
Note that the implementation will occur within the review discussion thread.
|
Note that the implementation will occur within the review discussion thread.
|
||||||
|
|
||||||
|
|
||||||
**Configuration options** <br>
|
**Configuration options**
|
||||||
- Use `/implement` to implement code change within and based on the review discussion. <br>
|
|
||||||
- Use `/implement <code-change-description>` inside a review discussion to implement specific instructions. <br>
|
- Use `/implement` to implement code change within and based on the review discussion.
|
||||||
- Use `/implement <link-to-review-comment>` to indirectly call the tool from any comment. <br>
|
- Use `/implement <code-change-description>` inside a review discussion to implement specific instructions.
|
||||||
|
- Use `/implement <link-to-review-comment>` to indirectly call the tool from any comment.
|
||||||
|
@ -9,7 +9,7 @@ The tool can be triggered automatically every time a new PR is [opened](../usage
|
|||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
Note that the following features are available only for Qodo Merge💎 users:
|
!!! note "The following features are available only for Qodo Merge 💎 users:"
|
||||||
- The `Apply this suggestion` checkbox, which interactively converts a suggestion into a committable code comment
|
- The `Apply this suggestion` checkbox, which interactively converts a suggestion into a committable code comment
|
||||||
- The `More` checkbox to generate additional suggestions
|
- The `More` checkbox to generate additional suggestions
|
||||||
|
|
||||||
@ -53,9 +53,10 @@ num_code_suggestions_per_chunk = ...
|
|||||||
- The `pr_commands` lists commands that will be executed automatically when a PR is opened.
|
- The `pr_commands` lists commands that will be executed automatically when a PR is opened.
|
||||||
- The `[pr_code_suggestions]` section contains the configurations for the `improve` tool you want to edit (if any)
|
- The `[pr_code_suggestions]` section contains the configurations for the `improve` tool you want to edit (if any)
|
||||||
|
|
||||||
### Assessing Impact 💎
|
### Assessing Impact
|
||||||
|
>`💎 feature`
|
||||||
|
|
||||||
Note that Qodo Merge tracks two types of implementations:
|
Qodo Merge tracks two types of implementations for tracking implemented suggestions:
|
||||||
|
|
||||||
- Direct implementation - when the user directly applies the suggestion by clicking the `Apply` checkbox.
|
- Direct implementation - when the user directly applies the suggestion by clicking the `Apply` checkbox.
|
||||||
- Indirect implementation - when the user implements the suggestion in their IDE environment. In this case, Qodo Merge will utilize, after each commit, a dedicated logic to identify if a suggestion was implemented, and will mark it as implemented.
|
- Indirect implementation - when the user implements the suggestion in their IDE environment. In this case, Qodo Merge will utilize, after each commit, a dedicated logic to identify if a suggestion was implemented, and will mark it as implemented.
|
||||||
@ -68,8 +69,8 @@ In post-process, Qodo Merge counts the number of suggestions that were implement
|
|||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
## Suggestion tracking 💎
|
## Suggestion tracking
|
||||||
`Platforms supported: GitHub, GitLab`
|
>`💎 feature. Platforms supported: GitHub, GitLab`
|
||||||
|
|
||||||
Qodo Merge employs a novel detection system to automatically [identify](https://qodo-merge-docs.qodo.ai/core-abilities/impact_evaluation/) AI code suggestions that PR authors have accepted and implemented.
|
Qodo Merge employs a novel detection system to automatically [identify](https://qodo-merge-docs.qodo.ai/core-abilities/impact_evaluation/) AI code suggestions that PR authors have accepted and implemented.
|
||||||
|
|
||||||
@ -102,8 +103,6 @@ The `improve` tool can be further customized by providing additional instruction
|
|||||||
|
|
||||||
### Extra instructions
|
### Extra instructions
|
||||||
|
|
||||||
>`Platforms supported: GitHub, GitLab, Bitbucket, Azure DevOps`
|
|
||||||
|
|
||||||
You can use the `extra_instructions` configuration option to give the AI model additional instructions for the `improve` tool.
|
You can use the `extra_instructions` configuration option to give the AI model additional instructions for the `improve` tool.
|
||||||
Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter.
|
Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter.
|
||||||
|
|
||||||
@ -119,9 +118,9 @@ extra_instructions="""\
|
|||||||
```
|
```
|
||||||
Use triple quotes to write multi-line instructions. Use bullet points or numbers to make the instructions more readable.
|
Use triple quotes to write multi-line instructions. Use bullet points or numbers to make the instructions more readable.
|
||||||
|
|
||||||
### Best practices 💎
|
### Best practices
|
||||||
|
|
||||||
>`Platforms supported: GitHub, GitLab, Bitbucket`
|
> `💎 feature. Platforms supported: GitHub, GitLab, Bitbucket`
|
||||||
|
|
||||||
Another option to give additional guidance to the AI model is by creating a `best_practices.md` file, either in your repository's root directory or as a [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) (we recommend the wiki page, as editing and maintaining it over time is easier).
|
Another option to give additional guidance to the AI model is by creating a `best_practices.md` file, either in your repository's root directory or as a [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) (we recommend the wiki page, as editing and maintaining it over time is easier).
|
||||||
This page can contain a list of best practices, coding standards, and guidelines that are specific to your repo/organization.
|
This page can contain a list of best practices, coding standards, and guidelines that are specific to your repo/organization.
|
||||||
@ -192,11 +191,11 @@ And the label will be: `{organization_name} best practice`.
|
|||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
### Auto best practices 💎
|
### Auto best practices
|
||||||
|
|
||||||
>`Platforms supported: GitHub`
|
>`💎 feature. Platforms supported: GitHub.`
|
||||||
|
|
||||||
'Auto best practices' is a novel Qodo Merge capability that:
|
`Auto best practices` is a novel Qodo Merge capability that:
|
||||||
|
|
||||||
1. Identifies recurring patterns from accepted suggestions
|
1. Identifies recurring patterns from accepted suggestions
|
||||||
2. **Automatically** generates [best practices page](https://github.com/qodo-ai/pr-agent/wiki/.pr_agent_auto_best_practices) based on what your team consistently values
|
2. **Automatically** generates [best practices page](https://github.com/qodo-ai/pr-agent/wiki/.pr_agent_auto_best_practices) based on what your team consistently values
|
||||||
@ -229,7 +228,8 @@ max_patterns = 5
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Combining `extra instructions` and `best practices` 💎
|
### Combining 'extra instructions' and 'best practices'
|
||||||
|
> `💎 feature`
|
||||||
|
|
||||||
The `extra instructions` configuration is more related to the `improve` tool prompt. It can be used, for example, to avoid specific suggestions ("Don't suggest to add try-except block", "Ignore changes in toml files", ...) or to emphasize specific aspects or formats ("Answer in Japanese", "Give only short suggestions", ...)
|
The `extra instructions` configuration is more related to the `improve` tool prompt. It can be used, for example, to avoid specific suggestions ("Don't suggest to add try-except block", "Ignore changes in toml files", ...) or to emphasize specific aspects or formats ("Answer in Japanese", "Give only short suggestions", ...)
|
||||||
|
|
||||||
@ -268,6 +268,8 @@ dual_publishing_score_threshold = x
|
|||||||
Where x represents the minimum score threshold (>=) for suggestions to be presented as commitable PR comments in addition to the table. Default is -1 (disabled).
|
Where x represents the minimum score threshold (>=) for suggestions to be presented as commitable PR comments in addition to the table. Default is -1 (disabled).
|
||||||
|
|
||||||
### Self-review
|
### Self-review
|
||||||
|
> `💎 feature`
|
||||||
|
|
||||||
If you set in a configuration file:
|
If you set in a configuration file:
|
||||||
```toml
|
```toml
|
||||||
[pr_code_suggestions]
|
[pr_code_suggestions]
|
||||||
@ -311,21 +313,56 @@ code_suggestions_self_review_text = "... (your text here) ..."
|
|||||||
|
|
||||||
To prevent unauthorized approvals, this configuration defaults to false, and cannot be altered through online comments; enabling requires a direct update to the configuration file and a commit to the repository. This ensures that utilizing the feature demands a deliberate documented decision by the repository owner.
|
To prevent unauthorized approvals, this configuration defaults to false, and cannot be altered through online comments; enabling requires a direct update to the configuration file and a commit to the repository. This ensures that utilizing the feature demands a deliberate documented decision by the repository owner.
|
||||||
|
|
||||||
|
### Auto-approval
|
||||||
|
> `💎 feature`
|
||||||
|
|
||||||
|
Under specific conditions, Qodo Merge can auto-approve a PR when a specific comment is invoked, or when the PR meets certain criteria.
|
||||||
|
|
||||||
|
To ensure safety, the auto-approval feature is disabled by default. To enable auto-approval, you need to actively set, in a pre-defined _configuration file_, the following:
|
||||||
|
```toml
|
||||||
|
[config]
|
||||||
|
enable_auto_approval = true
|
||||||
|
```
|
||||||
|
Note that this specific flag cannot be set with a command line argument, only in the configuration file, committed to the repository.
|
||||||
|
This ensures that enabling auto-approval is a deliberate decision by the repository owner.
|
||||||
|
|
||||||
|
**(1) Auto-approval by commenting**
|
||||||
|
|
||||||
|
After enabling, by commenting on a PR:
|
||||||
|
```
|
||||||
|
/review auto_approve
|
||||||
|
```
|
||||||
|
Qodo Merge will automatically approve the PR, and add a comment with the approval.
|
||||||
|
|
||||||
|
**(2) Auto-approval when the PR meets certain criteria**
|
||||||
|
|
||||||
|
There are two criteria that can be set for auto-approval:
|
||||||
|
|
||||||
|
- **Review effort score**
|
||||||
|
```toml
|
||||||
|
[config]
|
||||||
|
auto_approve_for_low_review_effort = X # X is a number between 1 to 5
|
||||||
|
```
|
||||||
|
When the [review effort score](https://www.qodo.ai/images/pr_agent/review3.png) is lower or equal to X, the PR will be auto-approved.
|
||||||
|
|
||||||
|
___
|
||||||
|
- **No code suggestions**
|
||||||
|
```toml
|
||||||
|
[config]
|
||||||
|
auto_approve_for_no_suggestions = true
|
||||||
|
```
|
||||||
|
When no [code suggestion](https://www.qodo.ai/images/pr_agent/code_suggestions_as_comment_closed.png) were found for the PR, the PR will be auto-approved.
|
||||||
|
|
||||||
### How many code suggestions are generated?
|
### How many code suggestions are generated?
|
||||||
Qodo Merge uses a dynamic strategy to generate code suggestions based on the size of the pull request (PR). Here's how it works:
|
Qodo Merge uses a dynamic strategy to generate code suggestions based on the size of the pull request (PR). Here's how it works:
|
||||||
|
|
||||||
1) Chunking large PRs:
|
#### 1. Chunking large PRs
|
||||||
|
|
||||||
- Qodo Merge divides large PRs into 'chunks'.
|
- Qodo Merge divides large PRs into 'chunks'.
|
||||||
- Each chunk contains up to `pr_code_suggestions.max_context_tokens` tokens (default: 14,000).
|
- Each chunk contains up to `pr_code_suggestions.max_context_tokens` tokens (default: 14,000).
|
||||||
|
|
||||||
|
#### 2. Generating suggestions
|
||||||
2) Generating suggestions:
|
|
||||||
|
|
||||||
- For each chunk, Qodo Merge generates up to `pr_code_suggestions.num_code_suggestions_per_chunk` suggestions (default: 4).
|
- For each chunk, Qodo Merge generates up to `pr_code_suggestions.num_code_suggestions_per_chunk` suggestions (default: 4).
|
||||||
|
|
||||||
|
|
||||||
This approach has two main benefits:
|
This approach has two main benefits:
|
||||||
|
|
||||||
- Scalability: The number of suggestions scales with the PR size, rather than being fixed.
|
- Scalability: The number of suggestions scales with the PR size, rather than being fixed.
|
||||||
|
@ -18,7 +18,7 @@ The tool will generate code suggestions for the selected component (if no compon
|
|||||||
|
|
||||||
{width=768}
|
{width=768}
|
||||||
|
|
||||||
**Notes**
|
!!! note "Notes"
|
||||||
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#.
|
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
|
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
|
||||||
|
|
||||||
|
@ -114,16 +114,6 @@ You can enable\disable the `review` tool to add specific labels to the PR:
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
!!! example "Auto-approval"
|
|
||||||
|
|
||||||
If enabled, the `review` tool can approve a PR when a specific comment, `/review auto_approve`, is invoked.
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><b>enable_auto_approval</b></td>
|
|
||||||
<td>If set to true, the tool will approve the PR when invoked with the 'auto_approve' command. Default is false. This flag can be changed only from a configuration file.</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
## Usage Tips
|
## Usage Tips
|
||||||
|
|
||||||
@ -175,23 +165,6 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review
|
|||||||
Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.
|
Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.
|
||||||
|
|
||||||
|
|
||||||
!!! tip "Auto-approval"
|
|
||||||
|
|
||||||
Qodo Merge can approve a PR when a specific comment is invoked.
|
|
||||||
|
|
||||||
To ensure safety, the auto-approval feature is disabled by default. To enable auto-approval, you need to actively set in a pre-defined configuration file the following:
|
|
||||||
```
|
|
||||||
[pr_reviewer]
|
|
||||||
enable_auto_approval = true
|
|
||||||
```
|
|
||||||
(this specific flag cannot be set with a command line argument, only in the configuration file, committed to the repository)
|
|
||||||
|
|
||||||
|
|
||||||
After enabling, by commenting on a PR:
|
|
||||||
```
|
|
||||||
/review auto_approve
|
|
||||||
```
|
|
||||||
Qodo Merge will automatically approve the PR, and add a comment with the approval.
|
|
||||||
|
|
||||||
|
|
||||||
!!! tip "Code suggestions"
|
!!! tip "Code suggestions"
|
||||||
|
@ -16,14 +16,17 @@ It can be invoked manually by commenting on any PR:
|
|||||||
|
|
||||||
Note that to perform retrieval, the `similar_issue` tool indexes all the repo previous issues (once).
|
Note that to perform retrieval, the `similar_issue` tool indexes all the repo previous issues (once).
|
||||||
|
|
||||||
|
### Selecting a Vector Database
|
||||||
|
Configure your preferred database by changing the `pr_similar_issue` parameter in `configuration.toml` file.
|
||||||
|
|
||||||
**Select VectorDBs** by changing `pr_similar_issue` parameter in `configuration.toml` file
|
#### Available Options
|
||||||
|
Choose from the following Vector Databases:
|
||||||
|
|
||||||
2 VectorDBs are available to switch in
|
|
||||||
1. LanceDB
|
1. LanceDB
|
||||||
2. Pinecone
|
2. Pinecone
|
||||||
|
|
||||||
To enable usage of the '**similar issue**' tool for Pinecone, you need to set the following keys in `.secrets.toml` (or in the relevant environment variables):
|
#### Pinecone Configuration
|
||||||
|
To use Pinecone with the `similar issue` tool, add these credentials to `.secrets.toml` (or set as environment variables):
|
||||||
|
|
||||||
```
|
```
|
||||||
[pinecone]
|
[pinecone]
|
||||||
|
@ -17,8 +17,8 @@ The tool will generate tests for the selected component (if no component is stat
|
|||||||
|
|
||||||
(Example taken from [here](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-1913679429)):
|
(Example taken from [here](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-1913679429)):
|
||||||
|
|
||||||
**Notes** <br>
|
!!! note "Notes"
|
||||||
- The following languages are currently supported: Python, Java, C++, JavaScript, TypeScript, C#. <br>
|
- The following languages are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
|
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@ Examples of invoking the different tools via the CLI:
|
|||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
|
|
||||||
(1) in addition to editing your local configuration file, you can also change any configuration value by adding it to the command line:
|
1. in addition to editing your local configuration file, you can also change any configuration value by adding it to the command line:
|
||||||
```
|
```
|
||||||
python -m pr_agent.cli --pr_url=<pr_url> /review --pr_reviewer.extra_instructions="focus on the file: ..."
|
python -m pr_agent.cli --pr_url=<pr_url> /review --pr_reviewer.extra_instructions="focus on the file: ..."
|
||||||
```
|
```
|
||||||
|
|
||||||
(2) You can print results locally, without publishing them, by setting in `configuration.toml`:
|
2. You can print results locally, without publishing them, by setting in `configuration.toml`:
|
||||||
```
|
```
|
||||||
[config]
|
[config]
|
||||||
publish_output=false
|
publish_output=false
|
||||||
@ -27,14 +27,9 @@ verbosity_level=2
|
|||||||
```
|
```
|
||||||
This is useful for debugging or experimenting with different tools.
|
This is useful for debugging or experimenting with different tools.
|
||||||
|
|
||||||
(3)
|
3. **git provider**: The [git_provider](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L5) field in a configuration file determines the GIT provider that will be used by Qodo Merge. Currently, the following providers are supported:
|
||||||
|
`github` **(default)**, `gitlab`, `bitbucket`, `azure`, `codecommit`, `local`, and `gerrit`.
|
||||||
|
|
||||||
**git provider**: The [git_provider](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L5) field in a configuration file determines the GIT provider that will be used by Qodo Merge. Currently, the following providers are supported:
|
|
||||||
`
|
|
||||||
"github", "gitlab", "bitbucket", "azure", "codecommit", "local", "gerrit"
|
|
||||||
`
|
|
||||||
|
|
||||||
Default is "github".
|
|
||||||
|
|
||||||
### CLI Health Check
|
### CLI Health Check
|
||||||
To verify that Qodo Merge has been configured correctly, you can run this health check command from the repository root:
|
To verify that Qodo Merge has been configured correctly, you can run this health check command from the repository root:
|
||||||
|
@ -189,18 +189,18 @@ key = ...
|
|||||||
|
|
||||||
If the relevant model doesn't appear [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/__init__.py), you can still use it as a custom model:
|
If the relevant model doesn't appear [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/__init__.py), you can still use it as a custom model:
|
||||||
|
|
||||||
(1) Set the model name in the configuration file:
|
1. Set the model name in the configuration file:
|
||||||
```
|
```
|
||||||
[config]
|
[config]
|
||||||
model="custom_model_name"
|
model="custom_model_name"
|
||||||
fallback_models=["custom_model_name"]
|
fallback_models=["custom_model_name"]
|
||||||
```
|
```
|
||||||
(2) Set the maximal tokens for the model:
|
2. Set the maximal tokens for the model:
|
||||||
```
|
```
|
||||||
[config]
|
[config]
|
||||||
custom_model_max_tokens= ...
|
custom_model_max_tokens= ...
|
||||||
```
|
```
|
||||||
(3) Go to [litellm documentation](https://litellm.vercel.app/docs/proxy/quick_start#supported-llms), find the model you want to use, and set the relevant environment variables.
|
3. Go to [litellm documentation](https://litellm.vercel.app/docs/proxy/quick_start#supported-llms), find the model you want to use, and set the relevant environment variables.
|
||||||
|
|
||||||
(4) Most reasoning models do not support chat-style inputs (`system` and `user` messages) or temperature settings.
|
4. Most reasoning models do not support chat-style inputs (`system` and `user` messages) or temperature settings.
|
||||||
To bypass chat templates and temperature controls, set `config.custom_reasoning_model = true` in your configuration file.
|
To bypass chat templates and temperature controls, set `config.custom_reasoning_model = true` in your configuration file.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
site_name: Qodo Merge (and open-source PR-Agent)
|
site_name: Qodo Merge (and open-source PR-Agent)
|
||||||
repo_url: https://github.com/Codium-ai/pr-agent
|
repo_url: https://github.com/qodo-ai/pr-agent
|
||||||
repo_name: Codium-ai/pr-agent
|
repo_name: Qodo-ai/pr-agent
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Overview:
|
- Overview:
|
||||||
|
@ -49,6 +49,11 @@ ignore_pr_authors = [] # authors to ignore from PR agent when an PR is created
|
|||||||
is_auto_command = false # will be auto-set to true if the command is triggered by an automation
|
is_auto_command = false # will be auto-set to true if the command is triggered by an automation
|
||||||
enable_ai_metadata = false # will enable adding ai metadata
|
enable_ai_metadata = false # will enable adding ai metadata
|
||||||
reasoning_effort = "medium" # "low", "medium", "high"
|
reasoning_effort = "medium" # "low", "medium", "high"
|
||||||
|
# auto approval 💎
|
||||||
|
enable_auto_approval=false # Set to true to enable auto-approval of PRs under certain conditions
|
||||||
|
auto_approve_for_low_review_effort=-1 # -1 to disable, [1-5] to set the threshold for auto-approval
|
||||||
|
auto_approve_for_no_suggestions=false # If true, the PR will be auto-approved if there are no suggestions
|
||||||
|
|
||||||
|
|
||||||
[pr_reviewer] # /review #
|
[pr_reviewer] # /review #
|
||||||
# enable/disable features
|
# enable/disable features
|
||||||
@ -71,9 +76,6 @@ minimal_commits_for_incremental_review=0
|
|||||||
minimal_minutes_for_incremental_review=0
|
minimal_minutes_for_incremental_review=0
|
||||||
enable_intro_text=true
|
enable_intro_text=true
|
||||||
enable_help_text=false # Determines whether to include help text in the PR review. Enabled by default.
|
enable_help_text=false # Determines whether to include help text in the PR review. Enabled by default.
|
||||||
# auto approval
|
|
||||||
enable_auto_approval=false
|
|
||||||
|
|
||||||
|
|
||||||
[pr_description] # /describe #
|
[pr_description] # /describe #
|
||||||
publish_labels=false
|
publish_labels=false
|
||||||
|
@ -123,10 +123,10 @@ class PRReviewer:
|
|||||||
if self.incremental.is_incremental and not self._can_run_incremental_review():
|
if self.incremental.is_incremental and not self._can_run_incremental_review():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if isinstance(self.args, list) and self.args and self.args[0] == 'auto_approve':
|
# if isinstance(self.args, list) and self.args and self.args[0] == 'auto_approve':
|
||||||
get_logger().info(f'Auto approve flow PR: {self.pr_url} ...')
|
# get_logger().info(f'Auto approve flow PR: {self.pr_url} ...')
|
||||||
self.auto_approve_logic()
|
# self.auto_approve_logic()
|
||||||
return None
|
# return None
|
||||||
|
|
||||||
get_logger().info(f'Reviewing PR: {self.pr_url} ...')
|
get_logger().info(f'Reviewing PR: {self.pr_url} ...')
|
||||||
relevant_configs = {'pr_reviewer': dict(get_settings().pr_reviewer),
|
relevant_configs = {'pr_reviewer': dict(get_settings().pr_reviewer),
|
||||||
@ -402,7 +402,7 @@ class PRReviewer:
|
|||||||
"""
|
"""
|
||||||
Auto-approve a pull request if it meets the conditions for auto-approval.
|
Auto-approve a pull request if it meets the conditions for auto-approval.
|
||||||
"""
|
"""
|
||||||
if get_settings().pr_reviewer.enable_auto_approval:
|
if get_settings().config.enable_auto_approval:
|
||||||
is_auto_approved = self.git_provider.auto_approve()
|
is_auto_approved = self.git_provider.auto_approve()
|
||||||
if is_auto_approved:
|
if is_auto_approved:
|
||||||
get_logger().info("Auto-approved PR")
|
get_logger().info("Auto-approved PR")
|
||||||
|
@ -1,118 +1,121 @@
|
|||||||
import unittest
|
# Currently doing API calls - wrong !
|
||||||
import asyncio
|
|
||||||
from unittest.mock import AsyncMock, patch
|
|
||||||
from pr_agent.tools.ticket_pr_compliance_check import extract_tickets, extract_and_cache_pr_tickets
|
|
||||||
from pr_agent.git_providers.github_provider import GithubProvider
|
|
||||||
|
|
||||||
|
|
||||||
class TestTicketCompliance(unittest.TestCase):
|
|
||||||
|
|
||||||
@patch.object(GithubProvider, 'get_user_description', return_value="Fixes #1 and relates to #2")
|
|
||||||
@patch.object(GithubProvider, '_parse_issue_url', side_effect=lambda url: ("WonOfAKind/KimchiBot", int(url.split('#')[-1])))
|
|
||||||
@patch.object(GithubProvider, 'repo_obj')
|
|
||||||
async def test_extract_tickets(self, mock_repo, mock_parse_issue_url, mock_user_desc):
|
|
||||||
"""
|
|
||||||
Test extract_tickets() to ensure it extracts tickets correctly
|
|
||||||
and fetches their content.
|
|
||||||
"""
|
|
||||||
github_provider = GithubProvider()
|
|
||||||
github_provider.repo = "WonOfAKind/KimchiBot"
|
|
||||||
github_provider.base_url_html = "https://github.com"
|
|
||||||
|
|
||||||
# Mock issue retrieval
|
|
||||||
mock_issue = AsyncMock()
|
|
||||||
mock_issue.number = 1
|
|
||||||
mock_issue.title = "Sample Issue"
|
|
||||||
mock_issue.body = "This is a test issue body."
|
|
||||||
mock_issue.labels = ["bug", "high priority"]
|
|
||||||
|
|
||||||
# Mock repo object
|
|
||||||
mock_repo.get_issue.return_value = mock_issue
|
|
||||||
|
|
||||||
tickets = await extract_tickets(github_provider)
|
|
||||||
|
|
||||||
# Verify tickets were extracted correctly
|
|
||||||
self.assertIsInstance(tickets, list)
|
|
||||||
self.assertGreater(len(tickets), 0, "Expected at least one ticket!")
|
|
||||||
|
|
||||||
# Verify ticket structure
|
|
||||||
first_ticket = tickets[0]
|
|
||||||
self.assertIn("ticket_id", first_ticket)
|
|
||||||
self.assertIn("ticket_url", first_ticket)
|
|
||||||
self.assertIn("title", first_ticket)
|
|
||||||
self.assertIn("body", first_ticket)
|
|
||||||
self.assertIn("labels", first_ticket)
|
|
||||||
|
|
||||||
print("\n Test Passed: extract_tickets() successfully retrieved ticket info!")
|
|
||||||
|
|
||||||
@patch.object(GithubProvider, 'get_user_description', return_value="Fixes #1 and relates to #2")
|
|
||||||
@patch.object(GithubProvider, '_parse_issue_url', side_effect=lambda url: ("WonOfAKind/KimchiBot", int(url.split('#')[-1])))
|
|
||||||
@patch.object(GithubProvider, 'repo_obj')
|
|
||||||
async def test_extract_and_cache_pr_tickets(self, mock_repo, mock_parse_issue_url, mock_user_desc):
|
|
||||||
"""
|
|
||||||
Test extract_and_cache_pr_tickets() to ensure tickets are extracted and cached correctly.
|
|
||||||
"""
|
|
||||||
github_provider = GithubProvider()
|
|
||||||
github_provider.repo = "WonOfAKind/KimchiBot"
|
|
||||||
github_provider.base_url_html = "https://github.com"
|
|
||||||
|
|
||||||
vars = {} # Simulate the dictionary to store results
|
|
||||||
|
|
||||||
# Mock issue retrieval
|
|
||||||
mock_issue = AsyncMock()
|
|
||||||
mock_issue.number = 1
|
|
||||||
mock_issue.title = "Sample Issue"
|
|
||||||
mock_issue.body = "This is a test issue body."
|
|
||||||
mock_issue.labels = ["bug", "high priority"]
|
|
||||||
|
|
||||||
# Mock repo object
|
|
||||||
mock_repo.get_issue.return_value = mock_issue
|
|
||||||
|
|
||||||
# Run function
|
|
||||||
await extract_and_cache_pr_tickets(github_provider, vars)
|
|
||||||
|
|
||||||
# Ensure tickets are cached
|
|
||||||
self.assertIn("related_tickets", vars)
|
|
||||||
self.assertIsInstance(vars["related_tickets"], list)
|
|
||||||
self.assertGreater(len(vars["related_tickets"]), 0, "Expected at least one cached ticket!")
|
|
||||||
|
|
||||||
print("\n Test Passed: extract_and_cache_pr_tickets() successfully cached ticket data!")
|
|
||||||
|
|
||||||
def test_fetch_sub_issues(self):
|
|
||||||
"""
|
|
||||||
Test fetch_sub_issues() to ensure sub-issues are correctly retrieved.
|
|
||||||
"""
|
|
||||||
github_provider = GithubProvider()
|
|
||||||
issue_url = "https://github.com/WonOfAKind/KimchiBot/issues/1" # Known issue with sub-issues
|
|
||||||
result = github_provider.fetch_sub_issues(issue_url)
|
|
||||||
|
|
||||||
print("Fetched sub-issues:", result)
|
|
||||||
|
|
||||||
self.assertIsInstance(result, set) # Ensure result is a set
|
|
||||||
self.assertGreater(len(result), 0, "Expected at least one sub-issue but found none!")
|
|
||||||
|
|
||||||
print("\n Test Passed: fetch_sub_issues() retrieved sub-issues correctly!")
|
|
||||||
|
|
||||||
def test_fetch_sub_issues_with_no_results(self):
|
|
||||||
"""
|
|
||||||
Test fetch_sub_issues() to ensure an empty set is returned for an issue with no sub-issues.
|
|
||||||
"""
|
|
||||||
github_provider = GithubProvider()
|
|
||||||
issue_url = "https://github.com/qodo-ai/pr-agent/issues/1499" # Likely non-existent issue
|
|
||||||
result = github_provider.fetch_sub_issues(issue_url)
|
|
||||||
|
|
||||||
print("Fetched sub-issues for non-existent issue:", result)
|
|
||||||
|
|
||||||
self.assertIsInstance(result, set) # Ensure result is a set
|
|
||||||
self.assertEqual(len(result), 0, "Expected no sub-issues but some were found!")
|
|
||||||
|
|
||||||
print("\n Test Passed: fetch_sub_issues_with_no_results() correctly returned an empty set!")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(unittest.main())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# import unittest
|
||||||
|
# import asyncio
|
||||||
|
# from unittest.mock import AsyncMock, patch
|
||||||
|
# from pr_agent.tools.ticket_pr_compliance_check import extract_tickets, extract_and_cache_pr_tickets
|
||||||
|
# from pr_agent.git_providers.github_provider import GithubProvider
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class TestTicketCompliance(unittest.TestCase):
|
||||||
|
#
|
||||||
|
# @patch.object(GithubProvider, 'get_user_description', return_value="Fixes #1 and relates to #2")
|
||||||
|
# @patch.object(GithubProvider, '_parse_issue_url', side_effect=lambda url: ("WonOfAKind/KimchiBot", int(url.split('#')[-1])))
|
||||||
|
# @patch.object(GithubProvider, 'repo_obj')
|
||||||
|
# async def test_extract_tickets(self, mock_repo, mock_parse_issue_url, mock_user_desc):
|
||||||
|
# """
|
||||||
|
# Test extract_tickets() to ensure it extracts tickets correctly
|
||||||
|
# and fetches their content.
|
||||||
|
# """
|
||||||
|
# github_provider = GithubProvider()
|
||||||
|
# github_provider.repo = "WonOfAKind/KimchiBot"
|
||||||
|
# github_provider.base_url_html = "https://github.com"
|
||||||
|
#
|
||||||
|
# # Mock issue retrieval
|
||||||
|
# mock_issue = AsyncMock()
|
||||||
|
# mock_issue.number = 1
|
||||||
|
# mock_issue.title = "Sample Issue"
|
||||||
|
# mock_issue.body = "This is a test issue body."
|
||||||
|
# mock_issue.labels = ["bug", "high priority"]
|
||||||
|
#
|
||||||
|
# # Mock repo object
|
||||||
|
# mock_repo.get_issue.return_value = mock_issue
|
||||||
|
#
|
||||||
|
# tickets = await extract_tickets(github_provider)
|
||||||
|
#
|
||||||
|
# # Verify tickets were extracted correctly
|
||||||
|
# self.assertIsInstance(tickets, list)
|
||||||
|
# self.assertGreater(len(tickets), 0, "Expected at least one ticket!")
|
||||||
|
#
|
||||||
|
# # Verify ticket structure
|
||||||
|
# first_ticket = tickets[0]
|
||||||
|
# self.assertIn("ticket_id", first_ticket)
|
||||||
|
# self.assertIn("ticket_url", first_ticket)
|
||||||
|
# self.assertIn("title", first_ticket)
|
||||||
|
# self.assertIn("body", first_ticket)
|
||||||
|
# self.assertIn("labels", first_ticket)
|
||||||
|
#
|
||||||
|
# print("\n Test Passed: extract_tickets() successfully retrieved ticket info!")
|
||||||
|
#
|
||||||
|
# @patch.object(GithubProvider, 'get_user_description', return_value="Fixes #1 and relates to #2")
|
||||||
|
# @patch.object(GithubProvider, '_parse_issue_url', side_effect=lambda url: ("WonOfAKind/KimchiBot", int(url.split('#')[-1])))
|
||||||
|
# @patch.object(GithubProvider, 'repo_obj')
|
||||||
|
# async def test_extract_and_cache_pr_tickets(self, mock_repo, mock_parse_issue_url, mock_user_desc):
|
||||||
|
# """
|
||||||
|
# Test extract_and_cache_pr_tickets() to ensure tickets are extracted and cached correctly.
|
||||||
|
# """
|
||||||
|
# github_provider = GithubProvider()
|
||||||
|
# github_provider.repo = "WonOfAKind/KimchiBot"
|
||||||
|
# github_provider.base_url_html = "https://github.com"
|
||||||
|
#
|
||||||
|
# vars = {} # Simulate the dictionary to store results
|
||||||
|
#
|
||||||
|
# # Mock issue retrieval
|
||||||
|
# mock_issue = AsyncMock()
|
||||||
|
# mock_issue.number = 1
|
||||||
|
# mock_issue.title = "Sample Issue"
|
||||||
|
# mock_issue.body = "This is a test issue body."
|
||||||
|
# mock_issue.labels = ["bug", "high priority"]
|
||||||
|
#
|
||||||
|
# # Mock repo object
|
||||||
|
# mock_repo.get_issue.return_value = mock_issue
|
||||||
|
#
|
||||||
|
# # Run function
|
||||||
|
# await extract_and_cache_pr_tickets(github_provider, vars)
|
||||||
|
#
|
||||||
|
# # Ensure tickets are cached
|
||||||
|
# self.assertIn("related_tickets", vars)
|
||||||
|
# self.assertIsInstance(vars["related_tickets"], list)
|
||||||
|
# self.assertGreater(len(vars["related_tickets"]), 0, "Expected at least one cached ticket!")
|
||||||
|
#
|
||||||
|
# print("\n Test Passed: extract_and_cache_pr_tickets() successfully cached ticket data!")
|
||||||
|
#
|
||||||
|
# def test_fetch_sub_issues(self):
|
||||||
|
# """
|
||||||
|
# Test fetch_sub_issues() to ensure sub-issues are correctly retrieved.
|
||||||
|
# """
|
||||||
|
# github_provider = GithubProvider()
|
||||||
|
# issue_url = "https://github.com/WonOfAKind/KimchiBot/issues/1" # Known issue with sub-issues
|
||||||
|
# result = github_provider.fetch_sub_issues(issue_url)
|
||||||
|
#
|
||||||
|
# print("Fetched sub-issues:", result)
|
||||||
|
#
|
||||||
|
# self.assertIsInstance(result, set) # Ensure result is a set
|
||||||
|
# self.assertGreater(len(result), 0, "Expected at least one sub-issue but found none!")
|
||||||
|
#
|
||||||
|
# print("\n Test Passed: fetch_sub_issues() retrieved sub-issues correctly!")
|
||||||
|
#
|
||||||
|
# def test_fetch_sub_issues_with_no_results(self):
|
||||||
|
# """
|
||||||
|
# Test fetch_sub_issues() to ensure an empty set is returned for an issue with no sub-issues.
|
||||||
|
# """
|
||||||
|
# github_provider = GithubProvider()
|
||||||
|
# issue_url = "https://github.com/qodo-ai/pr-agent/issues/1499" # Likely non-existent issue
|
||||||
|
# result = github_provider.fetch_sub_issues(issue_url)
|
||||||
|
#
|
||||||
|
# print("Fetched sub-issues for non-existent issue:", result)
|
||||||
|
#
|
||||||
|
# self.assertIsInstance(result, set) # Ensure result is a set
|
||||||
|
# self.assertEqual(len(result), 0, "Expected no sub-issues but some were found!")
|
||||||
|
#
|
||||||
|
# print("\n Test Passed: fetch_sub_issues_with_no_results() correctly returned an empty set!")
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# asyncio.run(unittest.main())
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
Reference in New Issue
Block a user