diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index bfe87dbd..9f56c3e5 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -37,5 +37,3 @@ jobs: name: Test dev docker run: | docker run --rm codiumai/pr-agent:test pytest -v tests/unittest - - diff --git a/.github/workflows/code_coverage.yaml b/.github/workflows/code_coverage.yaml index 136ed9a7..de372024 100644 --- a/.github/workflows/code_coverage.yaml +++ b/.github/workflows/code_coverage.yaml @@ -37,7 +37,7 @@ jobs: - id: code_cov name: Test dev docker run: | - docker run --name test_container codiumai/pr-agent:test pytest tests/unittest --cov=pr_agent --cov-report term --cov-report xml:coverage.xml + docker run --name test_container codiumai/pr-agent:test pytest tests/unittest --cov=pr_agent --cov-report term --cov-report xml:coverage.xml docker cp test_container:/app/coverage.xml coverage.xml docker rm test_container @@ -51,4 +51,4 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v4.0.1 with: - token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/docs-ci.yaml b/.github/workflows/docs-ci.yaml index b260039e..3e59de11 100644 --- a/.github/workflows/docs-ci.yaml +++ b/.github/workflows/docs-ci.yaml @@ -1,4 +1,4 @@ -name: docs-ci +name: docs-ci on: push: branches: @@ -20,14 +20,14 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x - - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV - uses: actions/cache@v4 with: key: mkdocs-material-${{ env.cache_id }} path: .cache restore-keys: | mkdocs-material- - - run: pip install mkdocs-material + - run: pip install mkdocs-material - run: pip install "mkdocs-material[imaging]" - run: pip install mkdocs-glightbox - run: mkdocs gh-deploy -f docs/mkdocs.yml --force diff --git a/.github/workflows/e2e_tests.yaml b/.github/workflows/e2e_tests.yaml index e49bcea3..07602d7f 100644 --- a/.github/workflows/e2e_tests.yaml +++ b/.github/workflows/e2e_tests.yaml @@ -43,4 +43,4 @@ jobs: - id: test3 name: E2E bitbucket app run: | - docker run -e BITBUCKET.USERNAME=${{ secrets.BITBUCKET_USERNAME }} -e BITBUCKET.PASSWORD=${{ secrets.BITBUCKET_PASSWORD }} --rm codiumai/pr-agent:test pytest -v tests/e2e_tests/test_bitbucket_app.py \ No newline at end of file + docker run -e BITBUCKET.USERNAME=${{ secrets.BITBUCKET_USERNAME }} -e BITBUCKET.PASSWORD=${{ secrets.BITBUCKET_PASSWORD }} --rm codiumai/pr-agent:test pytest -v tests/e2e_tests/test_bitbucket_app.py diff --git a/.github/workflows/pr-agent-review.yaml b/.github/workflows/pr-agent-review.yaml index aa7a8fe0..4d2a04ac 100644 --- a/.github/workflows/pr-agent-review.yaml +++ b/.github/workflows/pr-agent-review.yaml @@ -1,4 +1,4 @@ -# This workflow enables developers to call PR-Agents `/[actions]` in PR's comments and upon PR creation. +# This workflow enables developers to call PR-Agents `/[actions]` in PR's comments and upon PR creation. # Learn more at https://www.codium.ai/pr-agent/ # This is v0.2 of this workflow file @@ -30,6 +30,3 @@ jobs: GITHUB_ACTION_CONFIG.AUTO_DESCRIBE: true GITHUB_ACTION_CONFIG.AUTO_REVIEW: true GITHUB_ACTION_CONFIG.AUTO_IMPROVE: true - - - diff --git a/.gitignore b/.gitignore index 9fcb9193..ec1de25f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ dist/ *.egg-info/ build/ .DS_Store -docs/.cache/ \ No newline at end of file +docs/.cache/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff495d30..e5971b70 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,10 +13,10 @@ repos: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/rhysd/actionlint - rev: v1.7.3 - hooks: - - id: actionlint + # - repo: https://github.com/rhysd/actionlint + # rev: v1.7.3 + # hooks: + # - id: actionlint - repo: https://github.com/pycqa/isort # rev must match what's in dev-requirements.txt rev: 5.13.2 diff --git a/LICENSE b/LICENSE index 633ab1c9..a5fcacc9 100644 --- a/LICENSE +++ b/LICENSE @@ -199,4 +199,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/MANIFEST.in b/MANIFEST.in index ccb17336..194b3def 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ recursive-include pr_agent *.toml -recursive-exclude pr_agent *.secrets.toml \ No newline at end of file +recursive-exclude pr_agent *.secrets.toml diff --git a/README.md b/README.md index ef535434..e1ef104c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Qode Merge PR-Agent aims to help efficiently review and handle pull requests, by - [PR-Agent Pro 💎](https://pr-agent-docs.codium.ai/overview/pr_agent_pro/) - [How it works](#how-it-works) - [Why use PR-Agent?](#why-use-pr-agent) - + ## News and Updates ### October 27, 2024 @@ -55,7 +55,7 @@ Read more about this novel feature [here](https://qodo-merge-docs.qodo.ai/tools/ ### October 21, 2024 -**Disable publishing labels by default:** +**Disable publishing labels by default:** The default setting for `pr_description.publish_labels` has been updated to `false`. This means that labels generated by the `/describe` tool will no longer be published, unless this configuration is explicitly set to `true`. @@ -258,7 +258,7 @@ Note that when you set your own PR-Agent or use CodiumAI hosted PR-Agent, there 1. **Fully managed** - We take care of everything for you - hosting, models, regular updates, and more. Installation is as simple as signing up and adding the PR-Agent app to your GitHub\GitLab\BitBucket repo. 2. **Improved privacy** - No data will be stored or used to train models. PR-Agent Pro will employ zero data retention, and will use an OpenAI account with zero data retention. 3. **Improved support** - PR-Agent Pro users will receive priority support, and will be able to request new features and capabilities. -4. **Extra features** -In addition to the benefits listed above, PR-Agent Pro will emphasize more customization, and the usage of static code analysis, in addition to LLM logic, to improve results. +4. **Extra features** -In addition to the benefits listed above, PR-Agent Pro will emphasize more customization, and the usage of static code analysis, in addition to LLM logic, to improve results. See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for a list of features available in PR-Agent Pro. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3dab48f9..7ce674d2 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -88,7 +88,7 @@ Significant documentation updates (see [Installation Guide](https://github.com/C - codiumai/pr-agent:0.7-gitlab_webhook - codiumai/pr-agent:0.7-github_polling - codiumai/pr-agent:0.7-github_action - + ### Added::Algo - New tool /similar_issue - Currently on GitHub app and CLI: indexes the issues in the repo, find the most similar issues to the target issue. - Describe markers: Empower the /describe tool with a templating capability (see more details in https://github.com/Codium-ai/pr-agent/pull/273). diff --git a/docs/docs/assets/logo.svg b/docs/docs/assets/logo.svg index 0b4ddbba..a22defe7 100644 --- a/docs/docs/assets/logo.svg +++ b/docs/docs/assets/logo.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/docs/docs/chrome-extension/data_privacy.md b/docs/docs/chrome-extension/data_privacy.md index 14753a0c..848f8f2d 100644 --- a/docs/docs/chrome-extension/data_privacy.md +++ b/docs/docs/chrome-extension/data_privacy.md @@ -2,4 +2,3 @@ We take your code's security and privacy seriously: - The Chrome extension will not send your code to any external servers. - For private repositories, we will first validate the user's identity and permissions. After authentication, we generate responses using the existing Qodo Merge Pro integration. - diff --git a/docs/docs/chrome-extension/index.md b/docs/docs/chrome-extension/index.md index 6885df4b..f722639c 100644 --- a/docs/docs/chrome-extension/index.md +++ b/docs/docs/chrome-extension/index.md @@ -2,7 +2,7 @@ With a single-click installation you will gain access to a context-aware chat on your pull requests code, a toolbar extension with multiple AI feedbacks, Qodo Merge filters, and additional abilities. -The extension is powered by top code models like Claude 3.5 Sonnet and GPT4. All the extension's features are free to use on public repositories. +The extension is powered by top code models like Claude 3.5 Sonnet and GPT4. All the extension's features are free to use on public repositories. For private repositories, you will need to install [Qodo Merge Pro](https://github.com/apps/codiumai-pr-agent-pro) in addition to the extension (Quick GitHub app setup with a 14-day free trial. No credit card needed). For a demonstration of how to install Qodo Merge Pro and use it with the Chrome extension, please refer to the tutorial video at the provided [link](https://codium.ai/images/pr_agent/private_repos.mp4). diff --git a/docs/docs/core-abilities/code_oriented_yaml.md b/docs/docs/core-abilities/code_oriented_yaml.md index 32cfee7f..e65f8366 100644 --- a/docs/docs/core-abilities/code_oriented_yaml.md +++ b/docs/docs/core-abilities/code_oriented_yaml.md @@ -1,2 +1,2 @@ ## Overview -TBD \ No newline at end of file +TBD diff --git a/docs/docs/core-abilities/compression_strategy.md b/docs/docs/core-abilities/compression_strategy.md index c09de0db..1115c33c 100644 --- a/docs/docs/core-abilities/compression_strategy.md +++ b/docs/docs/core-abilities/compression_strategy.md @@ -12,9 +12,9 @@ We prioritize the languages of the repo based on the following criteria: 1. Exclude binary files and non code files (e.g. images, pdfs, etc) 2. Given the main languages used in the repo -3. We sort the PR files by the most common languages in the repo (in descending order): +3. We sort the PR files by the most common languages in the repo (in descending order): * ```[[file.py, file2.py],[file3.js, file4.jsx],[readme.md]]``` - + ### Small PR In this case, we can fit the entire PR in a single prompt: diff --git a/docs/docs/core-abilities/dynamic_context.md b/docs/docs/core-abilities/dynamic_context.md index b8b71a30..eff3e60c 100644 --- a/docs/docs/core-abilities/dynamic_context.md +++ b/docs/docs/core-abilities/dynamic_context.md @@ -1,7 +1,7 @@ ## TL;DR -Qodo Merge uses an **asymmetric and dynamic context strategy** to improve AI analysis of code changes in pull requests. -It provides more context before changes than after, and dynamically adjusts the context based on code structure (e.g., enclosing functions or classes). +Qodo Merge uses an **asymmetric and dynamic context strategy** to improve AI analysis of code changes in pull requests. +It provides more context before changes than after, and dynamically adjusts the context based on code structure (e.g., enclosing functions or classes). This approach balances providing sufficient context for accurate analysis, while avoiding needle-in-the-haystack information overload that could degrade AI performance or exceed token limits. ## Introduction @@ -17,12 +17,12 @@ Pull request code changes are retrieved in a unified diff format, showing three code line that already existed in the file... code line that already existed in the file... code line that already existed in the file... - + @@ -26,2 +26,4 @@ def func2(): ... ``` -This unified diff format can be challenging for AI models to interpret accurately, as it provides limited context for understanding the full scope of code changes. +This unified diff format can be challenging for AI models to interpret accurately, as it provides limited context for understanding the full scope of code changes. The presentation of code using '+', '-', and ' ' symbols to indicate additions, deletions, and unchanged lines respectively also differs from the standard code formatting typically used to train AI models. @@ -37,7 +37,7 @@ Pros: Cons: - Excessive context may overwhelm the model with extraneous information, creating a "needle in a haystack" scenario where focusing on the relevant details (the code that actually changed) becomes challenging. -LLM quality is known to degrade when the context gets larger. +LLM quality is known to degrade when the context gets larger. Pull requests often encompass multiple changes across many files, potentially spanning hundreds of lines of modified code. This complexity presents a genuine risk of overwhelming the model with excessive context. - Increased context expands the token count, increasing processing time and cost, and may prevent the model from processing the entire pull request in a single pass. @@ -47,18 +47,18 @@ To address these challenges, Qodo Merge employs an **asymmetric** and **dynamic* **Asymmetric:** -We start by recognizing that the context preceding a code change is typically more crucial for understanding the modification than the context following it. +We start by recognizing that the context preceding a code change is typically more crucial for understanding the modification than the context following it. Consequently, Qodo Merge implements an asymmetric context policy, decoupling the context window into two distinct segments: one for the code before the change and another for the code after. -By independently adjusting each context window, Qodo Merge can supply the model with a more tailored and pertinent context for individual code changes. +By independently adjusting each context window, Qodo Merge can supply the model with a more tailored and pertinent context for individual code changes. **Dynamic:** We also employ a "dynamic" context strategy. -We start by recognizing that the optimal context for a code change often corresponds to its enclosing code component (e.g., function, class), rather than a fixed number of lines. +We start by recognizing that the optimal context for a code change often corresponds to its enclosing code component (e.g., function, class), rather than a fixed number of lines. Consequently, we dynamically adjust the context window based on the code's structure, ensuring the model receives the most pertinent information for each modification. -To prevent overwhelming the model with excessive context, we impose a limit on the number of lines searched when identifying the enclosing component. +To prevent overwhelming the model with excessive context, we impose a limit on the number of lines searched when identifying the enclosing component. This balance allows for comprehensive understanding while maintaining efficiency and limiting context token usage. ## Appendix - relevant configuration options @@ -69,4 +69,4 @@ allow_dynamic_context=true # Allow dynamic context extension max_extra_lines_before_dynamic_context = 8 # will try to include up to X extra lines before the hunk in the patch, until we reach an enclosing function or class patch_extra_lines_before = 3 # Number of extra lines (+3 default ones) to include before each hunk in the patch patch_extra_lines_after = 1 # Number of extra lines (+3 default ones) to include after each hunk in the patch -``` \ No newline at end of file +``` diff --git a/docs/docs/core-abilities/impact_evaluation.md b/docs/docs/core-abilities/impact_evaluation.md index 41db3b52..2790411e 100644 --- a/docs/docs/core-abilities/impact_evaluation.md +++ b/docs/docs/core-abilities/impact_evaluation.md @@ -41,4 +41,4 @@ Here are key metrics that the dashboard tracks: #### Suggestion Score Distribution ![Impacted_Suggestion_Score](https://codium.ai/images/pr_agent/impacted_score_dist.png){width=512} -> Explanation: The distribution of the suggestion score for the implemented suggestions, ensuring that higher-scored suggestions truly represent more significant improvements. +> Explanation: The distribution of the suggestion score for the implemented suggestions, ensuring that higher-scored suggestions truly represent more significant improvements. diff --git a/docs/docs/core-abilities/index.md b/docs/docs/core-abilities/index.md index c9f288bc..2d025c9d 100644 --- a/docs/docs/core-abilities/index.md +++ b/docs/docs/core-abilities/index.md @@ -13,7 +13,7 @@ Qodo Merge utilizes a variety of core abilities to provide a comprehensive and e ## Blogs -Here are some additional technical blogs from Qodo, that delve deeper into the core capabilities and features of Large Language Models (LLMs) when applied to coding tasks. +Here are some additional technical blogs from Qodo, that delve deeper into the core capabilities and features of Large Language Models (LLMs) when applied to coding tasks. These resources provide more comprehensive insights into leveraging LLMs for software development. ### Code Generation and LLMs @@ -25,4 +25,4 @@ These resources provide more comprehensive insights into leveraging LLMs for sof - [Introduction to Code Coverage Testing](https://www.qodo.ai/blog/introduction-to-code-coverage-testing/) ### Cost Optimization -- [Reduce Your Costs by 30% When Using GPT for Python Code](https://www.qodo.ai/blog/reduce-your-costs-by-30-when-using-gpt-3-for-python-code/) \ No newline at end of file +- [Reduce Your Costs by 30% When Using GPT for Python Code](https://www.qodo.ai/blog/reduce-your-costs-by-30-when-using-gpt-3-for-python-code/) diff --git a/docs/docs/core-abilities/interactivity.md b/docs/docs/core-abilities/interactivity.md index e484d641..e107f781 100644 --- a/docs/docs/core-abilities/interactivity.md +++ b/docs/docs/core-abilities/interactivity.md @@ -1,2 +1,2 @@ ## Interactive invocation 💎 -TBD \ No newline at end of file +TBD diff --git a/docs/docs/core-abilities/metadata.md b/docs/docs/core-abilities/metadata.md index 570da42e..2b90b015 100644 --- a/docs/docs/core-abilities/metadata.md +++ b/docs/docs/core-abilities/metadata.md @@ -53,4 +53,4 @@ __old hunk__ (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. \ No newline at end of file +This comprehensive approach enables Qodo Merge AI models to generate more precise and contextually relevant suggestions and feedback. diff --git a/docs/docs/core-abilities/self_reflection.md b/docs/docs/core-abilities/self_reflection.md index b8acc395..894cee69 100644 --- a/docs/docs/core-abilities/self_reflection.md +++ b/docs/docs/core-abilities/self_reflection.md @@ -1,7 +1,7 @@ ## TL;DR -Qodo Merge implements a **self-reflection** process where the AI model reflects, scores, and re-ranks its own suggestions, eliminating irrelevant or incorrect ones. -This approach improves the quality and relevance of suggestions, saving users time and enhancing their experience. +Qodo Merge implements a **self-reflection** process where the AI model reflects, scores, and re-ranks its own suggestions, eliminating irrelevant or incorrect ones. +This approach improves the quality and relevance of suggestions, saving users time and enhancing their experience. Configuration options allow users to set a score threshold for further filtering out suggestions. ## Introduction - Efficient Review with Hierarchical Presentation @@ -24,7 +24,7 @@ The AI model is initially tasked with generating suggestions, and outputting the However, in practice we observe that models often struggle to simultaneously generate high-quality code suggestions and rank them well in a single pass. Furthermore, the initial set of generated suggestions sometimes contains easily identifiable errors. -To address these issues, we implemented a "self-reflection" process that refines suggestion ranking and eliminates irrelevant or incorrect proposals. +To address these issues, we implemented a "self-reflection" process that refines suggestion ranking and eliminates irrelevant or incorrect proposals. This process consists of the following steps: 1. Presenting the generated suggestions to the model in a follow-up call. @@ -48,4 +48,4 @@ This results in a more refined and valuable set of suggestions for the user, sav [pr_code_suggestions] self_reflect_on_suggestions = true # Enable self-reflection on code suggestions suggestions_score_threshold = 0 # Filter out suggestions with a score below this threshold (0-10) -``` \ No newline at end of file +``` diff --git a/docs/docs/faq/index.md b/docs/docs/faq/index.md index e01920b8..dcd5df6b 100644 --- a/docs/docs/faq/index.md +++ b/docs/docs/faq/index.md @@ -31,11 +31,11 @@ ___ - The hierarchical structure of the suggestions is designed to help the user to _quickly_ understand them, and to decide which ones are relevant and which are not: - + - Only if the `Category` header is relevant, the user should move to the summarized suggestion description. - Only if the summarized suggestion description is relevant, the user should click on the collapsible, to read the full suggestion description with a code preview example. - - In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. + - In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. - The interactive [PR chat](https://qodo-merge-docs.qodo.ai/chrome-extension/) also provides an easy way to get more tailored suggestions and feedback from the AI model. ___ @@ -51,7 +51,7 @@ ___ #### Answer:4 No. Qodo Merge strict privacy policy ensures that your code is not stored or used for training purposes. - + For a detailed overview of our data privacy policy, please refer to [this link](https://qodo-merge-docs.qodo.ai/overview/data_privacy/) ___ @@ -59,9 +59,9 @@ ___ ??? note "Question: Can I use my own LLM keys with Qodo Merge?" #### Answer:5 - When you self-host, you use your own keys. + When you self-host, you use your own keys. Qodo Merge Pro with SaaS deployment is a hosted version of Qodo Merge, where Qodo manages the infrastructure and the keys. For enterprise customers, on-prem deployment is also available. [Contact us](https://www.codium.ai/contact/#pricing) for more information. -___ \ No newline at end of file +___ diff --git a/docs/docs/finetuning_benchmark/index.md b/docs/docs/finetuning_benchmark/index.md index 5a002df8..b479ff0a 100644 --- a/docs/docs/finetuning_benchmark/index.md +++ b/docs/docs/finetuning_benchmark/index.md @@ -84,10 +84,10 @@ command: improve model1_score: 9, model2_score: 6, why: | - Response 1 is better because it provides more actionable and specific suggestions that directly - enhance the code's maintainability, performance, and best practices. For example, it suggests - using a variable for reusable widget instances and using named routes for navigation, which - are practical improvements. In contrast, Response 2 focuses more on general advice and less - actionable suggestions, such as changing variable names and adding comments, which are less + Response 1 is better because it provides more actionable and specific suggestions that directly + enhance the code's maintainability, performance, and best practices. For example, it suggests + using a variable for reusable widget instances and using named routes for navigation, which + are practical improvements. In contrast, Response 2 focuses more on general advice and less + actionable suggestions, such as changing variable names and adding comments, which are less critical for immediate code improvement." ``` diff --git a/docs/docs/installation/azure.md b/docs/docs/installation/azure.md index 62ea49ba..22db96a2 100644 --- a/docs/docs/installation/azure.md +++ b/docs/docs/installation/azure.md @@ -40,7 +40,7 @@ stages: export azure_devops__org="$ORG_URL" export config__git_provider="azure" - + pr-agent --pr_url="$PR_URL" describe pr-agent --pr_url="$PR_URL" review pr-agent --pr_url="$PR_URL" improve @@ -65,11 +65,11 @@ git_provider="azure" ``` Azure DevOps provider supports [PAT token](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows) or [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-overview#authentication-in-server-environments) authentication. -PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. +PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. Using DefaultAzureCredential you can use managed identity or Service principle, which are more secure and will create separate ADO user identity (via AAD) to the agent. -If PAT was chosen, you can assign the value in .secrets.toml. -If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, +If PAT was chosen, you can assign the value in .secrets.toml. +If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, or use managed identity/az cli (for local development) without any additional configuration. in any case, 'org' value must be assigned in .secrets.toml: ``` @@ -80,7 +80,7 @@ org = "https://dev.azure.com/YOUR_ORGANIZATION/" ### Azure DevOps Webhook -To trigger from an Azure webhook, you need to manually [add a webhook](https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops). +To trigger from an Azure webhook, you need to manually [add a webhook](https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops). Use the "Pull request created" type to trigger a review, or "Pull request commented on" to trigger any supported comment with / comment on the relevant PR. Note that for the "Pull request commented on" trigger, only API v2.0 is supported. diff --git a/docs/docs/installation/github.md b/docs/docs/installation/github.md index 8035d6db..b7e326ec 100644 --- a/docs/docs/installation/github.md +++ b/docs/docs/installation/github.md @@ -60,7 +60,7 @@ See detailed usage instructions in the [USAGE GUIDE](https://qodo-merge-docs.qod uses: docker://codiumai/pr-agent:0.23-github_action ... ``` - + For enhanced security, you can also specify the Docker image by its [digest](https://hub.docker.com/repository/docker/codiumai/pr-agent/tags): ```yaml ... @@ -71,17 +71,17 @@ See detailed usage instructions in the [USAGE GUIDE](https://qodo-merge-docs.qod ... ``` -### Action for GitHub enterprise server +### Action for GitHub enterprise server !!! tip "" To use the action with a GitHub enterprise server, add an environment variable `GITHUB.BASE_URL` with the API URL of your GitHub server. - + For example, if your GitHub server is at `https://github.mycompany.com`, add the following to your workflow file: ```yaml env: # ... previous environment values GITHUB.BASE_URL: "https://github.mycompany.com/api/v3" ``` - + --- @@ -118,7 +118,7 @@ git clone https://github.com/Codium-ai/pr-agent.git ``` 5) Copy the secrets template file and fill in the following: - + ``` cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets.toml # Edit .secrets.toml file @@ -147,7 +147,7 @@ cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets.toml - mountPath: /app/pr_agent/settings_prod name: settings-volume ``` - + > Another option is to set the secrets as environment variables in your deployment environment, for example `OPENAI.KEY` and `GITHUB.USER_TOKEN`. 6) Build a Docker image for the app and optionally push it to a Docker repository. We'll use Dockerhub as an example: diff --git a/docs/docs/installation/gitlab.md b/docs/docs/installation/gitlab.md index 5a1f23d4..513cdcb9 100644 --- a/docs/docs/installation/gitlab.md +++ b/docs/docs/installation/gitlab.md @@ -74,4 +74,4 @@ docker push codiumai/pr-agent:gitlab_webhook # Push to your Docker repository 6. Create a webhook in GitLab. Set the URL to ```http[s]:///webhook```, the secret token to the generated secret from step 2, and enable the triggers `push`, `comments` and `merge request events`. 7. Test your installation by opening a merge request or commenting on a merge request using one of CodiumAI's commands. -boxes \ No newline at end of file +boxes diff --git a/docs/docs/installation/index.md b/docs/docs/installation/index.md index 27c9a3b2..c5be6189 100644 --- a/docs/docs/installation/index.md +++ b/docs/docs/installation/index.md @@ -15,7 +15,7 @@ There are several ways to use self-hosted Qodo Merge: - [Azure DevOps](./azure.md) ## Qodo Merge Pro 💎 -Qodo Merge Pro, an app hosted by CodiumAI for GitHub\GitLab\BitBucket, is also available. +Qodo Merge Pro, an app hosted by CodiumAI for GitHub\GitLab\BitBucket, is also available.
-With Qodo Merge Pro, installation is as simple as signing up and adding the Qodo Merge app to your relevant repo. +With Qodo Merge Pro, installation is as simple as signing up and adding the Qodo Merge app to your relevant repo. See [here](https://qodo-merge-docs.qodo.ai/installation/pr_agent_pro/) for more details. diff --git a/docs/docs/installation/locally.md b/docs/docs/installation/locally.md index fad9d789..2d9859bf 100644 --- a/docs/docs/installation/locally.md +++ b/docs/docs/installation/locally.md @@ -45,7 +45,7 @@ To invoke a tool (for example `review`), you can run directly from the Docker im ``` docker run --rm -it -e OPENAI.KEY= -e GITHUB.USER_TOKEN= codiumai/pr-agent:latest --pr_url review ``` - If you are using GitHub enterprise server, you need to specify the custom url as variable. + If you are using GitHub enterprise server, you need to specify the custom url as variable. For example, if your GitHub server is at `https://github.mycompany.com`, add the following to the command: ``` -e GITHUB.BASE_URL=https://github.mycompany.com/api/v3 @@ -58,7 +58,7 @@ To invoke a tool (for example `review`), you can run directly from the Docker im If you have a dedicated GitLab instance, you need to specify the custom url as variable: ``` - -e GITLAB.URL= + -e GITLAB.URL= ``` - For BitBucket: @@ -110,4 +110,4 @@ python3 -m pr_agent.cli --issue_url similar_issue [Optional] Add the pr_agent folder to your PYTHONPATH ``` export PYTHONPATH=$PYTHONPATH: -``` \ No newline at end of file +``` diff --git a/docs/docs/installation/pr_agent_pro.md b/docs/docs/installation/pr_agent_pro.md index 0fe870e7..52fc92af 100644 --- a/docs/docs/installation/pr_agent_pro.md +++ b/docs/docs/installation/pr_agent_pro.md @@ -4,12 +4,12 @@ Qodo Merge Pro is a versatile application compatible with GitHub, GitLab, and BitBucket, hosted by CodiumAI. See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for more details about the benefits of using Qodo Merge Pro. -Interested parties can subscribe to Qodo Merge Pro through the following [link](https://www.codium.ai/pricing/). +Interested parties can subscribe to Qodo Merge Pro through the following [link](https://www.codium.ai/pricing/). After subscribing, you are granted the ability to easily install the application across any of your repositories. ![Qodo Merge Pro](https://codium.ai/images/pr_agent/pr_agent_pro_install.png){width=468} -Each user who wants to use Qodo Merge pro needs to buy a seat. +Each user who wants to use Qodo Merge pro needs to buy a seat. Initially, CodiumAI offers a two-week trial period at no cost, after which continued access requires each user to secure a personal seat. Once a user acquires a seat, they gain the flexibility to use Qodo Merge Pro across any repository where it was enabled. @@ -65,4 +65,4 @@ Enable SSL verification: Check the box. You’re all set! -Open a new merge request or add a MR comment with one of Qodo Merge’s commands such as /review, /describe or /improve. \ No newline at end of file +Open a new merge request or add a MR comment with one of Qodo Merge’s commands such as /review, /describe or /improve. diff --git a/docs/docs/overview/index.md b/docs/docs/overview/index.md index f56783bc..2856cc1e 100644 --- a/docs/docs/overview/index.md +++ b/docs/docs/overview/index.md @@ -90,4 +90,4 @@ The following diagram illustrates Qodo Merge tools and their flow: ![Qodo Merge Tools](https://codium.ai/images/pr_agent/diagram-v0.9.png) -Check out the [PR Compression strategy](core-abilities/index.md) page for more details on how we convert a code diff to a manageable LLM prompt \ No newline at end of file +Check out the [PR Compression strategy](core-abilities/index.md) page for more details on how we convert a code diff to a manageable LLM prompt diff --git a/docs/docs/overview/pr_agent_pro.md b/docs/docs/overview/pr_agent_pro.md index aa98add7..c2267774 100644 --- a/docs/docs/overview/pr_agent_pro.md +++ b/docs/docs/overview/pr_agent_pro.md @@ -19,7 +19,7 @@ Here are some of the additional features and capabilities that Qodo Merge Pro of | Feature | Description | |----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [**Model selection**](https://qodo-merge-docs.qodo.ai/usage-guide/PR_agent_pro_models/) | Choose the model that best fits your needs, among top models like `GPT4` and `Claude-Sonnet-3.5` +| [**Model selection**](https://qodo-merge-docs.qodo.ai/usage-guide/PR_agent_pro_models/) | Choose the model that best fits your needs, among top models like `GPT4` and `Claude-Sonnet-3.5` | [**Global and wiki configuration**](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) | Control configurations for many repositories from a single location;
Edit configuration of a single repo without committing code | | [**Apply suggestions**](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) | Generate committable code from the relevant suggestions interactively by clicking on a checkbox | | [**Suggestions impact**](https://qodo-merge-docs.qodo.ai/tools/improve/#assessing-impact) | Automatically mark suggestions that were implemented by the user (either directly in GitHub, or indirectly in the IDE) to enable tracking of the impact of the suggestions | @@ -45,7 +45,7 @@ Here are additional tools that are available only for Qodo Merge Pro users: ### Supported languages -Qodo Merge Pro leverages the world's leading code models - Claude 3.5 Sonnet and GPT-4. +Qodo Merge Pro leverages the world's leading code models - Claude 3.5 Sonnet and GPT-4. As a result, its primary tools such as `describe`, `review`, and `improve`, as well as the PR-chat feature, support virtually all programming languages. For specialized commands that require static code analysis, Qodo Merge Pro offers support for specific languages. For more details about features that require static code analysis, please refer to the [documentation](https://qodo-merge-docs.qodo.ai/tools/analyze/#overview). diff --git a/docs/docs/tools/analyze.md b/docs/docs/tools/analyze.md index 05458b13..c23d4418 100644 --- a/docs/docs/tools/analyze.md +++ b/docs/docs/tools/analyze.md @@ -16,4 +16,4 @@ An example result: **Notes** -- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#. \ No newline at end of file +- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#. diff --git a/docs/docs/tools/ask.md b/docs/docs/tools/ask.md index fca5b725..d29d0319 100644 --- a/docs/docs/tools/ask.md +++ b/docs/docs/tools/ask.md @@ -16,7 +16,7 @@ It can be invoked manually by commenting on any PR: You can run `/ask` on specific lines of code in the PR from the PR's diff view. The tool will answer questions based on the code changes in the selected lines. - Click on the '+' sign next to the line number to select the line. -- To select multiple lines, click on the '+' sign of the first line and then hold and drag to select the rest of the lines. +- To select multiple lines, click on the '+' sign of the first line and then hold and drag to select the rest of the lines. - write `/ask "..."` in the comment box and press `Add single comment` button. ![Ask Line](https://codium.ai/images/pr_agent/Ask_line.png){width=512} @@ -56,4 +56,4 @@ To get a direct link to an image, we recommend using the following scheme: ![Ask image5](https://codium.ai/images/pr_agent/ask_images5.png){width=512} -See a full video tutorial [here](https://codium.ai/images/pr_agent/ask_image_video.mov) \ No newline at end of file +See a full video tutorial [here](https://codium.ai/images/pr_agent/ask_image_video.mov) diff --git a/docs/docs/tools/custom_labels.md b/docs/docs/tools/custom_labels.md index 86b4d671..6df57f90 100644 --- a/docs/docs/tools/custom_labels.md +++ b/docs/docs/tools/custom_labels.md @@ -28,7 +28,7 @@ When working from CLI, you need to apply the [configuration changes](#configurat To enable custom labels, you need to apply the [configuration changes](#configuration-options) to the local `.pr_agent.toml` file in your repository. #### 3. Handle custom labels from the Repo's labels page 💎 -> This feature is available only in Qodo Merge Pro +> This feature is available only in Qodo Merge Pro * GitHub : `https://github.com/{owner}/{repo}/labels`, or click on the "Labels" tab in the issues or PRs page. * GitLab : `https://gitlab.com/{owner}/{repo}/-/labels`, or click on "Manage" -> "Labels" on the left menu. diff --git a/docs/docs/tools/custom_prompt.md b/docs/docs/tools/custom_prompt.md index 675bed69..9baa73d9 100644 --- a/docs/docs/tools/custom_prompt.md +++ b/docs/docs/tools/custom_prompt.md @@ -41,7 +41,7 @@ The code suggestions should focus only on the following: - make sure every variable has a meaningful name - make sure the code is efficient """ -``` +``` (The instructions above are just an example. We want to emphasize that the prompt should be specific and clear, and be tailored to the needs of your project) @@ -55,4 +55,4 @@ Results obtained with the prompt above: `num_code_suggestions`: number of code suggestions provided by the 'custom_prompt' tool. Default is 4. -`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true. \ No newline at end of file +`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true. diff --git a/docs/docs/tools/documentation.md b/docs/docs/tools/documentation.md index bb1330d1..12832b8d 100644 --- a/docs/docs/tools/documentation.md +++ b/docs/docs/tools/documentation.md @@ -30,4 +30,4 @@ You can state a name of a specific component in the PR to get documentation only **Notes** - 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. \ No newline at end of file +- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool. diff --git a/docs/docs/tools/improve.md b/docs/docs/tools/improve.md index 0b1ff8e5..bbc98e4a 100644 --- a/docs/docs/tools/improve.md +++ b/docs/docs/tools/improve.md @@ -83,15 +83,15 @@ This feature is controlled by a boolean configuration parameter: `pr_code_sugges !!! note "Wiki must be enabled" While the aggregation process is automatic, GitHub repositories require a one-time manual wiki setup. - - To initialize the wiki: navigate to `Wiki`, select `Create the first page`, then click `Save page`. + + To initialize the wiki: navigate to `Wiki`, select `Create the first page`, then click `Save page`. ![pr_agent_accepted_suggestions_create_first_page.png](https://qodo.ai/images/pr_agent/pr_agent_accepted_suggestions_create_first_page.png){width=768} Once a wiki repo is created, the tool will automatically use this wiki for tracking suggestions. !!! note "Why a wiki page?" - Your code belongs to you, and we respect your privacy. Hence, we won't store any code suggestions in an external database. + Your code belongs to you, and we respect your privacy. Hence, we won't store any code suggestions in an external database. Instead, we leverage a dedicated private page, within your repository wiki, to track suggestions. This approach offers convenient secure suggestion tracking while avoiding pull requests or any noise to the main repository. @@ -109,10 +109,10 @@ In addition to mistakes (which may happen, but are rare), sometimes the presente In such cases, we recommend prioritizing the suggestion's detailed description, using the diff snippet primarily as a supporting reference. ### Dual publishing mode -Our recommended approach for presenting code suggestions is through a [table](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) (`--pr_code_suggestions.commitable_code_suggestions=false`). +Our recommended approach for presenting code suggestions is through a [table](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) (`--pr_code_suggestions.commitable_code_suggestions=false`). This method significantly reduces the PR footprint and allows for quick and easy digestion of multiple suggestions. -We also offer a complementary **dual publishing mode**. When enabled, suggestions exceeding a certain score threshold are not only displayed in the table, but also presented as commitable PR comments. +We also offer a complementary **dual publishing mode**. When enabled, suggestions exceeding a certain score threshold are not only displayed in the table, but also presented as commitable PR comments. This mode helps highlight suggestions deemed more critical. To activate dual publishing mode, use the following setting: @@ -165,9 +165,9 @@ code_suggestions_self_review_text = "... (your text here) ..." ![self_review_2](https://codium.ai/images/pr_agent/self_review_2.png){width=512} - If you keep the number of required reviewers for a PR to 1 and enable this configuration, this effectively means that the PR author can approve the PR by actively clicking the self-review checkbox. - + 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. - + ### 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: @@ -199,7 +199,7 @@ Note: Chunking is primarily relevant for large PRs. For most PRs (up to 500 line 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. Specify relevant aspects that you want the model to focus on. - + Examples for possible instructions: ```toml [pr_code_suggestions] @@ -216,11 +216,11 @@ Use triple quotes to write multi-line instructions. Use bullet points or numbers >`Platforms supported: GitHub, GitLab` -Another option to give additional guidance to the AI model is by creating a dedicated [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) called `best_practices.md`. +Another option to give additional guidance to the AI model is by creating a dedicated [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) called `best_practices.md`. This page can contain a list of best practices, coding standards, and guidelines that are specific to your repo/organization. The AI model will use this wiki page as a reference, and in case the PR code violates any of the guidelines, it will suggest improvements accordingly, with a dedicated label: `Organization -best practice`. +best practice`. Example for a `best_practices.md` content can be found [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md) (adapted from Google's [pyguide](https://google.github.io/styleguide/pyguide.html)). This file is only an example. Since it is used as a prompt for an AI model, we want to emphasize the following: @@ -230,7 +230,7 @@ This file is only an example. Since it is used as a prompt for an AI model, we w - Recommended to limit the text to 800 lines or fewer. Here’s why: 1) Extremely long best practices documents may not be fully processed by the AI model. - + 2) A lengthy file probably represent a more "**generic**" set of guidelines, which the AI model is already familiar with. The objective is to focus on a more targeted set of guidelines tailored to the specific needs of this project. ##### Local and global best practices @@ -261,7 +261,7 @@ Using a combination of both can help the AI model to provide relevant and tailor ## Configuration options ??? example "General options" - + @@ -335,5 +335,5 @@ Using a combination of both can help the AI model to provide relevant and tailor - Only if the `Category` header is relevant, the user should move to the summarized suggestion description - Only if the summarized suggestion description is relevant, the user should click on the collapsible, to read the full suggestion description with a code preview example. -- In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. +- In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. - The interactive [PR chat](https://qodo-merge-docs.qodo.ai/chrome-extension/) also provides an easy way to get more tailored suggestions and feedback from the AI model. diff --git a/docs/docs/tools/improve_component.md b/docs/docs/tools/improve_component.md index 4e0c8890..b3aac539 100644 --- a/docs/docs/tools/improve_component.md +++ b/docs/docs/tools/improve_component.md @@ -26,4 +26,4 @@ The tool will generate code suggestions for the selected component (if no compon - `num_code_suggestions`: number of code suggestions to provide. Default is 4 - `extra_instructions`: Optional extra instructions to the tool. For example: "focus on ...". - `file`: in case there are several components with the same name, you can specify the relevant file. -- `class_name`: in case there are several methods with the same name in the same file, you can specify the relevant class name. \ No newline at end of file +- `class_name`: in case there are several methods with the same name in the same file, you can specify the relevant class name. diff --git a/docs/docs/tools/index.md b/docs/docs/tools/index.md index 394bdbab..9b856e23 100644 --- a/docs/docs/tools/index.md +++ b/docs/docs/tools/index.md @@ -19,4 +19,4 @@ Here is a list of Qodo Merge tools, each with a dedicated page that explains how | **💎 [Improve Component (`/improve_component component_name`](./improve_component.md))** | Generates code suggestions for a specific code component that changed in the PR | | **💎 [CI Feedback (`/checks ci_job`](./ci_feedback.md))** | Automatically generates feedback and analysis for a failed CI job | -Note that the tools marked with 💎 are available only for Qodo Merge Pro users. \ No newline at end of file +Note that the tools marked with 💎 are available only for Qodo Merge Pro users. diff --git a/docs/docs/tools/review.md b/docs/docs/tools/review.md index 2fd774f6..5d70c9e4 100644 --- a/docs/docs/tools/review.md +++ b/docs/docs/tools/review.md @@ -180,10 +180,10 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review The `review` tool provides a collection of configurable feedbacks about a PR. It is recommended to review the [Configuration options](#configuration-options) section, and choose the relevant options for your use case. - - Some of the features that are disabled by default are quite useful, and should be considered for enabling. For example: + + Some of the features that are disabled by default are quite useful, and should be considered for enabling. For example: `require_score_review`, and more. - + On the other hand, if you find one of the enabled features to be irrelevant for your use case, disable it. No default configuration can fit all use cases. !!! tip "Automation" @@ -197,19 +197,19 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review !!! tip "Possible labels from the review tool" The `review` tool can auto-generate two specific types of labels for a PR: - + - a `possible security issue` label that detects if a possible [security issue](https://github.com/Codium-ai/pr-agent/blob/tr/user_description/pr_agent/settings/pr_reviewer_prompts.toml#L136) exists in the PR code (`enable_review_labels_security` flag) - a `Review effort [1-5]: x` label, where x is the estimated effort to review the PR (`enable_review_labels_effort` flag) - + Both modes are useful, and we recommended to enable them. !!! tip "Extra instructions" Extra instructions are important. The `review` tool can be configured with extra instructions, which can be used to guide the model to a feedback tailored to the needs of your project. - + Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Specify the relevant sub-tool, and the relevant aspects of the PR that you want to emphasize. - + Examples of extra instructions: ``` [pr_reviewer] @@ -227,22 +227,22 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review !!! 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. - - + + You can also enable auto-approval only if the PR meets certain requirements, such as that the `estimated_review_effort` label is equal or below a certain threshold, by adjusting the flag: ``` [pr_reviewer] @@ -258,4 +258,3 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review [//]: # ( Notice If you are interested **only** in the code suggestions, it is recommended to use the [`improve`](./improve.md) feature instead, since it is a dedicated only to code suggestions, and usually gives better results.) [//]: # ( Use the `review` tool if you want to get more comprehensive feedback, which includes code suggestions as well.) - diff --git a/docs/docs/tools/similar_code.md b/docs/docs/tools/similar_code.md index c992a262..11de3a0c 100644 --- a/docs/docs/tools/similar_code.md +++ b/docs/docs/tools/similar_code.md @@ -51,7 +51,7 @@ It can be invoked automatically from the analyze table, can be accessed by: Choose the components you want to find similar code for, and click on the `similar` checkbox. ![analyze similar](https://codium.ai/images/pr_agent/analyze_similar.png){width=768} -If you are looking to search for similar code in the organization's codebase, you can click on the `Organization` checkbox, and it will invoke a new search command just for the organization's codebase. +If you are looking to search for similar code in the organization's codebase, you can click on the `Organization` checkbox, and it will invoke a new search command just for the organization's codebase. ![similar code global](https://codium.ai/images/pr_agent/similar_code_global.png){width=768} diff --git a/docs/docs/tools/similar_issues.md b/docs/docs/tools/similar_issues.md index 4f0351e0..d701c1c6 100644 --- a/docs/docs/tools/similar_issues.md +++ b/docs/docs/tools/similar_issues.md @@ -17,7 +17,7 @@ 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). -**Select VectorDBs** by changing `pr_similar_issue` parameter in `configuration.toml` file +**Select VectorDBs** by changing `pr_similar_issue` parameter in `configuration.toml` file 2 VectorDBs are available to switch in 1. LanceDB @@ -40,4 +40,4 @@ These parameters can be obtained by registering to [Pinecone](https://app.pineco - To invoke the 'similar' issue tool via online usage, [comment](https://github.com/Codium-ai/pr-agent/issues/178#issuecomment-1716934893) on a PR: `/similar_issue` -- You can also enable the 'similar issue' tool to run automatically when a new issue is opened, by adding it to the [pr_commands list in the github_app section](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L66) \ No newline at end of file +- You can also enable the 'similar issue' tool to run automatically when a new issue is opened, by adding it to the [pr_commands list in the github_app section](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L66) diff --git a/docs/docs/tools/test.md b/docs/docs/tools/test.md index b5a143f0..f3cc3910 100644 --- a/docs/docs/tools/test.md +++ b/docs/docs/tools/test.md @@ -29,4 +29,4 @@ The tool will generate tests for the selected component (if no component is stat - `extra_instructions`: Optional extra instructions to the tool. For example: "use the following mock injection scheme: ...". - `file`: in case there are several components with the same name, you can specify the relevant file. - `class_name`: in case there are several methods with the same name in the same file, you can specify the relevant class name. -- `enable_help_text`: if set to true, the tool will add a help text to the PR comment. Default is true. \ No newline at end of file +- `enable_help_text`: if set to true, the tool will add a help text to the PR comment. Default is true. diff --git a/docs/docs/tools/update_changelog.md b/docs/docs/tools/update_changelog.md index 0c1bfda5..9f880ccd 100644 --- a/docs/docs/tools/update_changelog.md +++ b/docs/docs/tools/update_changelog.md @@ -16,4 +16,4 @@ It can be invoked manually by commenting on any PR: Under the section `pr_update_changelog`, the [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L50) contains options to customize the 'update changelog' tool: - `push_changelog_changes`: whether to push the changes to CHANGELOG.md, or just print them. Default is false (print only). -- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ... \ No newline at end of file +- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ... diff --git a/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md b/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md index 0ec886a6..e9de20d8 100644 --- a/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md +++ b/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md @@ -186,4 +186,4 @@ Do not rely on the atomicity of built-in types. While Python’s built-in data types such as dictionaries appear to have atomic operations, there are corner cases where they aren’t atomic (e.g. if `__hash__` or `__eq__` are implemented as Python methods) and their atomicity should not be relied upon. Neither should you rely on atomic variable assignment (since this in turn depends on dictionaries). -Use the `queue` module’s `Queue` data type as the preferred way to communicate data between threads. Otherwise, use the `threading` module and its locking primitives. Prefer condition variables and `threading.Condition` instead of using lower-level locks. \ No newline at end of file +Use the `queue` module’s `Queue` data type as the preferred way to communicate data between threads. Otherwise, use the `threading` module and its locking primitives. Prefer condition variables and `threading.Condition` instead of using lower-level locks. diff --git a/docs/docs/usage-guide/automations_and_usage.md b/docs/docs/usage-guide/automations_and_usage.md index 57e1adeb..6fca67ec 100644 --- a/docs/docs/usage-guide/automations_and_usage.md +++ b/docs/docs/usage-guide/automations_and_usage.md @@ -66,7 +66,7 @@ Any configuration value in [configuration file](https://github.com/Codium-ai/pr- ### GitHub app automatic tools when a new PR is opened -The [github_app](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L108) section defines GitHub app specific configurations. +The [github_app](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L108) section defines GitHub app specific configurations. The configuration parameter `pr_commands` defines the list of tools that will be **run automatically** when a new PR is opened. ``` @@ -77,10 +77,10 @@ pr_commands = [ "/improve", ] ``` -This means that when a new PR is opened/reopened or marked as ready for review, Qodo Merge will run the `describe`, `review` and `improve` tools. +This means that when a new PR is opened/reopened or marked as ready for review, Qodo Merge will run the `describe`, `review` and `improve` tools. For the `review` tool, for example, the `num_code_suggestions` parameter will be set to 0. -You can override the default tool parameters by using one the three options for a [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/): **wiki**, **local**, or **global**. +You can override the default tool parameters by using one the three options for a [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/): **wiki**, **local**, or **global**. For example, if your local `.pr_agent.toml` file contains: ``` [pr_description] @@ -98,7 +98,7 @@ pr_commands = [] In addition to running automatic tools when a PR is opened, the GitHub app can also respond to new code that is pushed to an open PR. -The configuration toggle `handle_push_trigger` can be used to enable this feature. +The configuration toggle `handle_push_trigger` can be used to enable this feature. The configuration parameter `push_commands` defines the list of tools that will be **run automatically** when new code is pushed to the PR. ``` [github_app] @@ -112,7 +112,7 @@ This means that when new code is pushed to the PR, the Qodo Merge will run the ` ## GitHub Action `GitHub Action` is a different way to trigger Qodo Merge tools, and uses a different configuration mechanism than `GitHub App`.
-You can configure settings for `GitHub Action` by adding environment variables under the env section in `.github/workflows/pr_agent.yml` file. +You can configure settings for `GitHub Action` by adding environment variables under the env section in `.github/workflows/pr_agent.yml` file. Specifically, start by setting the following environment variables: ```yaml env: @@ -129,7 +129,7 @@ If not set, the default configuration is for all three tools to run automaticall `github_action_config.pr_actions` is used to configure which `pull_requests` events will trigger the enabled auto flags If not set, the default configuration is `["opened", "reopened", "ready_for_review", "review_requested"]` -`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`). +`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). @@ -154,7 +154,7 @@ pr_commands = [ ``` the GitLab webhook can also respond to new code that is pushed to an open MR. -The configuration toggle `handle_push_trigger` can be used to enable this feature. +The configuration toggle `handle_push_trigger` can be used to enable this feature. The configuration parameter `push_commands` defines the list of tools that will be **run automatically** when new code is pushed to the MR. ``` [gitlab] @@ -210,11 +210,11 @@ git_provider="azure" ``` Azure DevOps provider supports [PAT token](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows) or [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-overview#authentication-in-server-environments) authentication. -PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. +PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. Using DefaultAzureCredential you can use managed identity or Service principle, which are more secure and will create separate ADO user identity (via AAD) to the agent. -If PAT was chosen, you can assign the value in .secrets.toml. -If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, +If PAT was chosen, you can assign the value in .secrets.toml. +If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, or use managed identity/az cli (for local development) without any additional configuration. in any case, 'org' value must be assigned in .secrets.toml: ``` diff --git a/docs/docs/usage-guide/changing_a_model.md b/docs/docs/usage-guide/changing_a_model.md index f214f716..d5f6ae03 100644 --- a/docs/docs/usage-guide/changing_a_model.md +++ b/docs/docs/usage-guide/changing_a_model.md @@ -9,7 +9,7 @@ model_turbo = "..." fallback_models = ["..."] ``` -For models and environments not from OpenAI, you might need to provide additional keys and other parameters. +For models and environments not from OpenAI, you might need to provide additional keys and other parameters. You can give parameters via a configuration file (see below for instructions), or from environment variables. See [litellm documentation](https://litellm.vercel.app/docs/proxy/quick_start#supported-llms) for the environment variables relevant per model. ### Azure @@ -108,7 +108,7 @@ To use Llama3 model with Groq, for example, set: [config] # in configuration.toml model = "llama3-70b-8192" model_turbo = "llama3-70b-8192" -fallback_models = ["groq/llama3-70b-8192"] +fallback_models = ["groq/llama3-70b-8192"] [groq] # in .secrets.toml key = ... # your Groq api key ``` @@ -118,7 +118,7 @@ key = ... # your Groq api key To use Google's Vertex AI platform and its associated models (chat-bison/codechat-bison) set: -``` +``` [config] # in configuration.toml model = "vertex_ai/codechat-bison" model_turbo = "vertex_ai/codechat-bison" @@ -170,7 +170,7 @@ KEY = "..." To use Amazon Bedrock and its foundational models, add the below configuration: -``` +``` [config] # in configuration.toml model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0" model_turbo="bedrock/anthropic.claude-3-sonnet-20240229-v1:0" diff --git a/docs/docs/usage-guide/configuration_options.md b/docs/docs/usage-guide/configuration_options.md index 7b5607b7..c97b6531 100644 --- a/docs/docs/usage-guide/configuration_options.md +++ b/docs/docs/usage-guide/configuration_options.md @@ -20,7 +20,7 @@ In terms of precedence, wiki configurations will override local configurations, `Platforms supported: GitHub, GitLab, Bitbucket` -With Qodo Merge Pro, you can set configurations by creating a page called `.pr_agent.toml` in the [wiki](https://github.com/Codium-ai/pr-agent/wiki/pr_agent.toml) of the repo. +With Qodo Merge Pro, you can set configurations by creating a page called `.pr_agent.toml` in the [wiki](https://github.com/Codium-ai/pr-agent/wiki/pr_agent.toml) of the repo. The advantage of this method is that it allows to set configurations without needing to commit new content to the repo - just edit the wiki page and **save**. diff --git a/docs/docs/usage-guide/index.md b/docs/docs/usage-guide/index.md index bd1b93f4..1b680d8c 100644 --- a/docs/docs/usage-guide/index.md +++ b/docs/docs/usage-guide/index.md @@ -1,6 +1,6 @@ # Usage guide -This page provides a detailed guide on how to use Qodo Merge. +This page provides a detailed guide on how to use Qodo Merge. It includes information on how to adjust Qodo Merge configurations, define which tools will run automatically, and other advanced configurations. @@ -23,4 +23,4 @@ It includes information on how to adjust Qodo Merge configurations, define which - [Changing a model](./additional_configurations.md#changing-a-model) - [Patch Extra Lines](./additional_configurations.md#patch-extra-lines) - [Editing the prompts](./additional_configurations.md#editing-the-prompts) -- [Qodo Merge Pro Models](./PR_agent_pro_models.md) \ No newline at end of file +- [Qodo Merge Pro Models](./PR_agent_pro_models.md) diff --git a/docs/docs/usage-guide/introduction.md b/docs/docs/usage-guide/introduction.md index 687500a4..521ce6d7 100644 --- a/docs/docs/usage-guide/introduction.md +++ b/docs/docs/usage-guide/introduction.md @@ -10,4 +10,3 @@ Specifically, CLI commands can be issued by invoking a pre-built [docker image]( For online usage, you will need to setup either a [GitHub App](https://qodo-merge-docs.qodo.ai/installation/github/#run-as-a-github-app) or a [GitHub Action](https://qodo-merge-docs.qodo.ai/installation/github/#run-as-a-github-action) (GitHub), a [GitLab webhook](https://qodo-merge-docs.qodo.ai/installation/gitlab/#run-a-gitlab-webhook-server) (GitLab), or a [BitBucket App](https://qodo-merge-docs.qodo.ai/installation/bitbucket/#run-using-codiumai-hosted-bitbucket-app) (BitBucket). These platforms also enable to run Qodo Merge specific tools automatically when a new PR is opened, or on each push to a branch. - diff --git a/docs/docs/usage-guide/mail_notifications.md b/docs/docs/usage-guide/mail_notifications.md index 42fd7a8d..a1d97016 100644 --- a/docs/docs/usage-guide/mail_notifications.md +++ b/docs/docs/usage-guide/mail_notifications.md @@ -9,10 +9,10 @@ As an alternative, you can filter in your mail provider the notifications specif ![filter_mail_notifications](https://codium.ai/images/pr_agent/filter_mail_notifications.png){width=512} -Another option to reduce the mail overload, yet still receive notifications on Qodo Merge tools, is to disable the help collapsible section in Qodo Merge bot comments. +Another option to reduce the mail overload, yet still receive notifications on Qodo Merge tools, is to disable the help collapsible section in Qodo Merge bot comments. This can done by setting `enable_help_text=false` for the relevant tool in the configuration file. For example, to disable the help text for the `pr_reviewer` tool, set: ``` [pr_reviewer] enable_help_text = false -``` \ No newline at end of file +``` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f6957536..53ae3c24 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -144,8 +144,8 @@ markdown_extensions: - md_in_html - attr_list - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg + emoji_index: "!!python/name:material.extensions.emoji.twemoji" + emoji_generator: "!!python/name:material.extensions.emoji.to_svg" - toc: title: On this page toc_depth: 3 diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 93a67950..2f0de5ae 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -2,9 +2,9 @@ {% block scripts %} {{ super() }} - + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/docs/overrides/partials/footer.html b/docs/overrides/partials/footer.html index e41686ac..23f40894 100644 --- a/docs/overrides/partials/footer.html +++ b/docs/overrides/partials/footer.html @@ -42,7 +42,7 @@ } .social-icons svg { - width: 24px; + width: 24px; height: auto; fill: white; } diff --git a/docs/overrides/partials/integrations/analytics/custom.html b/docs/overrides/partials/integrations/analytics/custom.html index 9a0785d2..63dc6503 100644 --- a/docs/overrides/partials/integrations/analytics/custom.html +++ b/docs/overrides/partials/integrations/analytics/custom.html @@ -4,4 +4,4 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5C9KZBM3'); - \ No newline at end of file + diff --git a/pr_agent/__init__.py b/pr_agent/__init__.py index 8b137891..e69de29b 100644 --- a/pr_agent/__init__.py +++ b/pr_agent/__init__.py @@ -1 +0,0 @@ - diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index 8bf6cff7..d16e7a5c 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -3,7 +3,6 @@ from functools import partial from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler - from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings from pr_agent.git_providers.utils import apply_repo_settings diff --git a/pr_agent/algo/ai_handlers/base_ai_handler.py b/pr_agent/algo/ai_handlers/base_ai_handler.py index e3274eac..956fcaff 100644 --- a/pr_agent/algo/ai_handlers/base_ai_handler.py +++ b/pr_agent/algo/ai_handlers/base_ai_handler.py @@ -3,7 +3,7 @@ from abc import ABC, abstractmethod class BaseAiHandler(ABC): """ - This class defines the interface for an AI handler to be used by the PR Agents. + This class defines the interface for an AI handler to be used by the PR Agents. """ @abstractmethod @@ -23,6 +23,6 @@ class BaseAiHandler(ABC): model (str): the name of the model to use for the chat completion system (str): the system message string to use for the chat completion user (str): the user message string to use for the chat completion - temperature (float): the temperature to use for the chat completion + temperature (float): the temperature to use for the chat completion """ pass diff --git a/pr_agent/algo/ai_handlers/langchain_ai_handler.py b/pr_agent/algo/ai_handlers/langchain_ai_handler.py index 2f3b88c1..d4ea0aa5 100644 --- a/pr_agent/algo/ai_handlers/langchain_ai_handler.py +++ b/pr_agent/algo/ai_handlers/langchain_ai_handler.py @@ -1,17 +1,18 @@ try: - from langchain_openai import ChatOpenAI, AzureChatOpenAI - from langchain_core.messages import SystemMessage, HumanMessage + from langchain_core.messages import HumanMessage, SystemMessage + from langchain_openai import AzureChatOpenAI, ChatOpenAI except: # we don't enforce langchain as a dependency, so if it's not installed, just move on pass +import functools + +from openai import APIError, RateLimitError, Timeout +from retry import retry + from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.config_loader import get_settings from pr_agent.log import get_logger -from openai import APIError, RateLimitError, Timeout -from retry import retry -import functools - OPENAI_RETRIES = 5 @@ -73,4 +74,3 @@ class LangChainOpenAIHandler(BaseAiHandler): raise ValueError(f"OpenAI {e.name} is required") from e else: raise e - diff --git a/pr_agent/algo/ai_handlers/litellm_ai_handler.py b/pr_agent/algo/ai_handlers/litellm_ai_handler.py index 882e2370..ad1fc564 100644 --- a/pr_agent/algo/ai_handlers/litellm_ai_handler.py +++ b/pr_agent/algo/ai_handlers/litellm_ai_handler.py @@ -1,7 +1,8 @@ import os -import requests + import litellm import openai +import requests from litellm import acompletion from tenacity import retry, retry_if_exception_type, stop_after_attempt diff --git a/pr_agent/algo/ai_handlers/openai_ai_handler.py b/pr_agent/algo/ai_handlers/openai_ai_handler.py index 999f3d3f..b235af96 100644 --- a/pr_agent/algo/ai_handlers/openai_ai_handler.py +++ b/pr_agent/algo/ai_handlers/openai_ai_handler.py @@ -1,8 +1,8 @@ -from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler import openai from openai.error import APIError, RateLimitError, Timeout, TryAgain from retry import retry +from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.config_loader import get_settings from pr_agent.log import get_logger diff --git a/pr_agent/algo/git_patch_processing.py b/pr_agent/algo/git_patch_processing.py index f0540ad0..0ccce92d 100644 --- a/pr_agent/algo/git_patch_processing.py +++ b/pr_agent/algo/git_patch_processing.py @@ -3,8 +3,8 @@ from __future__ import annotations import re import traceback -from pr_agent.config_loader import get_settings from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.config_loader import get_settings from pr_agent.log import get_logger @@ -388,4 +388,4 @@ def extract_hunk_lines_from_patch(patch: str, file_name, line_start, line_end, s if not line.startswith('-'): # currently we don't support /ask line for deleted lines selected_lines_num += 1 - return patch_with_lines_str.rstrip(), selected_lines.rstrip() \ No newline at end of file + return patch_with_lines_str.rstrip(), selected_lines.rstrip() diff --git a/pr_agent/algo/language_handler.py b/pr_agent/algo/language_handler.py index 7c103998..dea77260 100644 --- a/pr_agent/algo/language_handler.py +++ b/pr_agent/algo/language_handler.py @@ -4,8 +4,6 @@ from typing import Dict from pr_agent.config_loader import get_settings - - def filter_bad_extensions(files): # Bad Extensions, source: https://github.com/EleutherAI/github-downloader/blob/345e7c4cbb9e0dc8a0615fd995a08bf9d73b3fe6/download_repo_text.py # noqa: E501 bad_extensions = get_settings().bad_extensions.default diff --git a/pr_agent/algo/pr_processing.py b/pr_agent/algo/pr_processing.py index 95d2fda7..114e24a0 100644 --- a/pr_agent/algo/pr_processing.py +++ b/pr_agent/algo/pr_processing.py @@ -5,14 +5,15 @@ from typing import Callable, List, Tuple from github import RateLimitExceededException -from pr_agent.algo.git_patch_processing import convert_to_hunks_with_lines_numbers, extend_patch, handle_patch_deletions -from pr_agent.algo.language_handler import sort_files_by_main_languages from pr_agent.algo.file_filter import filter_ignored +from pr_agent.algo.git_patch_processing import ( + convert_to_hunks_with_lines_numbers, extend_patch, handle_patch_deletions) +from pr_agent.algo.language_handler import sort_files_by_main_languages from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import get_max_tokens, clip_tokens, ModelType +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.algo.utils import ModelType, clip_tokens, get_max_tokens from pr_agent.config_loader import get_settings from pr_agent.git_providers.git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.log import get_logger DELETED_FILES_ = "Deleted files:\n" diff --git a/pr_agent/algo/token_handler.py b/pr_agent/algo/token_handler.py index 935e6da5..72f6184e 100644 --- a/pr_agent/algo/token_handler.py +++ b/pr_agent/algo/token_handler.py @@ -1,8 +1,9 @@ -from jinja2 import Environment, StrictUndefined -from tiktoken import encoding_for_model, get_encoding -from pr_agent.config_loader import get_settings from threading import Lock +from jinja2 import Environment, StrictUndefined +from tiktoken import encoding_for_model, get_encoding + +from pr_agent.config_loader import get_settings from pr_agent.log import get_logger @@ -85,4 +86,4 @@ class TokenHandler: Returns: The number of tokens in the patch string. """ - return len(self.encoder.encode(patch, disallowed_special=())) \ No newline at end of file + return len(self.encoder.encode(patch, disallowed_special=())) diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 6a23d609..a90636d3 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -14,7 +14,6 @@ from datetime import datetime from enum import Enum from typing import Any, List, Tuple - import html2text import requests import yaml @@ -23,10 +22,11 @@ from starlette_context import context from pr_agent.algo import MAX_TOKENS from pr_agent.algo.token_handler import TokenEncoder -from pr_agent.config_loader import get_settings, global_settings from pr_agent.algo.types import FilePatchInfo +from pr_agent.config_loader import get_settings, global_settings from pr_agent.log import get_logger + class Range(BaseModel): line_start: int # should be 0-indexed line_end: int diff --git a/pr_agent/cli.py b/pr_agent/cli.py index 98b493de..5f8afc88 100644 --- a/pr_agent/cli.py +++ b/pr_agent/cli.py @@ -4,7 +4,7 @@ import os from pr_agent.agent.pr_agent import PRAgent, commands from pr_agent.config_loader import get_settings -from pr_agent.log import setup_logger, get_logger +from pr_agent.log import get_logger, setup_logger log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/pr_agent/git_providers/__init__.py b/pr_agent/git_providers/__init__.py index c7e3e6e8..16547d90 100644 --- a/pr_agent/git_providers/__init__.py +++ b/pr_agent/git_providers/__init__.py @@ -1,14 +1,16 @@ +from starlette_context import context + from pr_agent.config_loader import get_settings +from pr_agent.git_providers.azuredevops_provider import AzureDevopsProvider from pr_agent.git_providers.bitbucket_provider import BitbucketProvider -from pr_agent.git_providers.bitbucket_server_provider import BitbucketServerProvider +from pr_agent.git_providers.bitbucket_server_provider import \ + BitbucketServerProvider from pr_agent.git_providers.codecommit_provider import CodeCommitProvider +from pr_agent.git_providers.gerrit_provider import GerritProvider from pr_agent.git_providers.git_provider import GitProvider from pr_agent.git_providers.github_provider import GithubProvider from pr_agent.git_providers.gitlab_provider import GitLabProvider from pr_agent.git_providers.local_git_provider import LocalGitProvider -from pr_agent.git_providers.azuredevops_provider import AzureDevopsProvider -from pr_agent.git_providers.gerrit_provider import GerritProvider -from starlette_context import context _GIT_PROVIDERS = { 'github': GithubProvider, diff --git a/pr_agent/git_providers/azuredevops_provider.py b/pr_agent/git_providers/azuredevops_provider.py index de782998..df87c564 100644 --- a/pr_agent/git_providers/azuredevops_provider.py +++ b/pr_agent/git_providers/azuredevops_provider.py @@ -2,33 +2,33 @@ import os from typing import Optional, Tuple from urllib.parse import urlparse -from ..algo.file_filter import filter_ignored -from ..log import get_logger -from ..algo.language_handler import is_valid_file -from ..algo.utils import clip_tokens, find_line_number_of_relevant_line_in_file, load_large_diff, PRDescriptionHeader -from ..config_loader import get_settings -from .git_provider import GitProvider from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from ..algo.file_filter import filter_ignored +from ..algo.language_handler import is_valid_file +from ..algo.utils import (PRDescriptionHeader, clip_tokens, + find_line_number_of_relevant_line_in_file, + load_large_diff) +from ..config_loader import get_settings +from ..log import get_logger +from .git_provider import GitProvider + AZURE_DEVOPS_AVAILABLE = True ADO_APP_CLIENT_DEFAULT_ID = "499b84ac-1321-427f-aa17-267ca6975798/.default" MAX_PR_DESCRIPTION_AZURE_LENGTH = 4000-1 try: # noinspection PyUnresolvedReferences - from msrest.authentication import BasicAuthentication # noinspection PyUnresolvedReferences from azure.devops.connection import Connection # noinspection PyUnresolvedReferences - from azure.identity import DefaultAzureCredential + from azure.devops.v7_1.git.models import (Comment, CommentThread, + GitPullRequest, + GitPullRequestIterationChanges, + GitVersionDescriptor) # noinspection PyUnresolvedReferences - from azure.devops.v7_1.git.models import ( - Comment, - CommentThread, - GitVersionDescriptor, - GitPullRequest, - GitPullRequestIterationChanges, - ) + from azure.identity import DefaultAzureCredential + from msrest.authentication import BasicAuthentication except ImportError: AZURE_DEVOPS_AVAILABLE = False @@ -620,4 +620,3 @@ class AzureDevopsProvider(GitProvider): def publish_file_comments(self, file_comments: list) -> bool: pass - diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index 51ba0770..76313ddf 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -6,13 +6,14 @@ import requests from atlassian.bitbucket import Cloud from starlette_context import context -from pr_agent.algo.types import FilePatchInfo, EDIT_TYPE +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo + from ..algo.file_filter import filter_ignored from ..algo.language_handler import is_valid_file from ..algo.utils import find_line_number_of_relevant_line_in_file from ..config_loader import get_settings from ..log import get_logger -from .git_provider import GitProvider, MAX_FILES_ALLOWED_FULL +from .git_provider import MAX_FILES_ALLOWED_FULL, GitProvider def _gef_filename(diff): diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index 7588075e..5fb599e4 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -1,16 +1,17 @@ from distutils.version import LooseVersion -from requests.exceptions import HTTPError from typing import Optional, Tuple from urllib.parse import quote_plus, urlparse from atlassian.bitbucket import Bitbucket +from requests.exceptions import HTTPError -from .git_provider import GitProvider -from ..algo.types import EDIT_TYPE, FilePatchInfo from ..algo.language_handler import is_valid_file -from ..algo.utils import load_large_diff, find_line_number_of_relevant_line_in_file +from ..algo.types import EDIT_TYPE, FilePatchInfo +from ..algo.utils import (find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings from ..log import get_logger +from .git_provider import GitProvider class BitbucketServerProvider(GitProvider): diff --git a/pr_agent/git_providers/codecommit_provider.py b/pr_agent/git_providers/codecommit_provider.py index 89a0254d..c4f1ed7b 100644 --- a/pr_agent/git_providers/codecommit_provider.py +++ b/pr_agent/git_providers/codecommit_provider.py @@ -4,13 +4,15 @@ from collections import Counter from typing import List, Optional, Tuple from urllib.parse import urlparse -from pr_agent.git_providers.codecommit_client import CodeCommitClient +from pr_agent.algo.language_handler import is_valid_file from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.git_providers.codecommit_client import CodeCommitClient + from ..algo.utils import load_large_diff -from .git_provider import GitProvider from ..config_loader import get_settings from ..log import get_logger -from pr_agent.algo.language_handler import is_valid_file +from .git_provider import GitProvider + class PullRequestCCMimic: """ @@ -162,7 +164,7 @@ class CodeCommitProvider(GitProvider): pr_body=CodeCommitProvider._add_additional_newlines(pr_body), ) except Exception as e: - raise ValueError(f"CodeCommit Cannot publish description for PR: {self.pr_num}") from e + raise ValueError(f"CodeCommit Cannot publish description for PR: {self.pr_num}") from e def publish_comment(self, pr_comment: str, is_temporary: bool = False): if is_temporary: @@ -190,7 +192,7 @@ class CodeCommitProvider(GitProvider): if not all(key in suggestion for key in ["body", "relevant_file", "relevant_lines_start"]): get_logger().warning(f"Skipping code suggestion #{counter}: Each suggestion must have 'body', 'relevant_file', 'relevant_lines_start' keys") continue - + # Publish the code suggestion to CodeCommit try: get_logger().debug(f"Code Suggestion #{counter} in file: {suggestion['relevant_file']}: {suggestion['relevant_lines_start']}") @@ -205,12 +207,12 @@ class CodeCommitProvider(GitProvider): ) except Exception as e: raise ValueError(f"CodeCommit Cannot publish code suggestions for PR: {self.pr_num}") from e - + counter += 1 # The calling function passes in a list of code suggestions, and this function publishes each suggestion one at a time. # If we were to return False here, the calling function will attempt to publish the same list of code suggestions again, one at a time. - # Since this function publishes the suggestions one at a time anyway, we always return True here to avoid the retry. + # Since this function publishes the suggestions one at a time anyway, we always return True here to avoid the retry. return True def publish_labels(self, labels): @@ -238,7 +240,7 @@ class CodeCommitProvider(GitProvider): def get_pr_id(self): """ Returns the PR ID in the format: "repo_name/pr_number". - Note: This is an internal identifier for PR-Agent, + Note: This is an internal identifier for PR-Agent, and is not the same as the CodeCommit PR identifier. """ try: @@ -246,7 +248,7 @@ class CodeCommitProvider(GitProvider): return pr_id except: return "" - + def get_languages(self): """ Returns a dictionary of languages, containing the percentage of each language used in the PR. @@ -348,7 +350,7 @@ class CodeCommitProvider(GitProvider): """ Check if the provided hostname is a valid AWS CodeCommit hostname. - This is not an exhaustive check of AWS region names, + This is not an exhaustive check of AWS region names, but instead uses a regex to check for matching AWS region patterns. Args: diff --git a/pr_agent/git_providers/gerrit_provider.py b/pr_agent/git_providers/gerrit_provider.py index 8ec1be13..ba587656 100644 --- a/pr_agent/git_providers/gerrit_provider.py +++ b/pr_agent/git_providers/gerrit_provider.py @@ -12,9 +12,9 @@ import requests import urllib3.util from git import Repo +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.config_loader import get_settings from pr_agent.git_providers.git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.git_providers.local_git_provider import PullRequestMimic from pr_agent.log import get_logger diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index 265e54d9..bc081aa4 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -1,12 +1,12 @@ from abc import ABC, abstractmethod - # enum EDIT_TYPE (ADDED, DELETED, MODIFIED, RENAMED) from typing import Optional +from pr_agent.algo.types import FilePatchInfo from pr_agent.algo.utils import Range, process_description from pr_agent.config_loader import get_settings -from pr_agent.algo.types import FilePatchInfo from pr_agent.log import get_logger + MAX_FILES_ALLOWED_FULL = 50 class GitProvider(ABC): @@ -62,8 +62,8 @@ class GitProvider(ABC): pass def get_pr_description(self, full: bool = True, split_changes_walkthrough=False) -> str or tuple: - from pr_agent.config_loader import get_settings from pr_agent.algo.utils import clip_tokens + from pr_agent.config_loader import get_settings max_tokens_description = get_settings().get("CONFIG.MAX_DESCRIPTION_TOKENS", None) description = self.get_pr_description_full() if full else self.get_user_description() if split_changes_walkthrough: diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 61de7f26..4137ea48 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -1,10 +1,11 @@ +import hashlib import itertools import time -import hashlib import traceback from datetime import datetime from typing import Optional, Tuple from urllib.parse import urlparse + from github import AppAuthentication, Auth, Github from retry import retry from starlette_context import context @@ -12,11 +13,14 @@ from starlette_context import context from ..algo.file_filter import filter_ignored from ..algo.language_handler import is_valid_file from ..algo.types import EDIT_TYPE -from ..algo.utils import PRReviewHeader, load_large_diff, clip_tokens, find_line_number_of_relevant_line_in_file, Range +from ..algo.utils import (PRReviewHeader, Range, clip_tokens, + find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings from ..log import get_logger from ..servers.utils import RateLimitExceeded -from .git_provider import FilePatchInfo, GitProvider, IncrementalPR, MAX_FILES_ALLOWED_FULL +from .git_provider import (MAX_FILES_ALLOWED_FULL, FilePatchInfo, GitProvider, + IncrementalPR) class GithubProvider(GitProvider): diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index 443f4161..6a7b85c3 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -7,13 +7,16 @@ import gitlab import requests from gitlab import GitlabGetError +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo + from ..algo.file_filter import filter_ignored from ..algo.language_handler import is_valid_file -from ..algo.utils import load_large_diff, clip_tokens, find_line_number_of_relevant_line_in_file +from ..algo.utils import (clip_tokens, + find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings -from .git_provider import GitProvider, MAX_FILES_ALLOWED_FULL -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from ..log import get_logger +from .git_provider import MAX_FILES_ALLOWED_FULL, GitProvider class DiffNotFoundError(Exception): diff --git a/pr_agent/git_providers/local_git_provider.py b/pr_agent/git_providers/local_git_provider.py index c104224a..a03b8ec2 100644 --- a/pr_agent/git_providers/local_git_provider.py +++ b/pr_agent/git_providers/local_git_provider.py @@ -4,9 +4,9 @@ from typing import List from git import Repo +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.config_loader import _find_repository_root, get_settings from pr_agent.git_providers.git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.log import get_logger diff --git a/pr_agent/git_providers/utils.py b/pr_agent/git_providers/utils.py index 10beb1bb..1f780ae9 100644 --- a/pr_agent/git_providers/utils.py +++ b/pr_agent/git_providers/utils.py @@ -3,11 +3,12 @@ import os import tempfile from dynaconf import Dynaconf +from starlette_context import context from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context +from pr_agent.git_providers import (get_git_provider, + get_git_provider_with_context) from pr_agent.log import get_logger -from starlette_context import context def apply_repo_settings(pr_url): diff --git a/pr_agent/identity_providers/__init__.py b/pr_agent/identity_providers/__init__.py index 6df37ecb..aa617ef4 100644 --- a/pr_agent/identity_providers/__init__.py +++ b/pr_agent/identity_providers/__init__.py @@ -1,5 +1,6 @@ from pr_agent.config_loader import get_settings -from pr_agent.identity_providers.default_identity_provider import DefaultIdentityProvider +from pr_agent.identity_providers.default_identity_provider import \ + DefaultIdentityProvider _IDENTITY_PROVIDERS = { 'default': DefaultIdentityProvider @@ -10,4 +11,4 @@ def get_identity_provider(): identity_provider_id = get_settings().get("CONFIG.IDENTITY_PROVIDER", "default") if identity_provider_id not in _IDENTITY_PROVIDERS: raise ValueError(f"Unknown identity provider: {identity_provider_id}") - return _IDENTITY_PROVIDERS[identity_provider_id]() \ No newline at end of file + return _IDENTITY_PROVIDERS[identity_provider_id]() diff --git a/pr_agent/identity_providers/default_identity_provider.py b/pr_agent/identity_providers/default_identity_provider.py index c542e1c2..341f6cb9 100644 --- a/pr_agent/identity_providers/default_identity_provider.py +++ b/pr_agent/identity_providers/default_identity_provider.py @@ -1,4 +1,5 @@ -from pr_agent.identity_providers.identity_provider import Eligibility, IdentityProvider +from pr_agent.identity_providers.identity_provider import (Eligibility, + IdentityProvider) class DefaultIdentityProvider(IdentityProvider): diff --git a/pr_agent/secret_providers/__init__.py b/pr_agent/secret_providers/__init__.py index 020ed16c..c9faf480 100644 --- a/pr_agent/secret_providers/__init__.py +++ b/pr_agent/secret_providers/__init__.py @@ -8,12 +8,10 @@ def get_secret_provider(): provider_id = get_settings().config.secret_provider if provider_id == 'google_cloud_storage': try: - from pr_agent.secret_providers.google_cloud_storage_secret_provider import GoogleCloudStorageSecretProvider + from pr_agent.secret_providers.google_cloud_storage_secret_provider import \ + GoogleCloudStorageSecretProvider return GoogleCloudStorageSecretProvider() except Exception as e: raise ValueError(f"Failed to initialize google_cloud_storage secret provider {provider_id}") from e else: raise ValueError("Unknown SECRET_PROVIDER") - - - diff --git a/pr_agent/servers/azuredevops_server_webhook.py b/pr_agent/servers/azuredevops_server_webhook.py index 37446659..bcee3cdf 100644 --- a/pr_agent/servers/azuredevops_server_webhook.py +++ b/pr_agent/servers/azuredevops_server_webhook.py @@ -9,9 +9,9 @@ import secrets from urllib.parse import unquote import uvicorn -from fastapi import APIRouter, Depends, FastAPI, HTTPException -from fastapi.security import HTTPBasic, HTTPBasicCredentials +from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request from fastapi.encoders import jsonable_encoder +from fastapi.security import HTTPBasic, HTTPBasicCredentials from starlette import status from starlette.background import BackgroundTasks from starlette.middleware import Middleware @@ -23,9 +23,6 @@ from pr_agent.agent.pr_agent import PRAgent, command2class from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings from pr_agent.git_providers.utils import apply_repo_settings -from pr_agent.log import get_logger -from fastapi import Request, Depends -from fastapi.security import HTTPBasic, HTTPBasicCredentials from pr_agent.log import LoggingFormat, get_logger, setup_logger setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") diff --git a/pr_agent/servers/bitbucket_server_webhook.py b/pr_agent/servers/bitbucket_server_webhook.py index c9bfa5d9..69167c33 100644 --- a/pr_agent/servers/bitbucket_server_webhook.py +++ b/pr_agent/servers/bitbucket_server_webhook.py @@ -6,20 +6,20 @@ from typing import List import uvicorn from fastapi import APIRouter, FastAPI from fastapi.encoders import jsonable_encoder +from fastapi.responses import RedirectResponse from starlette import status from starlette.background import BackgroundTasks from starlette.middleware import Middleware from starlette.requests import Request from starlette.responses import JSONResponse from starlette_context.middleware import RawContextMiddleware + from pr_agent.agent.pr_agent import PRAgent from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings from pr_agent.git_providers.utils import apply_repo_settings from pr_agent.log import LoggingFormat, get_logger, setup_logger from pr_agent.servers.utils import verify_signature -from fastapi.responses import RedirectResponse - setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") router = APIRouter() diff --git a/pr_agent/servers/github_app.py b/pr_agent/servers/github_app.py index 728d72c1..d0ac8d5a 100644 --- a/pr_agent/servers/github_app.py +++ b/pr_agent/servers/github_app.py @@ -15,7 +15,8 @@ from starlette_context.middleware import RawContextMiddleware from pr_agent.agent.pr_agent import PRAgent from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings, global_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context +from pr_agent.git_providers import (get_git_provider, + get_git_provider_with_context) from pr_agent.git_providers.git_provider import IncrementalPR from pr_agent.git_providers.utils import apply_repo_settings from pr_agent.identity_providers import get_identity_provider diff --git a/pr_agent/servers/github_polling.py b/pr_agent/servers/github_polling.py index de1a9f52..5eab94dc 100644 --- a/pr_agent/servers/github_polling.py +++ b/pr_agent/servers/github_polling.py @@ -1,11 +1,12 @@ import asyncio import multiprocessing -from collections import deque -import traceback -from datetime import datetime, timezone import time -import requests +import traceback +from collections import deque +from datetime import datetime, timezone + import aiohttp +import requests from pr_agent.agent.pr_agent import PRAgent from pr_agent.config_loader import get_settings diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py index e3e80dfa..b5a50ebe 100644 --- a/pr_agent/servers/gitlab_webhook.py +++ b/pr_agent/servers/gitlab_webhook.py @@ -1,6 +1,6 @@ import copy -import re import json +import re from datetime import datetime import uvicorn diff --git a/pr_agent/servers/help.py b/pr_agent/servers/help.py index 5578fb0f..7edd13db 100644 --- a/pr_agent/servers/help.py +++ b/pr_agent/servers/help.py @@ -82,7 +82,7 @@ the tool will replace every marker of the form `pr_agent:marker_name` in the PR - `walkthrough`: the PR walkthrough. Note that when markers are enabled, if the original PR description does not contain any markers, the tool will not alter the description at all. - + """ output += "\n\n\n\n" @@ -101,7 +101,7 @@ Examples for custom labels: The list above is eclectic, and aims to give an idea of different possibilities. Define custom labels that are relevant for your repo and use cases. Note that Labels are not mutually exclusive, so you can add multiple label categories. -Make sure to provide proper title, and a detailed and well-phrased description for each label, so the tool will know when to suggest it. +Make sure to provide proper title, and a detailed and well-phrased description for each label, so the tool will know when to suggest it. """ output += "\n\n\n\n" @@ -126,7 +126,7 @@ Be specific, clear, and concise in the instructions. With extra instructions, yo Examples for extra instructions: ``` -[pr_description] +[pr_description] extra_instructions="""\ - The PR title should be in the format: ': ' - The title should be short and concise (up to 10 words) @@ -159,8 +159,8 @@ It can be invoked manually by commenting on any PR: /ask "..." ``` -Note that the tool does not have "memory" of previous questions, and answers each question independently. -You can ask questions about the entire PR, about specific code lines, or about an image related to the PR code changes. +Note that the tool does not have "memory" of previous questions, and answers each question independently. +You can ask questions about the entire PR, about specific code lines, or about an image related to the PR code changes. """ # output += "\n\n<table>" # @@ -195,9 +195,9 @@ You can ask questions about the entire PR, about specific code lines, or about a some_config1=... some_config2=... ``` - + """ output += f"\n\nSee the improve [usage page](https://pr-agent-docs.codium.ai/tools/improve/) for a comprehensive guide on using this tool.\n\n" - return output \ No newline at end of file + return output diff --git a/pr_agent/servers/serverless.py b/pr_agent/servers/serverless.py index c0bce606..a46eb80a 100644 --- a/pr_agent/servers/serverless.py +++ b/pr_agent/servers/serverless.py @@ -5,7 +5,6 @@ from starlette_context.middleware import RawContextMiddleware from pr_agent.servers.github_app import router - middleware = [Middleware(RawContextMiddleware)] app = FastAPI(middleware=middleware) app.include_router(router) diff --git a/pr_agent/servers/utils.py b/pr_agent/servers/utils.py index 12dd85ae..4b1ea80b 100644 --- a/pr_agent/servers/utils.py +++ b/pr_agent/servers/utils.py @@ -2,7 +2,7 @@ import hashlib import hmac import time from collections import defaultdict -from typing import Callable, Any +from typing import Any, Callable from fastapi import HTTPException diff --git a/pr_agent/settings/.secrets_template.toml b/pr_agent/settings/.secrets_template.toml index 6da82327..bb3ee459 100644 --- a/pr_agent/settings/.secrets_template.toml +++ b/pr_agent/settings/.secrets_template.toml @@ -87,7 +87,7 @@ org = "" pat = "" [azure_devops_server] -# For Azure devops Server basic auth - configured in the webhook creation +# For Azure devops Server basic auth - configured in the webhook creation # Optional, uncomment if you want to use Azure devops webhooks. Value assinged when you create the webhook # webhook_username = "<basic auth user>" # webhook_password = "<basic auth password>" diff --git a/pr_agent/settings/custom_labels.toml b/pr_agent/settings/custom_labels.toml index ee45fb19..34d604b5 100644 --- a/pr_agent/settings/custom_labels.toml +++ b/pr_agent/settings/custom_labels.toml @@ -13,4 +13,4 @@ enable_custom_labels=false #[custom_labels."Documentation"] #description = """Adds or modifies documentation""" #[custom_labels."Other"] -#description = """Other changes that do not fit in any of the above categories""" \ No newline at end of file +#description = """Other changes that do not fit in any of the above categories""" diff --git a/pr_agent/settings/language_extensions.toml b/pr_agent/settings/language_extensions.toml index 2f3e5542..0cc6c700 100644 --- a/pr_agent/settings/language_extensions.toml +++ b/pr_agent/settings/language_extensions.toml @@ -437,4 +437,4 @@ xBase = [".prg", ".prw", ] [docs_blacklist_extensions] # Disable docs for these extensions of text files and scripts that are not programming languages of function, classes and methods -docs_blacklist = ['sql', 'txt', 'yaml', 'json', 'xml', 'md', 'rst', 'rest', 'rest.txt', 'rst.txt', 'mdpolicy', 'mdown', 'markdown', 'mdwn', 'mkd', 'mkdn', 'mkdown', 'sh'] \ No newline at end of file +docs_blacklist = ['sql', 'txt', 'yaml', 'json', 'xml', 'md', 'rst', 'rest', 'rest.txt', 'rst.txt', 'mdpolicy', 'mdown', 'markdown', 'mdwn', 'mkd', 'mkdn', 'mkdown', 'sh'] diff --git a/pr_agent/settings/pr_code_suggestions_prompts.toml b/pr_agent/settings/pr_code_suggestions_prompts.toml index 5bf15f59..be47b3ce 100644 --- a/pr_agent/settings/pr_code_suggestions_prompts.toml +++ b/pr_agent/settings/pr_code_suggestions_prompts.toml @@ -118,4 +118,4 @@ The PR Diff: Response (should be a valid YAML, and nothing else): ```yaml -""" \ No newline at end of file +""" diff --git a/pr_agent/tools/pr_code_suggestions.py b/pr_agent/tools/pr_code_suggestions.py index 1426ff1a..ae3efbb2 100644 --- a/pr_agent/tools/pr_code_suggestions.py +++ b/pr_agent/tools/pr_code_suggestions.py @@ -1,25 +1,29 @@ import asyncio import copy +import difflib +import re import textwrap from functools import partial from typing import Dict, List + from jinja2 import Environment, StrictUndefined from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler -from pr_agent.algo.pr_processing import get_pr_diff, get_pr_multi_diffs, retry_with_fallback_models, \ - add_ai_metadata_to_diff_files +from pr_agent.algo.pr_processing import (add_ai_metadata_to_diff_files, + get_pr_diff, get_pr_multi_diffs, + retry_with_fallback_models) from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import load_yaml, replace_code_tags, ModelType, show_relevant_configurations +from pr_agent.algo.utils import (ModelType, load_yaml, replace_code_tags, + show_relevant_configurations) from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context, GithubProvider, GitLabProvider, \ - AzureDevopsProvider +from pr_agent.git_providers import (AzureDevopsProvider, GithubProvider, + GitLabProvider, get_git_provider, + get_git_provider_with_context) from pr_agent.git_providers.git_provider import get_main_pr_language from pr_agent.log import get_logger from pr_agent.servers.help import HelpMessage from pr_agent.tools.pr_description import insert_br_after_x_chars -import difflib -import re class PRCodeSuggestions: @@ -726,7 +730,7 @@ class PRCodeSuggestions: [{relevant_file} {range_str}]({code_snippet_link}) -{example_code.rstrip()} +{example_code.rstrip()} """ if get_settings().pr_code_suggestions.self_reflect_on_suggestions: pr_body += f"<details><summary>Suggestion importance[1-10]: {suggestion['score']}</summary>\n\n" @@ -778,4 +782,3 @@ class PRCodeSuggestions: get_logger().info(f"Could not reflect on suggestions, error: {e}") return "" return response_reflect - diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 1d397a54..2c3610d7 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -9,19 +9,24 @@ from jinja2 import Environment, StrictUndefined from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler 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, get_pr_diff_multiple_patchs, \ - OUTPUT_BUFFER_TOKENS_HARD_THRESHOLD +from pr_agent.algo.pr_processing import (OUTPUT_BUFFER_TOKENS_HARD_THRESHOLD, + get_pr_diff, + get_pr_diff_multiple_patchs, + retry_with_fallback_models) from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import set_custom_labels, PRDescriptionHeader -from pr_agent.algo.utils import load_yaml, get_user_labels, ModelType, show_relevant_configurations, get_max_tokens, \ - clip_tokens +from pr_agent.algo.utils import (ModelType, PRDescriptionHeader, clip_tokens, + get_max_tokens, get_user_labels, load_yaml, + set_custom_labels, + show_relevant_configurations) from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, GithubProvider, get_git_provider_with_context +from pr_agent.git_providers import (GithubProvider, get_git_provider, + get_git_provider_with_context) from pr_agent.git_providers.git_provider import get_main_pr_language from pr_agent.log import get_logger from pr_agent.servers.help import HelpMessage -from pr_agent.tools.ticket_pr_compliance_check import extract_ticket_links_from_pr_description, extract_tickets, \ - extract_and_cache_pr_tickets +from pr_agent.tools.ticket_pr_compliance_check import ( + extract_and_cache_pr_tickets, extract_ticket_links_from_pr_description, + extract_tickets) class PRDescription: @@ -297,7 +302,7 @@ class PRDescription: files_walkthrough = files_walkthrough.strip() + "\n" + extra_file_yaml.strip() if i >= MAX_EXTRA_FILES_TO_OUTPUT: files_walkthrough += f"""\ -extra_file_yaml = +extra_file_yaml = - filename: | Additional {len(remaining_files_list) - MAX_EXTRA_FILES_TO_OUTPUT} files not shown changes_summary: | @@ -611,7 +616,7 @@ extra_file_yaml = </td> <td><a href="{link}">{diff_plus_minus}</a>{delta_nbsp}</td> -</tr> +</tr> """ if use_collapsible_file_list: pr_body += """</table></details></td></tr>""" diff --git a/pr_agent/tools/pr_generate_labels.py b/pr_agent/tools/pr_generate_labels.py index 1911e0cd..dae25d91 100644 --- a/pr_agent/tools/pr_generate_labels.py +++ b/pr_agent/tools/pr_generate_labels.py @@ -9,7 +9,7 @@ from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler 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 load_yaml, set_custom_labels, get_user_labels +from pr_agent.algo.utils import get_user_labels, load_yaml, set_custom_labels 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 get_main_pr_language @@ -57,7 +57,7 @@ class PRGenerateLabels: get_settings().pr_custom_labels_prompt.system, get_settings().pr_custom_labels_prompt.user, ) - + # Initialize patches_diff and prediction attributes self.patches_diff = None self.prediction = None @@ -98,7 +98,7 @@ class PRGenerateLabels: self.git_provider.remove_initial_comment() except Exception as e: get_logger().error(f"Error generating PR labels {self.pr_id}: {e}") - + return "" async def _prepare_prediction(self, model: str) -> None: diff --git a/pr_agent/tools/pr_help_message.py b/pr_agent/tools/pr_help_message.py index 09845f81..3b0ed5a1 100644 --- a/pr_agent/tools/pr_help_message.py +++ b/pr_agent/tools/pr_help_message.py @@ -9,10 +9,10 @@ from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.pr_processing import retry_with_fallback_models from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import ModelType, load_yaml, clip_tokens +from pr_agent.algo.utils import ModelType, clip_tokens, load_yaml from pr_agent.config_loader import get_settings -from pr_agent.git_providers import GithubProvider, BitbucketServerProvider, \ - get_git_provider_with_context +from pr_agent.git_providers import (BitbucketServerProvider, GithubProvider, + get_git_provider_with_context) from pr_agent.log import get_logger diff --git a/pr_agent/tools/pr_line_questions.py b/pr_agent/tools/pr_line_questions.py index 56818e1c..50bf4183 100644 --- a/pr_agent/tools/pr_line_questions.py +++ b/pr_agent/tools/pr_line_questions.py @@ -6,8 +6,8 @@ from jinja2 import Environment, StrictUndefined from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler -from pr_agent.algo.git_patch_processing import convert_to_hunks_with_lines_numbers, \ - extract_hunk_lines_from_patch +from pr_agent.algo.git_patch_processing import ( + convert_to_hunks_with_lines_numbers, extract_hunk_lines_from_patch) 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 ModelType diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index f5f82e06..e008703e 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -4,19 +4,27 @@ import traceback from collections import OrderedDict from functools import partial from typing import List, Tuple + from jinja2 import Environment, StrictUndefined + from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler 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, add_ai_metadata_to_diff_files +from pr_agent.algo.pr_processing import (add_ai_metadata_to_diff_files, + get_pr_diff, + retry_with_fallback_models) from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import github_action_output, load_yaml, ModelType, \ - show_relevant_configurations, convert_to_markdown_v2, PRReviewHeader +from pr_agent.algo.utils import (ModelType, PRReviewHeader, + convert_to_markdown_v2, github_action_output, + load_yaml, show_relevant_configurations) from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context -from pr_agent.git_providers.git_provider import IncrementalPR, get_main_pr_language +from pr_agent.git_providers import (get_git_provider, + get_git_provider_with_context) +from pr_agent.git_providers.git_provider import (IncrementalPR, + get_main_pr_language) from pr_agent.log import get_logger from pr_agent.servers.help import HelpMessage -from pr_agent.tools.ticket_pr_compliance_check import extract_tickets, extract_and_cache_pr_tickets +from pr_agent.tools.ticket_pr_compliance_check import ( + extract_and_cache_pr_tickets, extract_tickets) class PRReviewer: diff --git a/pr_agent/tools/pr_similar_issue.py b/pr_agent/tools/pr_similar_issue.py index 1a4d794a..dfa34c52 100644 --- a/pr_agent/tools/pr_similar_issue.py +++ b/pr_agent/tools/pr_similar_issue.py @@ -34,9 +34,9 @@ class PRSimilarIssue: if get_settings().pr_similar_issue.vectordb == "pinecone": try: + import pandas as pd import pinecone from pinecone_datasets import Dataset, DatasetMetadata - import pandas as pd except: raise Exception("Please install 'pinecone' and 'pinecone_datasets' to use pinecone as vectordb") # assuming pinecone api key and environment are set in secrets file @@ -108,10 +108,10 @@ class PRSimilarIssue: self._update_index_with_issues(issues_to_update, repo_name_for_index, upsert=True) else: get_logger().info('No new issues to update') - + elif get_settings().pr_similar_issue.vectordb == "lancedb": try: - import lancedb # import lancedb only if needed + import lancedb # import lancedb only if needed except: raise Exception("Please install lancedb to use lancedb as vectordb") self.db = lancedb.connect(get_settings().lancedb.uri) @@ -173,7 +173,7 @@ class PRSimilarIssue: self._update_table_with_issues(issues_to_update, repo_name_for_index, ingest=True) else: get_logger().info('No new issues to update') - + async def run(self): get_logger().info('Getting issue...') @@ -190,14 +190,14 @@ class PRSimilarIssue: relevant_issues_number_list = [] relevant_comment_number_list = [] score_list = [] - + if get_settings().pr_similar_issue.vectordb == "pinecone": pinecone_index = pinecone.Index(index_name=self.index_name) res = pinecone_index.query(embeds[0], top_k=5, filter={"repo": self.repo_name_for_index}, include_metadata=True).to_dict() - + for r in res['matches']: # skip example issue if 'example_issue_' in r["id"]: @@ -222,12 +222,12 @@ class PRSimilarIssue: elif get_settings().pr_similar_issue.vectordb == "lancedb": res = self.table.search(embeds[0]).where(f"metadata.repo='{self.repo_name_for_index}'", prefilter=True).to_list() - + for r in res: # skip example issue if 'example_issue_' in r["id"]: continue - + try: issue_number = int(r["id"].split('.')[0].split('_')[-1]) except: @@ -238,14 +238,14 @@ class PRSimilarIssue: continue if issue_number not in relevant_issues_number_list: relevant_issues_number_list.append(issue_number) - + if 'comment' in r["id"]: relevant_comment_number_list.append(int(r["id"].split('.')[1].split('_')[-1])) else: relevant_comment_number_list.append(-1) score_list.append(str("{:.2f}".format(1-r['_distance']))) get_logger().info('Done') - + get_logger().info('Publishing response...') similar_issues_str = "### Similar Issues\n___\n\n" @@ -447,14 +447,14 @@ class PRSimilarIssue: if not ingest: get_logger().info('Creating table from scratch...') self.table = self.db.create_table(self.index_name, data=df, mode="overwrite") - time.sleep(15) + time.sleep(15) else: get_logger().info('Ingesting in Table...') if self.index_name not in self.db.table_names(): self.table.add(df) else: get_logger().info(f"Table {self.index_name} doesn't exists!") - time.sleep(5) + time.sleep(5) get_logger().info('Done') diff --git a/pr_agent/tools/pr_update_changelog.py b/pr_agent/tools/pr_update_changelog.py index dfe90a0d..52136430 100644 --- a/pr_agent/tools/pr_update_changelog.py +++ b/pr_agent/tools/pr_update_changelog.py @@ -3,14 +3,16 @@ from datetime import date from functools import partial from time import sleep from typing import Tuple + from jinja2 import Environment, StrictUndefined + from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler 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 ModelType, show_relevant_configurations from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, GithubProvider +from pr_agent.git_providers import GithubProvider, get_git_provider from pr_agent.git_providers.git_provider import get_main_pr_language from pr_agent.log import get_logger diff --git a/pyproject.toml b/pyproject.toml index 86ce9a32..cc426428 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,19 +6,19 @@ build-backend = "setuptools.build_meta" name = "pr-agent" version = "0.2.4" -authors = [{name= "CodiumAI", email = "tal.r@codium.ai"}] +authors = [{ name = "CodiumAI", email = "tal.r@codium.ai" }] maintainers = [ - {name = "Tal Ridnik", email = "tal.r@codium.ai"}, - {name = "Ori Kotek", email = "ori.k@codium.ai"}, - {name = "Hussam Lawen", email = "hussam.l@codium.ai"}, + { name = "Tal Ridnik", email = "tal.r@codium.ai" }, + { name = "Ori Kotek", email = "ori.k@codium.ai" }, + { name = "Hussam Lawen", email = "hussam.l@codium.ai" }, ] description = "CodiumAI PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedbacks and suggestions." readme = "README.md" requires-python = ">=3.10" keywords = ["AI", "Agents", "Pull Request", "Automation", "Code Review"] -license = {name = "Apache 2.0", file = "LICENSE"} +license = { name = "Apache 2.0", file = "LICENSE" } classifiers = [ "Intended Audience :: Developers", @@ -28,7 +28,7 @@ dynamic = ["dependencies"] [tool.setuptools.dynamic] -dependencies = {file = ["requirements.txt"]} +dependencies = { file = ["requirements.txt"] } [project.urls] "Homepage" = "https://github.com/Codium-ai/pr-agent" @@ -40,41 +40,43 @@ license-files = ["LICENSE"] [tool.setuptools.packages.find] where = ["."] -include = ["pr_agent*"] # include pr_agent and any sub-packages it finds under it. +include = [ + "pr_agent*", +] # include pr_agent and any sub-packages it finds under it. [project.scripts] pr-agent = "pr_agent.cli:run" - [tool.ruff] - line-length = 120 -select = [ - "E", # Pyflakes - "F", # Pyflakes - "B", # flake8-bugbear - "I001", # isort basic checks - "I002", # isort missing-required-import - ] +lint.select = [ + "E", # Pyflakes + "F", # Pyflakes + "B", # flake8-bugbear + "I001", # isort basic checks + "I002", # isort missing-required-import +] # First commit - only fixing isort -fixable = [ - "I001", # isort basic checks +lint.fixable = [ + "I001", # isort basic checks ] -unfixable = [ - "B", # Avoid trying to fix flake8-bugbear (`B`) violations. - ] - -exclude = [ - "api/code_completions", +lint.unfixable = [ + "B", # Avoid trying to fix flake8-bugbear (`B`) violations. ] -ignore = [ - "E999", "B008" -] +lint.exclude = ["api/code_completions"] -[tool.ruff.per-file-ignores] -"__init__.py" = ["E402"] # Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`. -# TODO: should decide if maybe not to ignore these. +lint.ignore = ["E999", "B008"] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = [ + "E402", +] # Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`. + +[tool.bandit] +exclude_dirs = ["tests"] +skips = ["B101"] +tests = [] diff --git a/tests/e2e_tests/e2e_utils.py b/tests/e2e_tests/e2e_utils.py index 5251d83e..b39e2a46 100644 --- a/tests/e2e_tests/e2e_utils.py +++ b/tests/e2e_tests/e2e_utils.py @@ -32,4 +32,3 @@ def main(): if __name__ == '__main__': main() """ - diff --git a/tests/e2e_tests/test_bitbucket_app.py b/tests/e2e_tests/test_bitbucket_app.py index 47b9ca4f..eb819eb2 100644 --- a/tests/e2e_tests/test_bitbucket_app.py +++ b/tests/e2e_tests/test_bitbucket_app.py @@ -5,16 +5,16 @@ import time from datetime import datetime import jwt -from atlassian.bitbucket import Cloud - import requests +from atlassian.bitbucket import Cloud from requests.auth import HTTPBasicAuth from pr_agent.config_loader import get_settings -from pr_agent.log import setup_logger, get_logger -from tests.e2e_tests.e2e_utils import NEW_FILE_CONTENT, FILE_PATH, PR_HEADER_START_WITH, REVIEW_START_WITH, \ - IMPROVE_START_WITH_REGEX_PATTERN, NUM_MINUTES - +from pr_agent.log import get_logger, setup_logger +from tests.e2e_tests.e2e_utils import (FILE_PATH, + IMPROVE_START_WITH_REGEX_PATTERN, + NEW_FILE_CONTENT, NUM_MINUTES, + PR_HEADER_START_WITH, REVIEW_START_WITH) log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/tests/e2e_tests/test_github_app.py b/tests/e2e_tests/test_github_app.py index 6ecb1da8..70b742a6 100644 --- a/tests/e2e_tests/test_github_app.py +++ b/tests/e2e_tests/test_github_app.py @@ -5,9 +5,11 @@ from datetime import datetime from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider -from pr_agent.log import setup_logger, get_logger -from tests.e2e_tests.e2e_utils import NEW_FILE_CONTENT, FILE_PATH, PR_HEADER_START_WITH, REVIEW_START_WITH, \ - IMPROVE_START_WITH_REGEX_PATTERN, NUM_MINUTES +from pr_agent.log import get_logger, setup_logger +from tests.e2e_tests.e2e_utils import (FILE_PATH, + IMPROVE_START_WITH_REGEX_PATTERN, + NEW_FILE_CONTENT, NUM_MINUTES, + PR_HEADER_START_WITH, REVIEW_START_WITH) log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/tests/e2e_tests/test_gitlab_webhook.py b/tests/e2e_tests/test_gitlab_webhook.py index 053bb0dc..835a6d12 100644 --- a/tests/e2e_tests/test_gitlab_webhook.py +++ b/tests/e2e_tests/test_gitlab_webhook.py @@ -7,9 +7,11 @@ import gitlab from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider -from pr_agent.log import setup_logger, get_logger -from tests.e2e_tests.e2e_utils import NEW_FILE_CONTENT, FILE_PATH, PR_HEADER_START_WITH, REVIEW_START_WITH, \ - IMPROVE_START_WITH_REGEX_PATTERN, NUM_MINUTES +from pr_agent.log import get_logger, setup_logger +from tests.e2e_tests.e2e_utils import (FILE_PATH, + IMPROVE_START_WITH_REGEX_PATTERN, + NEW_FILE_CONTENT, NUM_MINUTES, + PR_HEADER_START_WITH, REVIEW_START_WITH) log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/tests/unittest/test_azure_devops_parsing.py b/tests/unittest/test_azure_devops_parsing.py index 84c0ad08..441d4e35 100644 --- a/tests/unittest/test_azure_devops_parsing.py +++ b/tests/unittest/test_azure_devops_parsing.py @@ -12,4 +12,4 @@ class TestAzureDevOpsParsing(): pr_url = "https://organization.visualstudio.com/project/_git/repo/pullrequest/1" # workspace_slug, repo_slug, pr_number - assert AzureDevopsProvider._parse_pr_url(pr_url) == ("project", "repo", 1) \ No newline at end of file + assert AzureDevopsProvider._parse_pr_url(pr_url) == ("project", "repo", 1) diff --git a/tests/unittest/test_bitbucket_provider.py b/tests/unittest/test_bitbucket_provider.py index 1ea99931..5c672928 100644 --- a/tests/unittest/test_bitbucket_provider.py +++ b/tests/unittest/test_bitbucket_provider.py @@ -1,8 +1,10 @@ +from unittest.mock import MagicMock + +from atlassian.bitbucket import Bitbucket + +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.git_providers import BitbucketServerProvider from pr_agent.git_providers.bitbucket_provider import BitbucketProvider -from unittest.mock import MagicMock -from atlassian.bitbucket import Bitbucket -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo class TestBitbucketProvider: @@ -121,7 +123,7 @@ class TestBitbucketServerProvider: NOT between the HEAD of main and the HEAD of branch b - o - o - o branch b - / / + / / o - o -- o - o main ^ node c ''' @@ -183,7 +185,7 @@ class TestBitbucketServerProvider: ---- o - o branch c / / ---- o branch b - / / + / / o - o - o main ^ node d ''' @@ -294,4 +296,4 @@ class TestBitbucketServerProvider: actual = provider.get_diff_files() - assert actual == expected \ No newline at end of file + assert actual == expected diff --git a/tests/unittest/test_codecommit_client.py b/tests/unittest/test_codecommit_client.py index a81e4b32..f5d89c6c 100644 --- a/tests/unittest/test_codecommit_client.py +++ b/tests/unittest/test_codecommit_client.py @@ -1,4 +1,5 @@ from unittest.mock import MagicMock + from pr_agent.git_providers.codecommit_client import CodeCommitClient diff --git a/tests/unittest/test_codecommit_provider.py b/tests/unittest/test_codecommit_provider.py index 56312d73..d080b50f 100644 --- a/tests/unittest/test_codecommit_provider.py +++ b/tests/unittest/test_codecommit_provider.py @@ -1,9 +1,11 @@ -import pytest from unittest.mock import patch -from pr_agent.git_providers.codecommit_provider import CodeCommitFile -from pr_agent.git_providers.codecommit_provider import CodeCommitProvider -from pr_agent.git_providers.codecommit_provider import PullRequestCCMimic + +import pytest + from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.git_providers.codecommit_provider import (CodeCommitFile, + CodeCommitProvider, + PullRequestCCMimic) class TestCodeCommitFile: diff --git a/tests/unittest/test_convert_to_markdown.py b/tests/unittest/test_convert_to_markdown.py index 8b82677a..4d1d1aa4 100644 --- a/tests/unittest/test_convert_to_markdown.py +++ b/tests/unittest/test_convert_to_markdown.py @@ -6,8 +6,8 @@ from pr_agent.tools.pr_description import insert_br_after_x_chars Code Analysis Objective: -The objective of the 'convert_to_markdown' function is to convert a dictionary of data into a markdown-formatted text. -The function takes in a dictionary as input and recursively iterates through its keys and values to generate the +The objective of the 'convert_to_markdown' function is to convert a dictionary of data into a markdown-formatted text. +The function takes in a dictionary as input and recursively iterates through its keys and values to generate the markdown text. Inputs: @@ -18,17 +18,17 @@ Flow: - Create a dictionary 'emojis' containing emojis for each key in the input dictionary. - Iterate through the input dictionary: - If the value is empty, continue to the next iteration. - - If the value is a dictionary, recursively call the 'convert_to_markdown' function with the value as input and + - If the value is a dictionary, recursively call the 'convert_to_markdown' function with the value as input and append the returned markdown text to 'markdown_text'. - If the value is a list: - If the key is 'code suggestions', add an additional line break to 'markdown_text'. - Get the corresponding emoji for the key from the 'emojis' dictionary. If no emoji is found, use a dash. - Append the emoji and key to 'markdown_text'. - Iterate through the items in the list: - - If the item is a dictionary and the key is 'code suggestions', call the 'parse_code_suggestion' function with + - If the item is a dictionary and the key is 'code suggestions', call the 'parse_code_suggestion' function with the item as input and append the returned markdown text to 'markdown_text'. - If the item is not empty, append it to 'markdown_text'. - - If the value is not 'n/a', get the corresponding emoji for the key from the 'emojis' dictionary. If no emoji is + - If the value is not 'n/a', get the corresponding emoji for the key from the 'emojis' dictionary. If no emoji is found, use a dash. Append the emoji, key, and value to 'markdown_text'. - Return 'markdown_text'. diff --git a/tests/unittest/test_delete_hunks.py b/tests/unittest/test_delete_hunks.py index 20b9a676..78ecc947 100644 --- a/tests/unittest/test_delete_hunks.py +++ b/tests/unittest/test_delete_hunks.py @@ -6,7 +6,7 @@ from pr_agent.algo.git_patch_processing import omit_deletion_hunks Code Analysis Objective: -The objective of the "omit_deletion_hunks" function is to remove deletion hunks from a patch file and return only the +The objective of the "omit_deletion_hunks" function is to remove deletion hunks from a patch file and return only the added lines. Inputs: @@ -16,11 +16,11 @@ Flow: - Initialize empty lists "temp_hunk" and "added_patched", and boolean variables "add_hunk" and "inside_hunk". - Compile a regular expression pattern to match hunk headers. - Iterate through each line in "patch_lines". -- If the line starts with "@@", match the line with the hunk header pattern, finish the previous hunk if necessary, +- If the line starts with "@@", match the line with the hunk header pattern, finish the previous hunk if necessary, and append the line to "temp_hunk". -- If the line does not start with "@@", append the line to "temp_hunk", check if it is an added line, and set +- If the line does not start with "@@", append the line to "temp_hunk", check if it is an added line, and set "add_hunk" to True if it is. -- If the function reaches the end of "patch_lines" and there is an unfinished hunk with added lines, append it to +- If the function reaches the end of "patch_lines" and there is an unfinished hunk with added lines, append it to "added_patched". - Join the lines in "added_patched" with newline characters and return the resulting string. diff --git a/tests/unittest/test_extend_patch.py b/tests/unittest/test_extend_patch.py index 2d8913f3..6689186c 100644 --- a/tests/unittest/test_extend_patch.py +++ b/tests/unittest/test_extend_patch.py @@ -1,4 +1,5 @@ import pytest + from pr_agent.algo.git_patch_processing import extend_patch from pr_agent.algo.pr_processing import pr_generate_extended_diff from pr_agent.algo.token_handler import TokenHandler diff --git a/tests/unittest/test_file_filter.py b/tests/unittest/test_file_filter.py index 43e9c9b4..b35e351f 100644 --- a/tests/unittest/test_file_filter.py +++ b/tests/unittest/test_file_filter.py @@ -1,7 +1,9 @@ import pytest + from pr_agent.algo.file_filter import filter_ignored from pr_agent.config_loader import global_settings + class TestIgnoreFilter: def test_no_ignores(self): """ diff --git a/tests/unittest/test_find_line_number_of_relevant_line_in_file.py b/tests/unittest/test_find_line_number_of_relevant_line_in_file.py index fcb028ca..07be17f4 100644 --- a/tests/unittest/test_find_line_number_of_relevant_line_in_file.py +++ b/tests/unittest/test_find_line_number_of_relevant_line_in_file.py @@ -1,9 +1,10 @@ # Generated by CodiumAI +import pytest + from pr_agent.algo.types import FilePatchInfo from pr_agent.algo.utils import find_line_number_of_relevant_line_in_file -import pytest class TestFindLineNumberOfRelevantLineInFile: # Tests that the function returns the correct line number and absolute position when the relevant line is found in the patch @@ -64,4 +65,4 @@ class TestFindLineNumberOfRelevantLineInFile: relevant_file = 'file1' relevant_line_in_file = 'relevant_line' expected = (-1, -1) - assert find_line_number_of_relevant_line_in_file(diff_files, relevant_file, relevant_line_in_file) == expected \ No newline at end of file + assert find_line_number_of_relevant_line_in_file(diff_files, relevant_file, relevant_line_in_file) == expected diff --git a/tests/unittest/test_github_action_output.py b/tests/unittest/test_github_action_output.py index 2b8e0db1..57a62c6e 100644 --- a/tests/unittest/test_github_action_output.py +++ b/tests/unittest/test_github_action_output.py @@ -1,33 +1,35 @@ -import os import json +import os + 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): @@ -35,16 +37,16 @@ class TestGitHubOutput: 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')) \ No newline at end of file + + assert not os.path.exists(str(tmp_path / 'output')) diff --git a/tests/unittest/test_handle_patch_deletions.py b/tests/unittest/test_handle_patch_deletions.py index e44c0d77..c216f189 100644 --- a/tests/unittest/test_handle_patch_deletions.py +++ b/tests/unittest/test_handle_patch_deletions.py @@ -8,7 +8,7 @@ from pr_agent.config_loader import get_settings Code Analysis Objective: -The objective of the function is to handle entire file or deletion patches and return the patch after omitting the +The objective of the function is to handle entire file or deletion patches and return the patch after omitting the deletion hunks. Inputs: diff --git a/tests/unittest/test_language_handler.py b/tests/unittest/test_language_handler.py index fdde7bb0..f76a15ea 100644 --- a/tests/unittest/test_language_handler.py +++ b/tests/unittest/test_language_handler.py @@ -7,8 +7,8 @@ from pr_agent.algo.language_handler import sort_files_by_main_languages Code Analysis Objective: -The objective of the function is to sort a list of files by their main language, putting the files that are in the main -language first and the rest of the files after. It takes in a dictionary of languages and their sizes, and a list of +The objective of the function is to sort a list of files by their main language, putting the files that are in the main +language first and the rest of the files after. It takes in a dictionary of languages and their sizes, and a list of files. Inputs: diff --git a/tests/unittest/test_load_yaml.py b/tests/unittest/test_load_yaml.py index 17d46936..5be0b1a2 100644 --- a/tests/unittest/test_load_yaml.py +++ b/tests/unittest/test_load_yaml.py @@ -47,7 +47,3 @@ PR Feedback: expected_output = [{'relevant file': 'src/app.py:\n', 'suggestion content': 'The print statement is outside inside the if __name__ ==:'}] assert load_yaml(yaml_str) == expected_output - - - - diff --git a/tests/unittest/test_parse_code_suggestion.py b/tests/unittest/test_parse_code_suggestion.py index 5ffd9f3e..c959a2dc 100644 --- a/tests/unittest/test_parse_code_suggestion.py +++ b/tests/unittest/test_parse_code_suggestion.py @@ -6,8 +6,8 @@ from pr_agent.algo.utils import parse_code_suggestion Code Analysis Objective: -The objective of the function is to convert a dictionary into a markdown format. The function takes in a dictionary as -input and recursively converts it into a markdown format. The function is specifically designed to handle dictionaries +The objective of the function is to convert a dictionary into a markdown format. The function takes in a dictionary as +input and recursively converts it into a markdown format. The function is specifically designed to handle dictionaries that contain code suggestions. Inputs: diff --git a/tests/unittest/test_try_fix_yaml.py b/tests/unittest/test_try_fix_yaml.py index 90fa63f1..336c4af5 100644 --- a/tests/unittest/test_try_fix_yaml.py +++ b/tests/unittest/test_try_fix_yaml.py @@ -1,10 +1,10 @@ # Generated by CodiumAI +import pytest + from pr_agent.algo.utils import try_fix_yaml -import pytest - class TestTryFixYaml: # The function successfully parses a valid YAML string. @@ -54,7 +54,7 @@ code_suggestions: src/index.ts label: | best practice - + - relevant_file: | src/index2.ts label: | @@ -87,4 +87,4 @@ code_suggestions: We can further improve the code by using the `const` keyword instead of `var` in the `src/index.ts` file. ''' expected_output = {'code_suggestions': [{'relevant_file': 'src/index.ts\n', 'label': 'best practice\n'}, {'relevant_file': 'src/index2.ts\n', 'label': 'enhancment'}]} - assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='label') == expected_output \ No newline at end of file + assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='label') == expected_output
extra_instructions