ai-cr 3.1.0__tar.gz → 3.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ai_cr-3.1.0 → ai_cr-3.1.2}/PKG-INFO +1 -1
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/cli.py +8 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/deploy.py +46 -12
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/gh_react_to_comment.py +26 -1
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/core.py +62 -7
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/gh_api.py +31 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/tpl/github_workflows/components/env-vars.j2 +1 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/tpl/github_workflows/gito-code-review.yml.j2 +2 -2
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/tpl/github_workflows/gito-react-to-comments.yml.j2 +1 -1
- ai_cr-3.1.2/gito/tpl/questions/changes_summary.j2 +55 -0
- ai_cr-3.1.2/gito/tpl/questions/testing_guide.j2 +23 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/pyproject.toml +1 -1
- {ai_cr-3.1.0 → ai_cr-3.1.2}/LICENSE +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/README.md +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/__init__.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/__main__.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/bootstrap.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/cli_base.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/__init__.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/fix.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/gh_post_review_comment.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/linear_comment.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/repl.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/commands/version.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/config.toml +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/constants.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/context.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/env.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/issue_trackers.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/pipeline.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/pipeline_steps/__init__.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/pipeline_steps/jira.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/pipeline_steps/linear.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/project_config.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/report_struct.py +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/tpl/github_workflows/components/installs.j2 +0 -0
- {ai_cr-3.1.0/gito/tpl → ai_cr-3.1.2/gito/tpl/questions}/release_notes.j2 +0 -0
- {ai_cr-3.1.0 → ai_cr-3.1.2}/gito/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: ai-cr
|
3
|
-
Version: 3.1.
|
3
|
+
Version: 3.1.2
|
4
4
|
Summary: AI code review tool that works with any language model provider. It detects issues in GitHub pull requests or local changes—instantly, reliably, and without vendor lock-in.
|
5
5
|
License: MIT
|
6
6
|
Keywords: static code analysis,code review,code quality,ai,coding,assistant,llm,github,automation,devops,developer tools,github actions,workflows,git
|
@@ -92,6 +92,7 @@ def cmd_review(
|
|
92
92
|
out: str = arg_out()
|
93
93
|
):
|
94
94
|
_what, _against = args_to_target(refs, what, against)
|
95
|
+
pr = pr or os.getenv("PR_NUMBER_FROM_WORKFLOW_DISPATCH")
|
95
96
|
with get_repo_context(url, _what) as (repo, out_folder):
|
96
97
|
asyncio.run(review(
|
97
98
|
repo=repo,
|
@@ -100,6 +101,7 @@ def cmd_review(
|
|
100
101
|
filters=filters,
|
101
102
|
use_merge_base=merge_base,
|
102
103
|
out_folder=out or out_folder,
|
104
|
+
pr=pr,
|
103
105
|
))
|
104
106
|
if post_comment:
|
105
107
|
try:
|
@@ -134,8 +136,13 @@ def cmd_answer(
|
|
134
136
|
default=None,
|
135
137
|
show_default=False
|
136
138
|
),
|
139
|
+
pr: int = typer.Option(
|
140
|
+
default=None,
|
141
|
+
help="GitHub Pull Request number"
|
142
|
+
),
|
137
143
|
):
|
138
144
|
_what, _against = args_to_target(refs, what, against)
|
145
|
+
pr = pr or os.getenv("PR_NUMBER_FROM_WORKFLOW_DISPATCH")
|
139
146
|
if str(question).startswith("tpl:"):
|
140
147
|
prompt_file = str(question)[4:]
|
141
148
|
question = ""
|
@@ -149,6 +156,7 @@ def cmd_answer(
|
|
149
156
|
use_merge_base=merge_base,
|
150
157
|
prompt_file=prompt_file,
|
151
158
|
use_pipeline=use_pipeline,
|
159
|
+
pr=pr,
|
152
160
|
)
|
153
161
|
if post_to == 'linear':
|
154
162
|
logging.info("Posting answer to Linear...")
|
@@ -1,16 +1,31 @@
|
|
1
|
+
import logging
|
1
2
|
from pathlib import Path
|
2
3
|
|
3
4
|
import microcore as mc
|
4
5
|
from microcore import ApiType, ui, utils
|
5
|
-
from git import Repo
|
6
|
+
from git import Repo, GitCommandError
|
7
|
+
import typer
|
6
8
|
|
9
|
+
from ..core import get_base_branch
|
7
10
|
from ..utils import version, extract_gh_owner_repo
|
8
11
|
from ..cli_base import app
|
12
|
+
from ..gh_api import gh_api
|
9
13
|
|
10
14
|
|
11
15
|
@app.command(name="deploy", help="Deploy Gito workflows to GitHub Actions")
|
12
16
|
@app.command(name="init", hidden=True)
|
13
|
-
def deploy(
|
17
|
+
def deploy(
|
18
|
+
api_type: ApiType = None,
|
19
|
+
commit: bool = None,
|
20
|
+
rewrite: bool = False,
|
21
|
+
to_branch: str = typer.Option(
|
22
|
+
default="gito_deploy",
|
23
|
+
help="Branch name for new PR containing with Gito workflows commit"
|
24
|
+
),
|
25
|
+
token: str = typer.Option(
|
26
|
+
"", help="GitHub token (or set GITHUB_TOKEN env var)"
|
27
|
+
),
|
28
|
+
):
|
14
29
|
repo = Repo(".")
|
15
30
|
workflow_files = dict(
|
16
31
|
code_review=Path(".github/workflows/gito-code-review.yml"),
|
@@ -77,16 +92,35 @@ def deploy(api_type: ApiType = None, commit: bool = None, rewrite: bool = False)
|
|
77
92
|
"Do you want to commit and push created GitHub workflows to a new branch?"
|
78
93
|
):
|
79
94
|
repo.git.add([str(file) for file in workflow_files.values()])
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
95
|
+
if not repo.active_branch.name.startswith(to_branch):
|
96
|
+
repo.git.checkout("-b", to_branch)
|
97
|
+
try:
|
98
|
+
repo.git.commit("-m", "Deploy Gito workflows")
|
99
|
+
except GitCommandError as e:
|
100
|
+
if "nothing added" in str(e):
|
101
|
+
ui.warning("Failed to commit changes: nothing was added")
|
102
|
+
else:
|
103
|
+
ui.error(f"Failed to commit changes: {e}")
|
104
|
+
return False
|
105
|
+
|
106
|
+
repo.git.push("origin", to_branch)
|
107
|
+
print(f"Changes pushed to {to_branch} branch.")
|
108
|
+
try:
|
109
|
+
api = gh_api(repo=repo)
|
110
|
+
base = get_base_branch(repo).split('/')[-1]
|
111
|
+
logging.info(f"Creating PR {ui.green(to_branch)} -> {ui.yellow(base)}...")
|
112
|
+
res = api.pulls.create(
|
113
|
+
head=to_branch,
|
114
|
+
base=base,
|
115
|
+
title="Deploy Gito workflows",
|
116
|
+
)
|
117
|
+
print(f"Pull request #{res.number} created successfully:\n{res.html_url}")
|
118
|
+
except Exception as e:
|
119
|
+
mc.ui.error(f"Failed to create pull request automatically: {e}")
|
120
|
+
print(
|
121
|
+
f"Please create a PR from '{to_branch}' to your main branch and merge it:\n"
|
122
|
+
f"https://github.com/{owner}/{repo_name}/compare/{to_branch}?expand=1"
|
123
|
+
)
|
90
124
|
else:
|
91
125
|
print(
|
92
126
|
"Now you can commit and push created GitHub workflows to your main repository branch.\n"
|
@@ -25,6 +25,30 @@ from ..utils import extract_gh_owner_repo
|
|
25
25
|
from .fix import fix
|
26
26
|
|
27
27
|
|
28
|
+
def cleanup_comment_addressed_to_gito(text):
|
29
|
+
if not text:
|
30
|
+
return text
|
31
|
+
patterns = [
|
32
|
+
r'^\s*gito\b',
|
33
|
+
r'^\s*ai\b',
|
34
|
+
r'^\s*bot\b',
|
35
|
+
r'^\s*@gito\b',
|
36
|
+
r'^\s*@ai\b',
|
37
|
+
r'^\s*@bot\b'
|
38
|
+
]
|
39
|
+
result = text
|
40
|
+
# Remove each pattern from the beginning
|
41
|
+
for pattern in patterns:
|
42
|
+
result = re.sub(pattern, '', result, flags=re.IGNORECASE)
|
43
|
+
|
44
|
+
# Remove leading comma and spaces that may be left after prefix removal
|
45
|
+
result = re.sub(r'^\s*,\s*', '', result)
|
46
|
+
|
47
|
+
# Clean up extra whitespace
|
48
|
+
result = re.sub(r'\s+', ' ', result).strip()
|
49
|
+
return result
|
50
|
+
|
51
|
+
|
28
52
|
@app.command(hidden=True)
|
29
53
|
def react_to_comment(
|
30
54
|
comment_id: int = typer.Argument(),
|
@@ -99,7 +123,8 @@ def react_to_comment(
|
|
99
123
|
)
|
100
124
|
else:
|
101
125
|
if cfg.answer_github_comments:
|
102
|
-
|
126
|
+
question = cleanup_comment_addressed_to_gito(comment.body)
|
127
|
+
response = answer(question, repo=repo, pr=pr)
|
103
128
|
post_gh_comment(
|
104
129
|
gh_repository=f"{owner}/{repo_name}",
|
105
130
|
pr_or_issue_number=pr,
|
@@ -1,11 +1,12 @@
|
|
1
|
+
import os
|
1
2
|
import fnmatch
|
2
3
|
import logging
|
3
|
-
from os import PathLike
|
4
4
|
from typing import Iterable
|
5
5
|
from pathlib import Path
|
6
6
|
from functools import partial
|
7
7
|
|
8
8
|
import microcore as mc
|
9
|
+
from gito.gh_api import gh_api
|
9
10
|
from microcore import ui
|
10
11
|
from git import Repo, Commit
|
11
12
|
from git.exc import GitCommandError
|
@@ -66,16 +67,57 @@ def commit_in_branch(repo: Repo, commit: Commit, target_branch: str) -> bool:
|
|
66
67
|
return False
|
67
68
|
|
68
69
|
|
70
|
+
def get_base_branch(repo: Repo, pr: int | str = None):
|
71
|
+
if os.getenv('GITHUB_ACTIONS'):
|
72
|
+
|
73
|
+
# triggered from PR
|
74
|
+
if base_ref := os.getenv('GITHUB_BASE_REF'):
|
75
|
+
logging.info(f"Using GITHUB_BASE_REF:{base_ref} as base branch")
|
76
|
+
return f'origin/{base_ref}'
|
77
|
+
logging.info("GITHUB_BASE_REF is not available...")
|
78
|
+
if pr:
|
79
|
+
api = gh_api(repo=repo)
|
80
|
+
pr_obj = api.pulls.get(pr)
|
81
|
+
logging.info(
|
82
|
+
f"Using 'origin/{pr_obj.base.ref}' as base branch "
|
83
|
+
f"(received via GH API for PR#{pr})"
|
84
|
+
)
|
85
|
+
return f'origin/{pr_obj.base.ref}'
|
86
|
+
|
87
|
+
try:
|
88
|
+
logging.info(
|
89
|
+
"Trying to resolve base branch from repo.remotes.origin.refs.HEAD.reference.name..."
|
90
|
+
)
|
91
|
+
# 'origin/main', 'origin/master', etc
|
92
|
+
# Stopped working in github actions since 07/2025
|
93
|
+
return repo.remotes.origin.refs.HEAD.reference.name
|
94
|
+
except AttributeError:
|
95
|
+
try:
|
96
|
+
logging.info(
|
97
|
+
"Checking if repo has 'main' or 'master' branchs to use as --against branch..."
|
98
|
+
)
|
99
|
+
remote_refs = repo.remotes.origin.refs
|
100
|
+
for branch_name in ['main', 'master']:
|
101
|
+
if hasattr(remote_refs, branch_name):
|
102
|
+
return f'origin/{branch_name}'
|
103
|
+
except Exception:
|
104
|
+
pass
|
105
|
+
|
106
|
+
logging.error("Could not determine default branch from remote refs.")
|
107
|
+
raise ValueError("No default branch found in the repository.")
|
108
|
+
|
109
|
+
|
69
110
|
def get_diff(
|
70
111
|
repo: Repo = None,
|
71
112
|
what: str = None,
|
72
113
|
against: str = None,
|
73
114
|
use_merge_base: bool = True,
|
115
|
+
pr: str | int = None
|
74
116
|
) -> PatchSet | list[PatchedFile]:
|
75
117
|
repo = repo or Repo(".")
|
76
118
|
if not against:
|
77
119
|
# 'origin/main', 'origin/master', etc
|
78
|
-
against = repo
|
120
|
+
against = get_base_branch(repo, pr=pr)
|
79
121
|
if review_subject_is_index(what):
|
80
122
|
what = None # working copy
|
81
123
|
if use_merge_base:
|
@@ -175,7 +217,7 @@ def get_diff(
|
|
175
217
|
)
|
176
218
|
if file_path == DEV_NULL:
|
177
219
|
continue
|
178
|
-
if is_binary_file(repo, file_path.
|
220
|
+
if is_binary_file(repo, file_path.removeprefix("b/")):
|
179
221
|
logging.info(f"Skipping binary file: {patched_file.path}")
|
180
222
|
continue
|
181
223
|
non_binary_diff.append(patched_file)
|
@@ -251,11 +293,12 @@ def _prepare(
|
|
251
293
|
against: str = None,
|
252
294
|
filters: str | list[str] = "",
|
253
295
|
use_merge_base: bool = True,
|
296
|
+
pr: str | int = None,
|
254
297
|
):
|
255
298
|
repo = repo or Repo(".")
|
256
299
|
cfg = ProjectConfig.load_for_repo(repo)
|
257
300
|
diff = get_diff(
|
258
|
-
repo=repo, what=what, against=against, use_merge_base=use_merge_base
|
301
|
+
repo=repo, what=what, against=against, use_merge_base=use_merge_base, pr=pr,
|
259
302
|
)
|
260
303
|
diff = filter_diff(diff, filters)
|
261
304
|
if not diff:
|
@@ -318,11 +361,17 @@ async def review(
|
|
318
361
|
against: str = None,
|
319
362
|
filters: str | list[str] = "",
|
320
363
|
use_merge_base: bool = True,
|
321
|
-
out_folder: str | PathLike | None = None,
|
364
|
+
out_folder: str | os.PathLike | None = None,
|
365
|
+
pr: str | int = None
|
322
366
|
):
|
323
367
|
try:
|
324
368
|
repo, cfg, diff, lines = _prepare(
|
325
|
-
repo=repo,
|
369
|
+
repo=repo,
|
370
|
+
what=what,
|
371
|
+
against=against,
|
372
|
+
filters=filters,
|
373
|
+
use_merge_base=use_merge_base,
|
374
|
+
pr=pr,
|
326
375
|
)
|
327
376
|
except NoChangesInContextError:
|
328
377
|
logging.error("No changes to review")
|
@@ -378,10 +427,16 @@ def answer(
|
|
378
427
|
use_merge_base: bool = True,
|
379
428
|
use_pipeline: bool = True,
|
380
429
|
prompt_file: str = None,
|
430
|
+
pr: str | int = None,
|
381
431
|
) -> str | None:
|
382
432
|
try:
|
383
433
|
repo, config, diff, lines = _prepare(
|
384
|
-
repo=repo,
|
434
|
+
repo=repo,
|
435
|
+
what=what,
|
436
|
+
against=against,
|
437
|
+
filters=filters,
|
438
|
+
use_merge_base=use_merge_base,
|
439
|
+
pr=pr
|
385
440
|
)
|
386
441
|
except NoChangesInContextError:
|
387
442
|
logging.error("No changes to review")
|
@@ -2,7 +2,38 @@ import os
|
|
2
2
|
import logging
|
3
3
|
|
4
4
|
import requests
|
5
|
+
import git
|
5
6
|
from fastcore.basics import AttrDict # objects returned by ghapi
|
7
|
+
from ghapi.core import GhApi
|
8
|
+
|
9
|
+
from .project_config import ProjectConfig
|
10
|
+
from .utils import extract_gh_owner_repo
|
11
|
+
|
12
|
+
|
13
|
+
def gh_api(
|
14
|
+
repo: git.Repo = None, # used to resolve owner/repo
|
15
|
+
config: ProjectConfig | None = None, # used to resolve owner/repo
|
16
|
+
token: str | None = None
|
17
|
+
) -> GhApi:
|
18
|
+
if repo:
|
19
|
+
# resolve owner/repo from repo.remotes.origin.url
|
20
|
+
owner, repo_name = extract_gh_owner_repo(repo)
|
21
|
+
else:
|
22
|
+
if not config:
|
23
|
+
config = ProjectConfig.load()
|
24
|
+
# resolve owner/repo from github env vars (github actions)
|
25
|
+
gh_env = config.prompt_vars.get("github_env", {})
|
26
|
+
gh_repo = gh_env.get("github_repo")
|
27
|
+
if not gh_repo:
|
28
|
+
raise ValueError("GitHub repository not specified and not found in project config.")
|
29
|
+
parts = gh_repo.split('/')
|
30
|
+
if len(parts) != 2:
|
31
|
+
raise ValueError(f"Invalid GitHub repository format: {gh_repo}. Expected 'owner/repo'.")
|
32
|
+
owner, repo_name = parts
|
33
|
+
|
34
|
+
token = resolve_gh_token(token)
|
35
|
+
api = GhApi(owner, repo_name, token=token)
|
36
|
+
return api
|
6
37
|
|
7
38
|
|
8
39
|
def resolve_gh_token(token_or_none: str | None = None) -> str | None:
|
@@ -22,8 +22,8 @@ jobs:
|
|
22
22
|
{%- include("github_workflows/components/env-vars.j2") %}
|
23
23
|
PR_NUMBER_FROM_WORKFLOW_DISPATCH: {% raw %}${{ github.event.inputs.pr_number }}{% endraw %}
|
24
24
|
run: |{% raw %}
|
25
|
-
gito --verbose review
|
26
|
-
gito github-comment
|
25
|
+
gito --verbose review
|
26
|
+
gito github-comment{% endraw %}
|
27
27
|
|
28
28
|
- uses: actions/upload-artifact@v4
|
29
29
|
with:
|
@@ -67,4 +67,4 @@ jobs:
|
|
67
67
|
# Otherwise, use LLM_API_TYPE: none
|
68
68
|
{%- include("github_workflows/components/env-vars.j2") %}
|
69
69
|
run: |
|
70
|
-
{% raw %}gito react-to-comment ${{ github.event.comment.id }}
|
70
|
+
{% raw %}gito react-to-comment ${{ github.event.comment.id }}{%- endraw %}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
{{ self_id }}
|
2
|
+
----TASK----
|
3
|
+
|
4
|
+
## Subtask 1:
|
5
|
+
Write a codebase changes summary clearly describing and explaining it for the engineering managers.
|
6
|
+
- It is intended to be posted into bug tracker for estimating work done in the pull request.
|
7
|
+
- Summary should be in a form of compact changelist where each change is described by one sentence.
|
8
|
+
- Caption should be: ## PR Summary: <3-10 words>
|
9
|
+
- Each change summary BP list item should start from effort estimation icon:
|
10
|
+
- - ◆◇◇ (up to 2 hours)
|
11
|
+
- - ◆◆◇ (half day)
|
12
|
+
- - ◆◆◆ (1-2 days and more)
|
13
|
+
|
14
|
+
Also include this estimation legend below as "Pure Codebase Work Estimation Legend".
|
15
|
+
|
16
|
+
|
17
|
+
## Subtask 1 (Issue alignment sentence)
|
18
|
+
Include one sentence about how the code changes address the requirements of the associated issue listed below.
|
19
|
+
- Use ✅ or ⚠️ to indicate whether the implementation fully satisfies the issue requirements.
|
20
|
+
- Put this sentence immediately below the PR Summary title
|
21
|
+
Examples:
|
22
|
+
|
23
|
+
If the implementation fully delivers the requested functionality:
|
24
|
+
```
|
25
|
+
✅ Implementation Satisfies [<ISSUE_KEY>](<ISSUE_URL>).
|
26
|
+
```
|
27
|
+
If there are concerns about how thoroughly the code covers the requirements and technical description from the associated issue:
|
28
|
+
```
|
29
|
+
⚠️ <Describe specific gap or concern>.
|
30
|
+
⚠️ <Describe additional limitation or missing feature>.
|
31
|
+
```
|
32
|
+
|
33
|
+
## Subtask 3:
|
34
|
+
Write release notes for public documentation.
|
35
|
+
- Caption should be: ## Release Notes Proposal
|
36
|
+
Summarize the following changes, focusing on what is new, improved, or fixed for the end user.
|
37
|
+
Do not include internal or technical details.
|
38
|
+
Structure release notes using clear sections: Added, Changed, Fixed.
|
39
|
+
Avoid internal technical jargon or developer-specific details.
|
40
|
+
|
41
|
+
----RELATED CODEBASE CHANGES----
|
42
|
+
{% for part in diff %}{{ part }}\n{% endfor %}
|
43
|
+
|
44
|
+
----FULL FILE CONTENT AFTER APPLYING CHANGES----
|
45
|
+
{% for file, file_lines in all_file_lines.items() %}
|
46
|
+
--FILE: {{ file }}--
|
47
|
+
{{ file_lines }}
|
48
|
+
{% endfor %}
|
49
|
+
|
50
|
+
{%- if pipeline_out.associated_issue and pipeline_out.associated_issue.title %}
|
51
|
+
----ASSOCIATED ISSUE----
|
52
|
+
# {{ pipeline_out.associated_issue.title }}
|
53
|
+
{{ pipeline_out.associated_issue.description }}
|
54
|
+
URL: {{ pipeline_out.associated_issue.url }}
|
55
|
+
{%- endif -%}{{ '\n' }}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{{ self_id }}
|
2
|
+
----TASK----
|
3
|
+
Create a concise comment for QA specialists that explains how to test the code-base changes.
|
4
|
+
Include:
|
5
|
+
- User journeys that could be disrupted by failures
|
6
|
+
- Relevant security scenarios and edge cases
|
7
|
+
- Potential risk areas introduced by the changes, with suggestions for focused testing to mitigate them
|
8
|
+
|
9
|
+
----RELATED CODEBASE CHANGES----
|
10
|
+
{% for part in diff %}{{ part }}\n{% endfor %}
|
11
|
+
|
12
|
+
----FULL FILE CONTENT AFTER APPLYING CHANGES----
|
13
|
+
{% for file, file_lines in all_file_lines.items() %}
|
14
|
+
--FILE: {{ file }}--
|
15
|
+
{{ file_lines }}
|
16
|
+
{% endfor %}
|
17
|
+
|
18
|
+
{%- if pipeline_out.associated_issue and pipeline_out.associated_issue.title %}
|
19
|
+
----ASSOCIATED ISSUE----
|
20
|
+
# {{ pipeline_out.associated_issue.title }}
|
21
|
+
{{ pipeline_out.associated_issue.description }}
|
22
|
+
URL: {{ pipeline_out.associated_issue.url }}
|
23
|
+
{%- endif -%}{{ '\n' }}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "ai-cr"
|
3
|
-
version = "3.1.
|
3
|
+
version = "3.1.2"
|
4
4
|
description = "AI code review tool that works with any language model provider. It detects issues in GitHub pull requests or local changes—instantly, reliably, and without vendor lock-in."
|
5
5
|
authors = ["Nayjest <mail@vitaliy.in>"]
|
6
6
|
readme = "README.md"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|