aireview 0.1.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +15 -0
- data/LICENSE +21 -0
- data/README.md +362 -0
- data/bin/aireview +8 -0
- data/config/.aireview.yml.example +31 -0
- data/lib/aireview/cli.rb +377 -0
- data/lib/aireview/config.rb +356 -0
- data/lib/aireview/context_builder.rb +111 -0
- data/lib/aireview/diff_fetcher.rb +47 -0
- data/lib/aireview/errors.rb +8 -0
- data/lib/aireview/gitlab_client.rb +166 -0
- data/lib/aireview/jira_client.rb +99 -0
- data/lib/aireview/mr_parser.rb +30 -0
- data/lib/aireview/output_schemas.rb +57 -0
- data/lib/aireview/prompts/critique.txt +57 -0
- data/lib/aireview/prompts/generate.txt +58 -0
- data/lib/aireview/publisher.rb +64 -0
- data/lib/aireview/review_marker.rb +65 -0
- data/lib/aireview/review_pipeline.rb +373 -0
- data/lib/aireview/review_renderer.rb +150 -0
- data/lib/aireview/review_schemas.rb +54 -0
- data/lib/aireview/reviewer.rb +280 -0
- data/lib/aireview/secret_scrubber.rb +70 -0
- data/lib/aireview/utils.rb +18 -0
- data/lib/aireview/version.rb +4 -0
- data/lib/aireview.rb +23 -0
- metadata +119 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0ceb8f061ed3a8172b46df1af17fa9961282858657aaf347215b42d5824acf7b
|
|
4
|
+
data.tar.gz: e345026c2323be4af4fa9ff2e00fb552685d9e9aec040a691a347cc063ce9d88
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 3fbbfb3540d90c6d5cf35bbe5e403ba0d4abc17fab630b464d9a03bd9748563cd3ed11192673ed5bca48e1d01c393b25bd5ad25324c4ccf7c3e4548695d336e0
|
|
7
|
+
data.tar.gz: 33f0bbba90317654a12835bd8328f6ef58a46b89b7d312aad6da46b76033495d708dc8da6a25772c7b8815811c0cc882878f0a58ac7cf418d0328af29821fe60
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
- Two-pass review of self-hosted GitLab merge requests: Generate finds
|
|
8
|
+
candidate findings, Critique filters out the weak ones.
|
|
9
|
+
- Gemini and local Ollama providers via RubyLLM, with a separate provider,
|
|
10
|
+
model and temperature per stage.
|
|
11
|
+
- Optional Jira issue context and per-project `review_instructions`.
|
|
12
|
+
- Path filtering and secret scrubbing before the diff reaches the LLM.
|
|
13
|
+
- A single updatable review note per merge request with `update` and `once`
|
|
14
|
+
modes, Retry detection in GitLab CI and a staleness check before posting.
|
|
15
|
+
- `.aireview.yml` and `.env` discovery walking up from the working directory.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Denis Levenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# aireview
|
|
2
|
+
|
|
3
|
+
`aireview` is a local CLI tool that reviews GitLab merge requests with the help
|
|
4
|
+
of LLMs. It uses a two-pass review pipeline: the first pass finds candidate
|
|
5
|
+
findings, the second one critiques them and drops the weak or invalid ones.
|
|
6
|
+
|
|
7
|
+
The tool supports self-hosted GitLab and self-hosted Jira only. GitLab.com and
|
|
8
|
+
Jira Cloud are not supported.
|
|
9
|
+
|
|
10
|
+
MVP flow:
|
|
11
|
+
|
|
12
|
+
1. Takes a GitLab merge request URL.
|
|
13
|
+
2. Fetches the MR metadata and changes from GitLab.
|
|
14
|
+
3. Filters out ignored paths and scrubs secrets from the diffs.
|
|
15
|
+
4. Optionally enriches the prompt with context from a Jira issue.
|
|
16
|
+
5. Runs the Generate pass through RubyLLM to get an MR summary and candidate
|
|
17
|
+
findings.
|
|
18
|
+
6. Optionally runs the Critique pass, which returns a verdict for every
|
|
19
|
+
candidate id.
|
|
20
|
+
7. Renders the final markdown review to stdout or posts it back to the merge
|
|
21
|
+
request.
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- Ruby 3.1.3 or newer (CI runs the tests on 3.1, 3.3, 3.4 and 4.0)
|
|
26
|
+
- Bundler 2.3.26 for the repository checkout; `gem install` needs no specific Bundler
|
|
27
|
+
- A GitLab personal access token
|
|
28
|
+
- An API key for a remote LLM provider; a local Ollama needs no key
|
|
29
|
+
- Optionally, a Jira login and password
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
From RubyGems:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
gem install aireview
|
|
37
|
+
aireview --help
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
From a checkout of the repository:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bundle _2.3.26_ install
|
|
44
|
+
bundle _2.3.26_ exec bin/aireview --help
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The examples below use `bundle _2.3.26_ exec bin/aireview`; with the gem
|
|
48
|
+
installed, replace it with plain `aireview`.
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
Secrets live in environment variables or in a local `.env` file. In `.env` the
|
|
53
|
+
Generate and Critique models are set explicitly:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
GITLAB_URL=https://gitlab.company.com
|
|
57
|
+
GITLAB_TOKEN=glpat-xxx
|
|
58
|
+
JIRA_URL=https://jira.company.com
|
|
59
|
+
JIRA_LOGIN=user
|
|
60
|
+
JIRA_PASSWORD=xxx
|
|
61
|
+
GEMINI_API_KEY=xxx
|
|
62
|
+
LLM_PROVIDER=gemini
|
|
63
|
+
LLM_TEMPERATURE=0
|
|
64
|
+
LLM_TIMEOUT=60
|
|
65
|
+
LLM_HTTP_PROXY=http://127.0.0.1:8888
|
|
66
|
+
LLM_GENERATE_PROVIDER=gemini
|
|
67
|
+
LLM_GENERATE_MODEL=gemini-3.7-flash
|
|
68
|
+
LLM_GENERATE_TEMPERATURE=0.3
|
|
69
|
+
LLM_CRITIQUE_PROVIDER=gemini
|
|
70
|
+
LLM_CRITIQUE_MODEL=gemini-3.8-flash
|
|
71
|
+
LLM_CRITIQUE_TEMPERATURE=0
|
|
72
|
+
REVIEW_LANGUAGE=ru
|
|
73
|
+
REVIEW_MODE=update
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
At the moment only the `gemini` and `ollama` providers are supported. The
|
|
77
|
+
provider and the model of each stage are set through `LLM_GENERATE_PROVIDER`,
|
|
78
|
+
`LLM_GENERATE_MODEL`, `LLM_CRITIQUE_PROVIDER` and `LLM_CRITIQUE_MODEL`.
|
|
79
|
+
`LLM_PROVIDER` stays the shared default when a stage has no provider of its
|
|
80
|
+
own.
|
|
81
|
+
|
|
82
|
+
`REVIEW_LANGUAGE` (or `review_language` in `.aireview.yml`) sets the language
|
|
83
|
+
of the review: both the LLM answers and the headings of the rendered report.
|
|
84
|
+
`en` is the default; `ru` is supported as well.
|
|
85
|
+
|
|
86
|
+
If only the LLM traffic has to go through a proxy, set `LLM_HTTP_PROXY` or
|
|
87
|
+
`llm.http_proxy`. That configures RubyLLM only; requests to GitLab and Jira
|
|
88
|
+
keep going directly.
|
|
89
|
+
|
|
90
|
+
### Local Ollama
|
|
91
|
+
|
|
92
|
+
Install Ollama following the
|
|
93
|
+
[official guide](https://docs.ollama.com/quickstart), then pull a local model,
|
|
94
|
+
[`qwen2.5-coder:7b`](https://ollama.com/library/qwen2.5-coder:7b):
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ollama pull qwen2.5-coder:7b
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If the service did not start on its own, start it separately and leave it
|
|
101
|
+
running during the review:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
ollama serve
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For a decent result use a stronger model for Critique than for Generate. For
|
|
108
|
+
example, to generate through a local Ollama and critique through Gemini,
|
|
109
|
+
configure `.env` like this:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
LLM_GENERATE_PROVIDER=ollama
|
|
113
|
+
LLM_GENERATE_MODEL=qwen2.5-coder:7b
|
|
114
|
+
LLM_GENERATE_TEMPERATURE=0
|
|
115
|
+
LLM_CRITIQUE_PROVIDER=gemini
|
|
116
|
+
LLM_CRITIQUE_MODEL=gemini-3.8-flash
|
|
117
|
+
LLM_CRITIQUE_TEMPERATURE=0
|
|
118
|
+
OLLAMA_API_BASE=http://localhost:11434/v1
|
|
119
|
+
GEMINI_API_KEY=xxx
|
|
120
|
+
LLM_TIMEOUT=300
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Ollama models that have been verified:
|
|
124
|
+
|
|
125
|
+
- `qwen2.5-coder:7b`
|
|
126
|
+
- `qwen2.5-coder:14b`
|
|
127
|
+
- `qwen3:8b`
|
|
128
|
+
- `qwen3:14b`
|
|
129
|
+
- `gpt-oss:20b`
|
|
130
|
+
|
|
131
|
+
The context window size is configured on the machine that runs Ollama. For a
|
|
132
|
+
permanent setting on Linux, open the service configuration:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
sudo systemctl edit ollama.service
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Add the setting:
|
|
139
|
+
|
|
140
|
+
```ini
|
|
141
|
+
[Service]
|
|
142
|
+
Environment="OLLAMA_CONTEXT_LENGTH=8192"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Then apply it and restart Ollama:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
sudo systemctl daemon-reload
|
|
149
|
+
sudo systemctl restart ollama
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
When the server is started by hand, the context can only be set for the current
|
|
153
|
+
process:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
OLLAMA_CONTEXT_LENGTH=8192 ollama serve
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
A local Ollama needs no API key. The providers can be swapped by changing
|
|
160
|
+
`LLM_GENERATE_PROVIDER`, `LLM_CRITIQUE_PROVIDER` and the corresponding models.
|
|
161
|
+
To run both stages locally, set `ollama` in both provider variables. The
|
|
162
|
+
address with `/v1` matches the
|
|
163
|
+
[Ollama configuration in RubyLLM](https://rubyllm.com/configuration/#provider-configuration).
|
|
164
|
+
`LLM_TIMEOUT` sets the timeout of every LLM request in seconds; for a slow
|
|
165
|
+
local model it can be raised.
|
|
166
|
+
|
|
167
|
+
Project rules live in `.aireview.yml`. In YAML the `generate.model` and
|
|
168
|
+
`critique.model` settings are required for each stage and are not inherited
|
|
169
|
+
from the base `llm` settings. `llm.provider` is used as the default when
|
|
170
|
+
`generate.provider` or `critique.provider` is not set:
|
|
171
|
+
|
|
172
|
+
```yaml
|
|
173
|
+
ignore_paths:
|
|
174
|
+
- db/migrate/**
|
|
175
|
+
- vendor/**
|
|
176
|
+
- node_modules/**
|
|
177
|
+
- "*.lock"
|
|
178
|
+
|
|
179
|
+
secret_patterns:
|
|
180
|
+
- 'api_key\s*=\s*["'\''].*["'\'']'
|
|
181
|
+
- 'SECRET_[A-Z_]+'
|
|
182
|
+
|
|
183
|
+
secret_files:
|
|
184
|
+
- .env
|
|
185
|
+
- .env.*
|
|
186
|
+
- config/secrets.yml
|
|
187
|
+
- config/credentials/*.key
|
|
188
|
+
- spec/fixtures/cassettes/*.yml
|
|
189
|
+
- spec/fixtures/cassettes/**/*.yml
|
|
190
|
+
- spec/cassettes/*.yml
|
|
191
|
+
- spec/cassettes/**/*.yml
|
|
192
|
+
- test/fixtures/cassettes/*.yml
|
|
193
|
+
- test/fixtures/cassettes/**/*.yml
|
|
194
|
+
|
|
195
|
+
review_instructions: |
|
|
196
|
+
This is a Rails project. Pay attention to:
|
|
197
|
+
- N+1 queries
|
|
198
|
+
- strong params
|
|
199
|
+
- missing tests for new logic
|
|
200
|
+
Ignore style — that is what the linters are for.
|
|
201
|
+
|
|
202
|
+
ollama_api_base: http://localhost:11434/v1
|
|
203
|
+
|
|
204
|
+
llm:
|
|
205
|
+
provider: gemini
|
|
206
|
+
temperature: 0
|
|
207
|
+
timeout: 60
|
|
208
|
+
http_proxy: http://127.0.0.1:8888
|
|
209
|
+
generate:
|
|
210
|
+
provider: gemini
|
|
211
|
+
model: gemini-3.7-flash
|
|
212
|
+
temperature: 0.3
|
|
213
|
+
critique:
|
|
214
|
+
provider: ollama
|
|
215
|
+
model: qwen2.5-coder:7b
|
|
216
|
+
temperature: 0
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Usage
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123
|
|
223
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123 --post
|
|
224
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123 --no-jira
|
|
225
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123 --dry-run --verbose
|
|
226
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123 --generate-model gemini-3.7-flash --critique-model gemini-3.8-flash
|
|
227
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123 --generate-model gemini-3.7-flash --generate-temperature 0.3 --critique-model gemini-3.8-flash --critique-temperature 0
|
|
228
|
+
bundle _2.3.26_ exec bin/aireview review https://gitlab.company.com/team/project/-/merge_requests/123 --no-critique
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
- `--generate-model MODEL` overrides the model for the Generate pass only.
|
|
232
|
+
- `--critique-model MODEL` overrides the model for the Critique pass only.
|
|
233
|
+
- `--generate-temperature VALUE` overrides the temperature for the Generate pass only.
|
|
234
|
+
- `--critique-temperature VALUE` overrides the temperature for the Critique pass only.
|
|
235
|
+
- `--config PATH` points at a specific `.aireview.yml`.
|
|
236
|
+
- `--no-jira` turns off the Jira enrichment even when the MR carries an issue key.
|
|
237
|
+
- `--dry-run` prints the LLM settings and the Generate prompt, plus the Critique prompt unless `--no-critique` is given.
|
|
238
|
+
- `--no-critique` skips the second pass and renders the Generate candidates directly.
|
|
239
|
+
- `--review-mode MODE` sets the behaviour when a review has already been published: `update` or `once`.
|
|
240
|
+
- `--force` reviews again even when a review for this state of the MR is already published.
|
|
241
|
+
|
|
242
|
+
### A single comment per merge request
|
|
243
|
+
|
|
244
|
+
With `--post` the review is not published as a new note every time; it updates
|
|
245
|
+
its own note instead. A hidden marker `<!-- aireview:key=... -->` is embedded
|
|
246
|
+
into the comment body, and the review uses it to find its own note among the
|
|
247
|
+
others. The note is looked up across all pages of the discussion and only among
|
|
248
|
+
the ones written by the same user the token belongs to. When there is no note
|
|
249
|
+
with the marker, the tool picks up its own older note that starts with
|
|
250
|
+
`**aireview review**`. Its key is unknown: on the next allowed run it will be
|
|
251
|
+
updated and get a marker. In `once` mode an old review also counts as existing —
|
|
252
|
+
updating it needs a Retry. Duplicates that have already piled up are not
|
|
253
|
+
removed automatically.
|
|
254
|
+
|
|
255
|
+
The key is a hash of the assembled prompts together with the providers, models
|
|
256
|
+
and temperatures of both stages. So the diff, the merge request description, the
|
|
257
|
+
Jira issue context, `review_instructions`, `ignore_paths` and the response
|
|
258
|
+
language all end up in it on their own: change any of those and the key differs,
|
|
259
|
+
so the review runs again.
|
|
260
|
+
|
|
261
|
+
The behaviour is set by `review_mode` (or `REVIEW_MODE`, or `--review-mode`):
|
|
262
|
+
|
|
263
|
+
- `update` (the default) — when the key matches the previous review, no requests
|
|
264
|
+
are sent to the LLM at all; when the diff or the settings have changed, the
|
|
265
|
+
review runs again and **overwrites** the previous comment.
|
|
266
|
+
- `once` — the review is done once, and later pushes to the MR do not repeat it.
|
|
267
|
+
To update the review by hand, press **Retry** on the job in GitLab: if the key
|
|
268
|
+
has changed, the LLM runs again and updates the previous comment. If nothing
|
|
269
|
+
changed, no requests are sent to the LLM. The current state of the MR is
|
|
270
|
+
checked, including when the job is restarted from an old pipeline. Note that
|
|
271
|
+
`.aireview.yml` (models, `review_instructions`, `ignore_paths`) is taken from
|
|
272
|
+
the checkout of the restarted pipeline. The `[skip review]` check in the
|
|
273
|
+
example below uses the `CI_MERGE_REQUEST_TITLE` of that pipeline, not the
|
|
274
|
+
fresh title from the API.
|
|
275
|
+
|
|
276
|
+
Detecting a Retry needs `CI_PROJECT_ID`, `CI_JOB_ID` and access for the
|
|
277
|
+
`GITLAB_TOKEN` to the
|
|
278
|
+
[Jobs API](https://docs.gitlab.com/api/jobs/#list-all-jobs-by-pipeline).
|
|
279
|
+
The tool checks whether an earlier attempt of the same job exists in the same
|
|
280
|
+
pipeline. An automatic retry from the GitLab `retry:` setting counts as a repeat
|
|
281
|
+
attempt too. Outside of GitLab CI, `once` mode keeps skipping an existing
|
|
282
|
+
review. The `--force` flag repeats the review even when nothing has changed.
|
|
283
|
+
|
|
284
|
+
While the review is running, the merge request can move on. Before publishing,
|
|
285
|
+
`aireview` re-reads it and compares `sha`, the target branch, `diff_refs`, the
|
|
286
|
+
title and the description: if any of those changed, the result is not published —
|
|
287
|
+
a comment must not end up holding a review of a diff that is no longer current.
|
|
288
|
+
The review text is printed to stdout before the publishing attempt, so it stays
|
|
289
|
+
in the job log. The previous comment is kept until the end of the next run.
|
|
290
|
+
|
|
291
|
+
## GitLab CI
|
|
292
|
+
|
|
293
|
+
For merge request pipelines `aireview` can run in a separate CI job, letting
|
|
294
|
+
GitLab substitute the current MR URL:
|
|
295
|
+
|
|
296
|
+
```yaml
|
|
297
|
+
workflow:
|
|
298
|
+
rules:
|
|
299
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
300
|
+
|
|
301
|
+
stages:
|
|
302
|
+
- review
|
|
303
|
+
|
|
304
|
+
aireview:
|
|
305
|
+
stage: review
|
|
306
|
+
image:
|
|
307
|
+
name: registry.gitlab.example.com/your-group/aireview:latest
|
|
308
|
+
entrypoint: [""]
|
|
309
|
+
variables:
|
|
310
|
+
MR_URL: "$CI_MERGE_REQUEST_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_IID"
|
|
311
|
+
REVIEW_LANGUAGE: "ru"
|
|
312
|
+
LLM_PROVIDER: "gemini"
|
|
313
|
+
LLM_GENERATE_MODEL: "gemini-3.7-flash"
|
|
314
|
+
LLM_CRITIQUE_MODEL: "gemini-3.8-flash"
|
|
315
|
+
LLM_TIMEOUT: "60"
|
|
316
|
+
LLM_HTTP_PROXY: "http://127.0.0.1:8888"
|
|
317
|
+
script:
|
|
318
|
+
- bundle _2.3.26_ exec bin/aireview review "$MR_URL" --verbose
|
|
319
|
+
retry:
|
|
320
|
+
max: 1
|
|
321
|
+
when:
|
|
322
|
+
- runner_system_failure
|
|
323
|
+
- stuck_or_timeout_failure
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Set secrets such as `GITLAB_TOKEN`, `GEMINI_API_KEY` and the optional Jira
|
|
327
|
+
credentials in the GitLab CI/CD variables. If the job should publish the result
|
|
328
|
+
back to the merge request, add `--post` to the review command.
|
|
329
|
+
|
|
330
|
+
For runners where the LLM provider is only reachable over WireGuard, bring up a
|
|
331
|
+
local HTTP proxy (`wireproxy`, for instance) before `aireview` starts and point
|
|
332
|
+
`LLM_HTTP_PROXY` at it. That avoids setting global `https_proxy`/`no_proxy`, so
|
|
333
|
+
GitLab and Jira stay on direct connections while RubyLLM goes through the
|
|
334
|
+
tunnel.
|
|
335
|
+
|
|
336
|
+
## Docker
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
docker build -t aireview .
|
|
340
|
+
docker run --rm --env-file .env -v "$PWD/.aireview.yml:/app/.aireview.yml:ro" aireview \
|
|
341
|
+
review https://gitlab.company.com/team/project/-/merge_requests/123
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Testing
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
bundle _2.3.26_ exec rspec
|
|
348
|
+
bundle _2.3.26_ exec rspec spec/config_spec.rb
|
|
349
|
+
bundle _2.3.26_ exec rspec spec/secret_scrubber_spec.rb
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Notes
|
|
353
|
+
|
|
354
|
+
- The CLI looks for `.aireview.yml` and `.env` walking up from the current working directory, so the project config can be kept in the repository root even when the tool is run from `aireview/`.
|
|
355
|
+
|
|
356
|
+
## Changelog
|
|
357
|
+
|
|
358
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
359
|
+
|
|
360
|
+
## License
|
|
361
|
+
|
|
362
|
+
[MIT](LICENSE)
|
data/bin/aireview
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
ignore_paths:
|
|
2
|
+
- db/migrate/**
|
|
3
|
+
- vendor/**
|
|
4
|
+
- node_modules/**
|
|
5
|
+
- "*.lock"
|
|
6
|
+
|
|
7
|
+
secret_patterns:
|
|
8
|
+
- 'api_key\s*=\s*["'\''].*["'\'']'
|
|
9
|
+
- 'SECRET_[A-Z_]+'
|
|
10
|
+
|
|
11
|
+
# update — обновлять свой комментарий, когда дифф или настройки изменились,
|
|
12
|
+
# once — один раз автоматически; Retry джоба обновляет ревью при изменениях.
|
|
13
|
+
review_mode: update
|
|
14
|
+
|
|
15
|
+
secret_files:
|
|
16
|
+
- .env
|
|
17
|
+
- .env.*
|
|
18
|
+
- config/secrets.yml
|
|
19
|
+
- config/credentials/*.key
|
|
20
|
+
|
|
21
|
+
review_instructions: |
|
|
22
|
+
Это Rails-проект. Обращай внимание на:
|
|
23
|
+
- N+1 запросы
|
|
24
|
+
- strong params
|
|
25
|
+
- отсутствие тестов для новой логики
|
|
26
|
+
Игнорируй стилистику — для этого есть линтеры.
|
|
27
|
+
|
|
28
|
+
llm:
|
|
29
|
+
provider: gemini
|
|
30
|
+
model: gemini-3.7-flash
|
|
31
|
+
temperature: 0.2
|