ira-review 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.
- package/LICENSE +21 -0
- package/README.md +317 -0
- package/dist/cli.js +831 -0
- package/dist/index.cjs +841 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +264 -0
- package/dist/index.d.ts +264 -0
- package/dist/index.js +790 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mayur Patil
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# ira-review
|
|
2
|
+
|
|
3
|
+
**AI-powered PR reviews with built-in JIRA intelligence.**
|
|
4
|
+
|
|
5
|
+
Your PRs get flagged by SonarQube. Then someone has to go read each issue, figure out what it means, and decide how to fix it. That takes time.
|
|
6
|
+
|
|
7
|
+
**ira-review** does that for you. It pulls your SonarQube issues, runs them through AI, and posts clear, actionable comments right on your pull request. Explanation, impact, suggested fix. Done.
|
|
8
|
+
|
|
9
|
+
It also scores the overall risk of your PR, highlights complex code, and can validate JIRA acceptance criteria automatically.
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
1. Fetches issues from SonarQube/SonarCloud for a specific PR
|
|
14
|
+
2. Filters down to what matters (BLOCKER and CRITICAL only)
|
|
15
|
+
3. Detects your framework (React, Angular, Vue, NestJS, Node) for smarter suggestions
|
|
16
|
+
4. Sends each issue to AI for a human-readable explanation and fix
|
|
17
|
+
5. Calculates a PR risk score based on issues, security concerns, and complexity
|
|
18
|
+
6. Analyzes code complexity and flags hotspots
|
|
19
|
+
7. Validates JIRA acceptance criteria against the PR (optional)
|
|
20
|
+
8. Posts inline comments back to your PR on Bitbucket
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install ira-review
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
The fastest way to try it out. This runs against real Sonar data but prints results to your terminal instead of posting to Bitbucket. No Bitbucket token needed.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export OPENAI_API_KEY=sk-xxxxx
|
|
34
|
+
|
|
35
|
+
npx ira-review review \
|
|
36
|
+
--sonar-url https://sonarcloud.io \
|
|
37
|
+
--sonar-token sqa_xxxxx \
|
|
38
|
+
--project-key my-org_my-project \
|
|
39
|
+
--pr 42 \
|
|
40
|
+
--dry-run
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
When you're ready to post comments to a real PR:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx ira-review review \
|
|
47
|
+
--sonar-url https://sonarcloud.io \
|
|
48
|
+
--sonar-token sqa_xxxxx \
|
|
49
|
+
--project-key my-org_my-project \
|
|
50
|
+
--pr 42 \
|
|
51
|
+
--bitbucket-token bb_xxxxx \
|
|
52
|
+
--repo my-workspace/my-repo
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## PR Risk Scoring
|
|
56
|
+
|
|
57
|
+
Every review automatically calculates a risk score based on five factors:
|
|
58
|
+
|
|
59
|
+
| Factor | Max Points | What it measures |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Blocker Issues | 30 | Number of blocker-level issues |
|
|
62
|
+
| Critical Issues | 20 | Number of critical-level issues |
|
|
63
|
+
| Issue Density | 15 | Issues per file changed |
|
|
64
|
+
| Security Concerns | 20 | Vulnerabilities, CWE/OWASP-tagged issues |
|
|
65
|
+
| Code Complexity | 15 | Files with cyclomatic/cognitive complexity > 15 |
|
|
66
|
+
|
|
67
|
+
Risk levels: **LOW** (0-19), **MEDIUM** (20-39), **HIGH** (40-59), **CRITICAL** (60+)
|
|
68
|
+
|
|
69
|
+
In dry-run mode you'll see output like:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
═══════════════════════════════════════════════════
|
|
73
|
+
🟠 PR Risk Score: HIGH (45/100)
|
|
74
|
+
═══════════════════════════════════════════════════
|
|
75
|
+
▓ Blocker Issues: 20/30 - 2 blocker issues found
|
|
76
|
+
▓ Security Concerns: 10/20 - 1 security-related issue
|
|
77
|
+
▓ Code Complexity: 10/15 - 2 high-complexity files
|
|
78
|
+
▓ Critical Issues: 5/20 - 1 critical issue found
|
|
79
|
+
░ Issue Density: 0/15 - 0.5 issues per file changed
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Code Complexity Insights
|
|
83
|
+
|
|
84
|
+
ira-review fetches complexity metrics from SonarQube's measures API and flags hotspots:
|
|
85
|
+
|
|
86
|
+
- **Cyclomatic complexity** (how many paths through the code)
|
|
87
|
+
- **Cognitive complexity** (how hard it is to understand)
|
|
88
|
+
- **Lines of code** per file
|
|
89
|
+
|
|
90
|
+
Files with complexity > 15 are flagged as hotspots. This feeds into the risk score and shows up in dry-run output.
|
|
91
|
+
|
|
92
|
+
## JIRA Acceptance Criteria Validation
|
|
93
|
+
|
|
94
|
+
Connect your JIRA to validate whether a PR meets its ticket's acceptance criteria. This is optional and only runs when you provide JIRA config.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx ira-review review \
|
|
98
|
+
--sonar-url https://sonarcloud.io \
|
|
99
|
+
--sonar-token sqa_xxxxx \
|
|
100
|
+
--project-key my-org_my-project \
|
|
101
|
+
--pr 42 \
|
|
102
|
+
--jira-url https://yourcompany.atlassian.net \
|
|
103
|
+
--jira-email dev@company.com \
|
|
104
|
+
--jira-token jira_xxxxx \
|
|
105
|
+
--jira-ticket PROJ-123 \
|
|
106
|
+
--dry-run
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
It fetches the JIRA ticket, extracts the acceptance criteria, and uses AI to check each criterion against the SonarQube analysis. Output looks like:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
✅ JIRA Acceptance: PROJ-123 - Add user authentication
|
|
113
|
+
✅ CRITERION_1: MET - Authentication endpoint implemented
|
|
114
|
+
No blocker issues in auth module
|
|
115
|
+
❌ CRITERION_2: NOT_MET - Input validation
|
|
116
|
+
Critical security issue found in login handler
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
If your team uses a custom field for acceptance criteria, pass the field ID:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
--jira-ac-field customfield_10042
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Default field is `customfield_10035`.
|
|
126
|
+
|
|
127
|
+
## Use it in code
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { ReviewEngine } from "ira-review";
|
|
131
|
+
|
|
132
|
+
const engine = new ReviewEngine({
|
|
133
|
+
sonar: {
|
|
134
|
+
baseUrl: "https://sonarcloud.io",
|
|
135
|
+
token: "sqa_xxxxx",
|
|
136
|
+
projectKey: "my-org_my-project",
|
|
137
|
+
},
|
|
138
|
+
scm: {
|
|
139
|
+
token: "bb_xxxxx",
|
|
140
|
+
workspace: "my-workspace",
|
|
141
|
+
repoSlug: "my-repo",
|
|
142
|
+
},
|
|
143
|
+
ai: {
|
|
144
|
+
provider: "openai",
|
|
145
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
146
|
+
},
|
|
147
|
+
pullRequestId: "42",
|
|
148
|
+
// Optional: JIRA integration
|
|
149
|
+
jira: {
|
|
150
|
+
baseUrl: "https://yourcompany.atlassian.net",
|
|
151
|
+
email: "dev@company.com",
|
|
152
|
+
token: "jira_xxxxx",
|
|
153
|
+
},
|
|
154
|
+
jiraTicket: "PROJ-123",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const result = await engine.run();
|
|
158
|
+
|
|
159
|
+
console.log(`Risk: ${result.risk?.level}`);
|
|
160
|
+
console.log(`Complexity hotspots: ${result.complexity?.hotspots.length}`);
|
|
161
|
+
console.log(`AC validation: ${result.acceptanceValidation?.overallPass}`);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Want to preview without posting? Add `dryRun: true` to the config.
|
|
165
|
+
|
|
166
|
+
## Environment variables
|
|
167
|
+
|
|
168
|
+
Tired of passing flags every time? Set these instead. CLI flags still override them if you pass both.
|
|
169
|
+
|
|
170
|
+
| Variable | What it does |
|
|
171
|
+
|---|---|
|
|
172
|
+
| `OPENAI_API_KEY` | Your OpenAI API key (required) |
|
|
173
|
+
| `IRA_SONAR_URL` | SonarQube/SonarCloud URL |
|
|
174
|
+
| `IRA_SONAR_TOKEN` | Sonar API token |
|
|
175
|
+
| `IRA_PROJECT_KEY` | Sonar project key |
|
|
176
|
+
| `IRA_PR` | Pull request ID |
|
|
177
|
+
| `IRA_BITBUCKET_TOKEN` | Bitbucket API token |
|
|
178
|
+
| `IRA_BITBUCKET_URL` | Bitbucket Server URL (only for self-hosted) |
|
|
179
|
+
| `IRA_REPO` | `workspace/repo-slug` format |
|
|
180
|
+
| `IRA_JIRA_URL` | JIRA base URL (optional) |
|
|
181
|
+
| `IRA_JIRA_EMAIL` | JIRA account email (optional) |
|
|
182
|
+
| `IRA_JIRA_TOKEN` | JIRA API token (optional) |
|
|
183
|
+
|
|
184
|
+
Copy `.env.example` to `.env` and fill it in.
|
|
185
|
+
|
|
186
|
+
## CI/CD example
|
|
187
|
+
|
|
188
|
+
Here's how you'd wire it into a Bitbucket Pipeline:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
pipelines:
|
|
192
|
+
pull-requests:
|
|
193
|
+
'**':
|
|
194
|
+
- step:
|
|
195
|
+
name: AI Code Review
|
|
196
|
+
script:
|
|
197
|
+
- npx ira-review review --pr $BITBUCKET_PR_ID --repo $BITBUCKET_REPO_FULL_NAME
|
|
198
|
+
environment:
|
|
199
|
+
OPENAI_API_KEY: $OPENAI_API_KEY
|
|
200
|
+
IRA_SONAR_URL: $SONAR_URL
|
|
201
|
+
IRA_SONAR_TOKEN: $SONAR_TOKEN
|
|
202
|
+
IRA_PROJECT_KEY: $SONAR_PROJECT_KEY
|
|
203
|
+
IRA_BITBUCKET_TOKEN: $BB_TOKEN
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
All tokens come from your pipeline's secret variables. The package never sees or stores them.
|
|
207
|
+
|
|
208
|
+
## What comments look like
|
|
209
|
+
|
|
210
|
+
When ira-review posts to your PR, each comment looks like this:
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
🔍 IRA Review - typescript:S1854 (BLOCKER)
|
|
214
|
+
|
|
215
|
+
> Remove this useless assignment to local variable "data".
|
|
216
|
+
|
|
217
|
+
Explanation: The variable "data" is assigned a value that is never used
|
|
218
|
+
before being reassigned on line 15. This is dead code that adds confusion.
|
|
219
|
+
|
|
220
|
+
Impact: Dead code makes the codebase harder to read and maintain. It can
|
|
221
|
+
also mask real bugs if developers assume the assignment has a purpose.
|
|
222
|
+
|
|
223
|
+
Suggested Fix: Remove the assignment on line 10 entirely, or if the
|
|
224
|
+
variable is needed later, move the declaration to where it's first used.
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## CLI reference
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
ira-review review [options]
|
|
231
|
+
|
|
232
|
+
Options:
|
|
233
|
+
--sonar-url <url> SonarQube base URL
|
|
234
|
+
--sonar-token <token> Sonar API token
|
|
235
|
+
--project-key <key> Sonar project key
|
|
236
|
+
--pr <id> Pull request ID
|
|
237
|
+
--bitbucket-token <token> Bitbucket API token
|
|
238
|
+
--repo <repo> workspace/repo-slug
|
|
239
|
+
--ai-provider <provider> AI provider (default: openai)
|
|
240
|
+
--ai-model <model> AI model (default: gpt-4o-mini)
|
|
241
|
+
--bitbucket-url <url> Bitbucket base URL (self-hosted)
|
|
242
|
+
--dry-run Print to terminal instead of posting
|
|
243
|
+
--jira-url <url> JIRA base URL
|
|
244
|
+
--jira-email <email> JIRA account email
|
|
245
|
+
--jira-token <token> JIRA API token
|
|
246
|
+
--jira-ticket <key> JIRA ticket key (e.g. PROJ-123)
|
|
247
|
+
--jira-ac-field <field> Custom field ID for acceptance criteria
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## How it's built
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
src/
|
|
254
|
+
core/
|
|
255
|
+
sonarClient.ts Sonar API client with pagination and retry
|
|
256
|
+
issueProcessor.ts Filters and groups issues by file
|
|
257
|
+
reviewEngine.ts Orchestrates the full pipeline
|
|
258
|
+
riskScorer.ts Calculates PR risk score from 5 factors
|
|
259
|
+
complexityAnalyzer.ts Fetches and analyzes code complexity metrics
|
|
260
|
+
acceptanceValidator.ts Validates JIRA AC using AI
|
|
261
|
+
ai/
|
|
262
|
+
aiClient.ts Pluggable AI provider (OpenAI today)
|
|
263
|
+
promptBuilder.ts Builds structured prompts per issue
|
|
264
|
+
scm/
|
|
265
|
+
bitbucket.ts Posts inline PR comments
|
|
266
|
+
integrations/
|
|
267
|
+
jiraClient.ts JIRA REST API client
|
|
268
|
+
frameworks/
|
|
269
|
+
detector.ts Auto-detects React, Angular, Vue, NestJS, Node
|
|
270
|
+
utils/
|
|
271
|
+
retry.ts Exponential backoff with jitter
|
|
272
|
+
concurrency.ts Caps parallel AI calls (default: 3)
|
|
273
|
+
env.ts Resolves config from env vars + CLI flags
|
|
274
|
+
types/
|
|
275
|
+
config.ts All config interfaces
|
|
276
|
+
sonar.ts Sonar API types
|
|
277
|
+
review.ts Review result types and provider interfaces
|
|
278
|
+
risk.ts Risk scoring and complexity types
|
|
279
|
+
jira.ts JIRA and acceptance criteria types
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Built-in reliability
|
|
283
|
+
|
|
284
|
+
Every external API call (Sonar, OpenAI, Bitbucket, JIRA) automatically retries up to 3 times with exponential backoff. AI calls run with a concurrency limit of 3 to avoid hitting rate limits. Complexity analysis is fault-tolerant and won't block the review if the measures API is unavailable. You don't need to configure any of this.
|
|
285
|
+
|
|
286
|
+
## Security
|
|
287
|
+
|
|
288
|
+
Your tokens are safe. Here's why:
|
|
289
|
+
|
|
290
|
+
- **ira-review runs on your servers, not ours.** It's just an npm package. When it runs in your CI/CD pipeline, tokens live in your infrastructure. The package author has zero access.
|
|
291
|
+
- **The code is open source.** Every line is auditable. Tokens are only used in `Authorization` headers to APIs you already own.
|
|
292
|
+
- **Only compiled code ships to npm.** No source files, no config, no secrets. Just the `dist/` folder.
|
|
293
|
+
- **No telemetry. No analytics. No tracking.** The only network calls are the APIs you explicitly configure: Sonar, OpenAI, Bitbucket, and optionally JIRA.
|
|
294
|
+
|
|
295
|
+
Think of it like any CLI tool (ESLint, AWS CLI, Docker). You install it, you give it your credentials at runtime, it does its job. The author never sees your data.
|
|
296
|
+
|
|
297
|
+
## Development
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
npm install # install deps
|
|
301
|
+
npm run typecheck # type check
|
|
302
|
+
npm test # run all 64 tests
|
|
303
|
+
npm run test:watch # watch mode
|
|
304
|
+
npm run build # build ESM + CJS + types
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Requirements
|
|
308
|
+
|
|
309
|
+
- Node.js 18+
|
|
310
|
+
- A SonarQube or SonarCloud project with PR analysis enabled
|
|
311
|
+
- An OpenAI API key (pay-per-use, not free)
|
|
312
|
+
- A Bitbucket repo with an open PR
|
|
313
|
+
- (Optional) JIRA Cloud instance for acceptance criteria validation
|
|
314
|
+
|
|
315
|
+
## License
|
|
316
|
+
|
|
317
|
+
MIT
|