@probelabs/visor 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/README.md +1240 -0
- package/action.yml +142 -0
- package/defaults/.visor.yaml +184 -0
- package/dist/action-cli-bridge.d.ts +104 -0
- package/dist/action-cli-bridge.d.ts.map +1 -0
- package/dist/action-cli-bridge.js +372 -0
- package/dist/action-cli-bridge.js.map +1 -0
- package/dist/ai-review-service.d.ts +84 -0
- package/dist/ai-review-service.d.ts.map +1 -0
- package/dist/ai-review-service.js +674 -0
- package/dist/ai-review-service.js.map +1 -0
- package/dist/check-execution-engine.d.ts +165 -0
- package/dist/check-execution-engine.d.ts.map +1 -0
- package/dist/check-execution-engine.js +1172 -0
- package/dist/check-execution-engine.js.map +1 -0
- package/dist/cli-main.d.ts +6 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +247 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/cli.d.ts +47 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +224 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +10 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +53 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +63 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +369 -0
- package/dist/config.js.map +1 -0
- package/dist/dependency-resolver.d.ts +54 -0
- package/dist/dependency-resolver.d.ts.map +1 -0
- package/dist/dependency-resolver.js +163 -0
- package/dist/dependency-resolver.js.map +1 -0
- package/dist/event-mapper.d.ts +125 -0
- package/dist/event-mapper.d.ts.map +1 -0
- package/dist/event-mapper.js +311 -0
- package/dist/event-mapper.js.map +1 -0
- package/dist/failure-condition-evaluator.d.ts +81 -0
- package/dist/failure-condition-evaluator.d.ts.map +1 -0
- package/dist/failure-condition-evaluator.js +445 -0
- package/dist/failure-condition-evaluator.js.map +1 -0
- package/dist/git-repository-analyzer.d.ts +45 -0
- package/dist/git-repository-analyzer.d.ts.map +1 -0
- package/dist/git-repository-analyzer.js +285 -0
- package/dist/git-repository-analyzer.js.map +1 -0
- package/dist/github-check-service.d.ts +104 -0
- package/dist/github-check-service.d.ts.map +1 -0
- package/dist/github-check-service.js +382 -0
- package/dist/github-check-service.js.map +1 -0
- package/dist/github-comments.d.ts +109 -0
- package/dist/github-comments.d.ts.map +1 -0
- package/dist/github-comments.js +289 -0
- package/dist/github-comments.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1265 -0
- package/dist/index.js.map +1 -0
- package/dist/output-formatters.d.ts +66 -0
- package/dist/output-formatters.d.ts.map +1 -0
- package/dist/output-formatters.js +624 -0
- package/dist/output-formatters.js.map +1 -0
- package/dist/pr-analyzer.d.ts +47 -0
- package/dist/pr-analyzer.d.ts.map +1 -0
- package/dist/pr-analyzer.js +194 -0
- package/dist/pr-analyzer.js.map +1 -0
- package/dist/pr-detector.d.ts +78 -0
- package/dist/pr-detector.d.ts.map +1 -0
- package/dist/pr-detector.js +357 -0
- package/dist/pr-detector.js.map +1 -0
- package/dist/providers/ai-check-provider.d.ts +40 -0
- package/dist/providers/ai-check-provider.d.ts.map +1 -0
- package/dist/providers/ai-check-provider.js +416 -0
- package/dist/providers/ai-check-provider.js.map +1 -0
- package/dist/providers/check-provider-registry.d.ts +67 -0
- package/dist/providers/check-provider-registry.d.ts.map +1 -0
- package/dist/providers/check-provider-registry.js +138 -0
- package/dist/providers/check-provider-registry.js.map +1 -0
- package/dist/providers/check-provider.interface.d.ts +78 -0
- package/dist/providers/check-provider.interface.d.ts.map +1 -0
- package/dist/providers/check-provider.interface.js +11 -0
- package/dist/providers/check-provider.interface.js.map +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +19 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/script-check-provider.d.ts +20 -0
- package/dist/providers/script-check-provider.d.ts.map +1 -0
- package/dist/providers/script-check-provider.js +163 -0
- package/dist/providers/script-check-provider.js.map +1 -0
- package/dist/providers/tool-check-provider.d.ts +19 -0
- package/dist/providers/tool-check-provider.d.ts.map +1 -0
- package/dist/providers/tool-check-provider.js +125 -0
- package/dist/providers/tool-check-provider.js.map +1 -0
- package/dist/providers/webhook-check-provider.d.ts +21 -0
- package/dist/providers/webhook-check-provider.d.ts.map +1 -0
- package/dist/providers/webhook-check-provider.js +173 -0
- package/dist/providers/webhook-check-provider.js.map +1 -0
- package/dist/reviewer.d.ts +88 -0
- package/dist/reviewer.d.ts.map +1 -0
- package/dist/reviewer.js +760 -0
- package/dist/reviewer.js.map +1 -0
- package/dist/types/cli.d.ts +41 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +3 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/types/config.d.ts +315 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +6 -0
- package/dist/types/config.js.map +1 -0
- package/dist/utils/env-resolver.d.ts +38 -0
- package/dist/utils/env-resolver.d.ts.map +1 -0
- package/dist/utils/env-resolver.js +130 -0
- package/dist/utils/env-resolver.js.map +1 -0
- package/package.json +116 -0
package/README.md
ADDED
|
@@ -0,0 +1,1240 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="site/visor.png" alt="Visor Logo" width="200" />
|
|
3
|
+
|
|
4
|
+
# Visor - AI-Powered Code Review with Schema-Template System
|
|
5
|
+
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
[]()
|
|
9
|
+
|
|
10
|
+
**Intelligent code analysis for GitHub Pull Requests**
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🚀 Quick Start
|
|
16
|
+
|
|
17
|
+
### As GitHub Action (Recommended)
|
|
18
|
+
|
|
19
|
+
Create `.github/workflows/code-review.yml`:
|
|
20
|
+
|
|
21
|
+
#### Option 1: Using GitHub Token (Default)
|
|
22
|
+
```yaml
|
|
23
|
+
name: Code Review
|
|
24
|
+
on: pull_request
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
review:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- uses: ./ # or: gates-ai/visor-action@v1
|
|
32
|
+
with:
|
|
33
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
34
|
+
env:
|
|
35
|
+
# Choose one AI provider (see AI Configuration below)
|
|
36
|
+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
|
37
|
+
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
38
|
+
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### Option 2: Using GitHub App Authentication (Recommended for Production)
|
|
42
|
+
For better security and to have comments appear from your custom GitHub App:
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
name: Code Review with GitHub App
|
|
46
|
+
on: pull_request
|
|
47
|
+
|
|
48
|
+
jobs:
|
|
49
|
+
review:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: ./ # or: gates-ai/visor-action@v1
|
|
54
|
+
with:
|
|
55
|
+
app-id: ${{ secrets.APP_ID }}
|
|
56
|
+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
57
|
+
# installation-id: ${{ secrets.APP_INSTALLATION_ID }} # Optional, auto-detected
|
|
58
|
+
env:
|
|
59
|
+
# Choose one AI provider (see AI Configuration below)
|
|
60
|
+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
|
61
|
+
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
62
|
+
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Setting up GitHub App:**
|
|
66
|
+
1. [Create a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) with these permissions:
|
|
67
|
+
- **Pull requests**: Read & Write
|
|
68
|
+
- **Issues**: Write
|
|
69
|
+
- **Metadata**: Read
|
|
70
|
+
2. Generate and download a private key for your app
|
|
71
|
+
3. Install the app on your repository
|
|
72
|
+
4. Add these secrets to your repository:
|
|
73
|
+
- `APP_ID`: Your GitHub App's ID
|
|
74
|
+
- `APP_PRIVATE_KEY`: The private key you downloaded (entire contents)
|
|
75
|
+
- `APP_INSTALLATION_ID`: (Optional) The installation ID for this repository
|
|
76
|
+
|
|
77
|
+
That's it! Visor will automatically review your PRs with AI-powered analysis.
|
|
78
|
+
|
|
79
|
+
### As CLI Tool
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Build the project
|
|
83
|
+
npm install
|
|
84
|
+
npm run build
|
|
85
|
+
|
|
86
|
+
# Run analysis
|
|
87
|
+
./dist/cli-main.js --check all
|
|
88
|
+
|
|
89
|
+
# Output as JSON
|
|
90
|
+
./dist/cli-main.js --check security --output json
|
|
91
|
+
|
|
92
|
+
# Use custom config
|
|
93
|
+
./dist/cli-main.js --config custom.yaml
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## ✨ Features
|
|
97
|
+
|
|
98
|
+
- **Automated PR Reviews** - Analyzes code changes and posts review comments
|
|
99
|
+
- **Schema-Template System** - Flexible data validation with JSON Schema and Liquid templating
|
|
100
|
+
- **Group-Based Comments** - Multiple GitHub comments organized by check groups
|
|
101
|
+
- **Multiple Check Types** - Security, performance, style, and architecture analysis
|
|
102
|
+
- **Flexible Output** - Table, JSON, Markdown, or SARIF format
|
|
103
|
+
- **Step Dependencies** - Define execution order with `depends_on` relationships
|
|
104
|
+
- **PR Commands** - Trigger reviews with `/review` comments
|
|
105
|
+
- **GitHub Integration** - Creates check runs, adds labels, posts comments
|
|
106
|
+
|
|
107
|
+
## 💬 PR Comment Commands
|
|
108
|
+
|
|
109
|
+
Add comments to your PR to trigger Visor:
|
|
110
|
+
|
|
111
|
+
- `/review` - Run all checks
|
|
112
|
+
- `/review --check security` - Run security checks only
|
|
113
|
+
- `/review --check performance` - Run performance checks only
|
|
114
|
+
- `/review --help` - Show available commands
|
|
115
|
+
|
|
116
|
+
## 📋 CLI Usage
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
visor [options]
|
|
120
|
+
|
|
121
|
+
Options:
|
|
122
|
+
-c, --check <type> Check type: security, performance, style, architecture, all
|
|
123
|
+
Can be used multiple times: --check security --check style
|
|
124
|
+
-o, --output <format> Output format: table, json, markdown, sarif
|
|
125
|
+
Default: table
|
|
126
|
+
--config <path> Path to configuration file
|
|
127
|
+
Default: visor.config.yaml
|
|
128
|
+
--version Show version
|
|
129
|
+
--help Show help
|
|
130
|
+
|
|
131
|
+
Examples:
|
|
132
|
+
visor --check all # Run all checks
|
|
133
|
+
visor --check security --output json # Security check with JSON output
|
|
134
|
+
visor --check style --check performance # Multiple specific checks
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 🤖 AI Configuration
|
|
138
|
+
|
|
139
|
+
Visor uses AI-powered code analysis to provide intelligent review feedback. Configure one of the following providers:
|
|
140
|
+
|
|
141
|
+
### Supported AI Providers
|
|
142
|
+
|
|
143
|
+
| Provider | Environment Variable | Recommended Models |
|
|
144
|
+
|----------|---------------------|-------------------|
|
|
145
|
+
| Google Gemini | `GOOGLE_API_KEY` | `gemini-2.0-flash-exp` (default), `gemini-1.5-pro` |
|
|
146
|
+
| Anthropic Claude | `ANTHROPIC_API_KEY` | `claude-3-opus`, `claude-3-sonnet` |
|
|
147
|
+
| OpenAI GPT | `OPENAI_API_KEY` | `gpt-4`, `gpt-4-turbo`, `gpt-3.5-turbo` |
|
|
148
|
+
|
|
149
|
+
### Setting Up API Keys
|
|
150
|
+
|
|
151
|
+
#### For GitHub Actions
|
|
152
|
+
Add your API key as a repository secret:
|
|
153
|
+
1. Go to Settings → Secrets and variables → Actions
|
|
154
|
+
2. Click "New repository secret"
|
|
155
|
+
3. Add one of: `GOOGLE_API_KEY`, `ANTHROPIC_API_KEY`, or `OPENAI_API_KEY`
|
|
156
|
+
4. (Optional) Add `AI_MODEL_NAME` to specify a model
|
|
157
|
+
|
|
158
|
+
#### For Local Development
|
|
159
|
+
Set environment variables:
|
|
160
|
+
```bash
|
|
161
|
+
# Using Google Gemini
|
|
162
|
+
export GOOGLE_API_KEY="your-api-key"
|
|
163
|
+
export MODEL_NAME="gemini-2.0-flash-exp"
|
|
164
|
+
|
|
165
|
+
# Using Anthropic Claude
|
|
166
|
+
export ANTHROPIC_API_KEY="your-api-key"
|
|
167
|
+
export MODEL_NAME="claude-3-sonnet"
|
|
168
|
+
|
|
169
|
+
# Using OpenAI GPT
|
|
170
|
+
export OPENAI_API_KEY="your-api-key"
|
|
171
|
+
export MODEL_NAME="gpt-4"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Getting API Keys
|
|
175
|
+
|
|
176
|
+
- **Google Gemini**: [Get API Key](https://makersuite.google.com/app/apikey) (Free tier available)
|
|
177
|
+
- **Anthropic Claude**: [Get API Key](https://console.anthropic.com/)
|
|
178
|
+
- **OpenAI GPT**: [Get API Key](https://platform.openai.com/api-keys)
|
|
179
|
+
|
|
180
|
+
### Fallback Behavior
|
|
181
|
+
|
|
182
|
+
If no API key is configured, Visor will fall back to basic pattern-matching analysis:
|
|
183
|
+
- Keyword detection for security issues (e.g., `eval`, `innerHTML`)
|
|
184
|
+
- Simple performance checks (nested loops, large files)
|
|
185
|
+
- Basic style validation
|
|
186
|
+
|
|
187
|
+
For best results, configure an AI provider for intelligent, context-aware code review.
|
|
188
|
+
|
|
189
|
+
## 📊 Step Dependencies & Intelligent Execution
|
|
190
|
+
|
|
191
|
+
### Dependency-Aware Check Execution
|
|
192
|
+
|
|
193
|
+
Visor supports defining dependencies between checks using the `depends_on` field. This enables:
|
|
194
|
+
|
|
195
|
+
- **Sequential Execution**: Dependent checks wait for their dependencies to complete
|
|
196
|
+
- **Parallel Optimization**: Independent checks run simultaneously for faster execution
|
|
197
|
+
- **Smart Scheduling**: Automatic topological sorting ensures correct execution order
|
|
198
|
+
|
|
199
|
+
### Configuration Example
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
version: "1.0"
|
|
203
|
+
checks:
|
|
204
|
+
security:
|
|
205
|
+
type: ai
|
|
206
|
+
group: code-review
|
|
207
|
+
schema: code-review
|
|
208
|
+
prompt: "Comprehensive security analysis..."
|
|
209
|
+
on: [pr_opened, pr_updated]
|
|
210
|
+
# No dependencies - runs first
|
|
211
|
+
|
|
212
|
+
performance:
|
|
213
|
+
type: ai
|
|
214
|
+
group: code-review
|
|
215
|
+
schema: code-review
|
|
216
|
+
prompt: "Performance analysis..."
|
|
217
|
+
on: [pr_opened, pr_updated]
|
|
218
|
+
# No dependencies - runs parallel with security
|
|
219
|
+
|
|
220
|
+
style:
|
|
221
|
+
type: ai
|
|
222
|
+
group: code-review
|
|
223
|
+
schema: code-review
|
|
224
|
+
prompt: "Style analysis based on security findings..."
|
|
225
|
+
on: [pr_opened]
|
|
226
|
+
depends_on: [security] # Waits for security to complete
|
|
227
|
+
|
|
228
|
+
architecture:
|
|
229
|
+
type: ai
|
|
230
|
+
group: code-review
|
|
231
|
+
schema: code-review
|
|
232
|
+
prompt: "Architecture analysis building on previous checks..."
|
|
233
|
+
on: [pr_opened, pr_updated]
|
|
234
|
+
depends_on: [security, performance] # Waits for both to complete
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Execution Flow
|
|
238
|
+
|
|
239
|
+
With the above configuration:
|
|
240
|
+
1. **Level 0**: `security` and `performance` run in parallel
|
|
241
|
+
2. **Level 1**: `style` runs after `security` completes
|
|
242
|
+
3. **Level 2**: `architecture` runs after both `security` and `performance` complete
|
|
243
|
+
|
|
244
|
+
### Benefits
|
|
245
|
+
|
|
246
|
+
- **Faster Execution**: Independent checks run in parallel
|
|
247
|
+
- **Better Context**: Later checks can reference findings from dependencies
|
|
248
|
+
- **Logical Flow**: Ensures foundational checks (like security) complete before specialized ones
|
|
249
|
+
- **Error Handling**: Failed dependencies don't prevent other independent checks from running
|
|
250
|
+
|
|
251
|
+
### Advanced Patterns
|
|
252
|
+
|
|
253
|
+
#### Diamond Dependency
|
|
254
|
+
```yaml
|
|
255
|
+
version: "1.0"
|
|
256
|
+
checks:
|
|
257
|
+
foundation:
|
|
258
|
+
type: ai
|
|
259
|
+
group: base
|
|
260
|
+
schema: code-review
|
|
261
|
+
prompt: "Base analysis"
|
|
262
|
+
|
|
263
|
+
branch_a:
|
|
264
|
+
type: ai
|
|
265
|
+
group: code-review
|
|
266
|
+
schema: code-review
|
|
267
|
+
depends_on: [foundation]
|
|
268
|
+
|
|
269
|
+
branch_b:
|
|
270
|
+
type: ai
|
|
271
|
+
group: code-review
|
|
272
|
+
schema: code-review
|
|
273
|
+
depends_on: [foundation]
|
|
274
|
+
|
|
275
|
+
final:
|
|
276
|
+
type: ai
|
|
277
|
+
group: summary
|
|
278
|
+
schema: markdown
|
|
279
|
+
depends_on: [branch_a, branch_b]
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### Multiple Independent Chains
|
|
283
|
+
```yaml
|
|
284
|
+
version: "1.0"
|
|
285
|
+
checks:
|
|
286
|
+
# Security chain
|
|
287
|
+
security_basic:
|
|
288
|
+
type: ai
|
|
289
|
+
group: security
|
|
290
|
+
schema: code-review
|
|
291
|
+
prompt: "Basic security scan"
|
|
292
|
+
|
|
293
|
+
security_advanced:
|
|
294
|
+
type: ai
|
|
295
|
+
group: security
|
|
296
|
+
schema: code-review
|
|
297
|
+
depends_on: [security_basic]
|
|
298
|
+
|
|
299
|
+
# Performance chain
|
|
300
|
+
performance_basic:
|
|
301
|
+
type: ai
|
|
302
|
+
group: performance
|
|
303
|
+
schema: code-review
|
|
304
|
+
prompt: "Basic performance scan"
|
|
305
|
+
|
|
306
|
+
performance_advanced:
|
|
307
|
+
type: ai
|
|
308
|
+
group: performance
|
|
309
|
+
schema: code-review
|
|
310
|
+
depends_on: [performance_basic]
|
|
311
|
+
|
|
312
|
+
# Final integration (waits for both chains)
|
|
313
|
+
integration:
|
|
314
|
+
type: ai
|
|
315
|
+
group: summary
|
|
316
|
+
schema: markdown
|
|
317
|
+
depends_on: [security_advanced, performance_advanced]
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Error Handling
|
|
321
|
+
|
|
322
|
+
- **Cycle Detection**: Circular dependencies are detected and reported
|
|
323
|
+
- **Missing Dependencies**: References to non-existent checks are validated
|
|
324
|
+
- **Graceful Failures**: Failed checks don't prevent independent checks from running
|
|
325
|
+
- **Dependency Results**: Results from dependency checks are available to dependent checks
|
|
326
|
+
|
|
327
|
+
## 📋 Schema-Template System
|
|
328
|
+
|
|
329
|
+
Visor's new schema-template system provides structured output validation and customizable rendering, replacing the previous category-based approach with a more flexible, configuration-driven system.
|
|
330
|
+
|
|
331
|
+
### Overview
|
|
332
|
+
|
|
333
|
+
The schema-template system separates data structure (schemas) from presentation (templates), enabling:
|
|
334
|
+
|
|
335
|
+
- **JSON Schema Validation**: Runtime validation of check results using AJV
|
|
336
|
+
- **Liquid Templates**: Dynamic content rendering with conditional logic and loops
|
|
337
|
+
- **Multiple Output Formats**: Support for structured tables, free-form markdown, and custom formats
|
|
338
|
+
- **Group-Based Comments**: Create separate GitHub comments based on `group` configuration
|
|
339
|
+
- **Check-Focused Organization**: Group issues by check name rather than artificial categories
|
|
340
|
+
- **Extensible Design**: Easy to add new schemas and output formats
|
|
341
|
+
|
|
342
|
+
### Configuration
|
|
343
|
+
|
|
344
|
+
```yaml
|
|
345
|
+
version: "1.0"
|
|
346
|
+
|
|
347
|
+
checks:
|
|
348
|
+
security:
|
|
349
|
+
type: ai
|
|
350
|
+
group: code-review # Groups this check with others for commenting
|
|
351
|
+
schema: code-review # Uses built-in code-review schema
|
|
352
|
+
prompt: |
|
|
353
|
+
Perform comprehensive security analysis focusing on:
|
|
354
|
+
- SQL injection vulnerabilities
|
|
355
|
+
- XSS attack vectors
|
|
356
|
+
- Authentication/authorization issues
|
|
357
|
+
|
|
358
|
+
Return results in JSON format matching the code-review schema.
|
|
359
|
+
on: [pr_opened, pr_updated]
|
|
360
|
+
|
|
361
|
+
performance:
|
|
362
|
+
type: ai
|
|
363
|
+
group: code-review # Same group = combined in one comment
|
|
364
|
+
schema: code-review # Same schema = same table format
|
|
365
|
+
prompt: |
|
|
366
|
+
Analyze performance issues including:
|
|
367
|
+
- Algorithm complexity
|
|
368
|
+
- Memory usage patterns
|
|
369
|
+
- Database query optimization
|
|
370
|
+
on: [pr_opened, pr_updated]
|
|
371
|
+
|
|
372
|
+
full-review:
|
|
373
|
+
type: ai
|
|
374
|
+
group: pr-overview # Different group = separate comment
|
|
375
|
+
schema: text # Uses built-in text schema for markdown
|
|
376
|
+
prompt: |
|
|
377
|
+
Create a comprehensive pull request overview in markdown format with:
|
|
378
|
+
|
|
379
|
+
## 📋 Pull Request Overview
|
|
380
|
+
1. **Summary**: Brief description of changes
|
|
381
|
+
2. **Files Changed**: Table of modified files
|
|
382
|
+
3. **Architecture Impact**: Key architectural considerations
|
|
383
|
+
on: [pr_opened]
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## 🎯 Enhanced Prompts
|
|
387
|
+
|
|
388
|
+
Visor supports advanced prompt features including Liquid templates, file-based prompts, and access to event context and previous check results.
|
|
389
|
+
|
|
390
|
+
### Smart Auto-Detection
|
|
391
|
+
|
|
392
|
+
Visor automatically detects whether your prompt is a file path or inline content:
|
|
393
|
+
|
|
394
|
+
```yaml
|
|
395
|
+
checks:
|
|
396
|
+
security:
|
|
397
|
+
type: ai
|
|
398
|
+
# File path - automatically detected
|
|
399
|
+
prompt: ./templates/security-analysis.liquid
|
|
400
|
+
|
|
401
|
+
performance:
|
|
402
|
+
type: ai
|
|
403
|
+
# Inline string - automatically detected
|
|
404
|
+
prompt: "Analyze this code for performance issues"
|
|
405
|
+
|
|
406
|
+
quality:
|
|
407
|
+
type: ai
|
|
408
|
+
# Multi-line string - automatically detected
|
|
409
|
+
prompt: |
|
|
410
|
+
Review this code for:
|
|
411
|
+
- Code quality issues
|
|
412
|
+
- Best practices violations
|
|
413
|
+
- Maintainability concerns
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Auto-detection rules:**
|
|
417
|
+
- ✅ **File paths**: `./file.liquid`, `../templates/prompt.md`, `/absolute/path/file.txt`
|
|
418
|
+
- ✅ **Inline content**: `Analyze this code`, `Review for security issues`
|
|
419
|
+
- ✅ **Multi-line**: Uses YAML `|` or `>` syntax for longer prompts
|
|
420
|
+
|
|
421
|
+
### Liquid Template Support
|
|
422
|
+
|
|
423
|
+
Prompts can use [Liquid templating](https://shopify.github.io/liquid/) with rich context data:
|
|
424
|
+
|
|
425
|
+
```yaml
|
|
426
|
+
checks:
|
|
427
|
+
context-aware-review:
|
|
428
|
+
type: ai
|
|
429
|
+
prompt: |
|
|
430
|
+
# Review for PR {{ pr.number }}: {{ pr.title }}
|
|
431
|
+
|
|
432
|
+
## PR Details
|
|
433
|
+
- Author: {{ pr.author }}
|
|
434
|
+
- Branch: {{ pr.headBranch }} → {{ pr.baseBranch }}
|
|
435
|
+
- Files changed: {{ files.size }}
|
|
436
|
+
- Total changes: +{{ pr.totalAdditions }}/-{{ pr.totalDeletions }}
|
|
437
|
+
|
|
438
|
+
## File Analysis
|
|
439
|
+
{% if utils.filesByExtension.ts %}
|
|
440
|
+
### TypeScript Files ({{ utils.filesByExtension.ts.size }})
|
|
441
|
+
{% for file in utils.filesByExtension.ts %}
|
|
442
|
+
- {{ file.filename }} (+{{ file.additions }}/-{{ file.deletions }})
|
|
443
|
+
{% endfor %}
|
|
444
|
+
{% endif %}
|
|
445
|
+
|
|
446
|
+
{% if utils.hasLargeChanges %}
|
|
447
|
+
⚠️ **Warning**: This PR contains large changes requiring careful review.
|
|
448
|
+
{% endif %}
|
|
449
|
+
|
|
450
|
+
## Previous Results
|
|
451
|
+
{% if outputs.security %}
|
|
452
|
+
Security check found {{ outputs.security.totalIssues }} issues:
|
|
453
|
+
{% for issue in outputs.security.securityIssues %}
|
|
454
|
+
- **{{ issue.severity | upcase }}**: {{ issue.message }} in {{ issue.file }}:{{ issue.line }}
|
|
455
|
+
{% endfor %}
|
|
456
|
+
{% endif %}
|
|
457
|
+
on: [pr_opened, pr_updated]
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### File-Based Prompts
|
|
461
|
+
|
|
462
|
+
Store prompts in external files for better organization:
|
|
463
|
+
|
|
464
|
+
```yaml
|
|
465
|
+
checks:
|
|
466
|
+
security-review:
|
|
467
|
+
type: ai
|
|
468
|
+
prompt: ./prompts/security-detailed.liquid # Auto-detects file path
|
|
469
|
+
on: [pr_opened, pr_updated]
|
|
470
|
+
|
|
471
|
+
architecture-check:
|
|
472
|
+
type: ai
|
|
473
|
+
prompt: /absolute/path/to/architecture-prompt.liquid # Auto-detects file path
|
|
474
|
+
on: [pr_opened]
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Template Context Variables
|
|
478
|
+
|
|
479
|
+
#### PR Information (`pr`)
|
|
480
|
+
```liquid
|
|
481
|
+
{{ pr.number }} <!-- PR number -->
|
|
482
|
+
{{ pr.title }} <!-- PR title -->
|
|
483
|
+
{{ pr.author }} <!-- PR author -->
|
|
484
|
+
{{ pr.baseBranch }} <!-- Base branch name -->
|
|
485
|
+
{{ pr.headBranch }} <!-- Head branch name -->
|
|
486
|
+
{{ pr.totalAdditions }} <!-- Total lines added -->
|
|
487
|
+
{{ pr.totalDeletions }} <!-- Total lines deleted -->
|
|
488
|
+
{{ pr.isIncremental }} <!-- Boolean: incremental analysis -->
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
#### File Information (`files` and `utils`)
|
|
492
|
+
```liquid
|
|
493
|
+
{{ files.size }} <!-- Number of files changed -->
|
|
494
|
+
{{ utils.filesByExtension.ts.size }} <!-- TypeScript files count -->
|
|
495
|
+
{{ utils.filesByExtension.js.size }} <!-- JavaScript files count -->
|
|
496
|
+
{{ utils.addedFiles.size }} <!-- Newly added files -->
|
|
497
|
+
{{ utils.modifiedFiles.size }} <!-- Modified files -->
|
|
498
|
+
{{ utils.hasLargeChanges }} <!-- Boolean: large changes detected -->
|
|
499
|
+
{{ utils.totalFiles }} <!-- Total files changed -->
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
#### GitHub Event Context (`event`)
|
|
503
|
+
```liquid
|
|
504
|
+
{{ event.name }} <!-- Event name (pull_request, issue_comment, etc.) -->
|
|
505
|
+
{{ event.action }} <!-- Event action (opened, updated, etc.) -->
|
|
506
|
+
{{ event.repository.fullName }} <!-- Repository owner/name -->
|
|
507
|
+
|
|
508
|
+
<!-- For comment-triggered events -->
|
|
509
|
+
{% if event.comment %}
|
|
510
|
+
{{ event.comment.body }} <!-- Comment text -->
|
|
511
|
+
{{ event.comment.author }} <!-- Comment author -->
|
|
512
|
+
{% endif %}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
#### Previous Check Results (`outputs`)
|
|
516
|
+
```liquid
|
|
517
|
+
{% if outputs.security %}
|
|
518
|
+
Security Results:
|
|
519
|
+
- Total issues: {{ outputs.security.totalIssues }}
|
|
520
|
+
- Critical: {{ outputs.security.criticalIssues }}
|
|
521
|
+
- Errors: {{ outputs.security.errorIssues }}
|
|
522
|
+
- Warnings: {{ outputs.security.warningIssues }}
|
|
523
|
+
|
|
524
|
+
Security Issues:
|
|
525
|
+
{% for issue in outputs.security.securityIssues %}
|
|
526
|
+
- {{ issue.severity | upcase }}: {{ issue.message }}
|
|
527
|
+
{% endfor %}
|
|
528
|
+
|
|
529
|
+
Suggestions:
|
|
530
|
+
{% for suggestion in outputs.security.suggestions %}
|
|
531
|
+
- {{ suggestion }}
|
|
532
|
+
{% endfor %}
|
|
533
|
+
{% endif %}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### Custom Templates
|
|
537
|
+
|
|
538
|
+
Customize output rendering with custom templates:
|
|
539
|
+
|
|
540
|
+
```yaml
|
|
541
|
+
checks:
|
|
542
|
+
security-with-custom-output:
|
|
543
|
+
type: ai
|
|
544
|
+
prompt: "Analyze security vulnerabilities..."
|
|
545
|
+
template:
|
|
546
|
+
file: ./templates/security-report.liquid
|
|
547
|
+
# OR inline content:
|
|
548
|
+
# content: |
|
|
549
|
+
# # 🔒 Security Report
|
|
550
|
+
# {% for issue in issues %}
|
|
551
|
+
# - **{{ issue.severity }}**: {{ issue.message }}
|
|
552
|
+
# {% endfor %}
|
|
553
|
+
on: [pr_opened]
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Advanced Example: Multi-Context Review
|
|
557
|
+
|
|
558
|
+
```yaml
|
|
559
|
+
checks:
|
|
560
|
+
comprehensive-review:
|
|
561
|
+
type: ai
|
|
562
|
+
depends_on: [security, performance] # Run after these checks
|
|
563
|
+
prompt:
|
|
564
|
+
content: |
|
|
565
|
+
# Comprehensive Review for {{ event.repository.fullName }}#{{ pr.number }}
|
|
566
|
+
|
|
567
|
+
{% if event.comment %}
|
|
568
|
+
Triggered by comment: "{{ event.comment.body }}" from {{ event.comment.author }}
|
|
569
|
+
{% endif %}
|
|
570
|
+
|
|
571
|
+
## Previous Analysis Summary
|
|
572
|
+
{% if outputs.security %}
|
|
573
|
+
- **Security**: {{ outputs.security.totalIssues }} issues found
|
|
574
|
+
{% for issue in outputs.security.criticalIssues %}
|
|
575
|
+
- 🔴 **CRITICAL**: {{ issue.message }}
|
|
576
|
+
{% endfor %}
|
|
577
|
+
{% endif %}
|
|
578
|
+
|
|
579
|
+
{% if outputs.performance %}
|
|
580
|
+
- **Performance**: {{ outputs.performance.totalIssues }} issues found
|
|
581
|
+
{% endif %}
|
|
582
|
+
|
|
583
|
+
## New Focus Areas
|
|
584
|
+
Based on file changes in this PR:
|
|
585
|
+
{% for ext, files in utils.filesByExtension %}
|
|
586
|
+
- {{ ext | upcase }} files: {{ files.size }}
|
|
587
|
+
{% endfor %}
|
|
588
|
+
|
|
589
|
+
Please provide an architectural review focusing on:
|
|
590
|
+
1. Integration between modified components
|
|
591
|
+
2. Impact on existing security measures
|
|
592
|
+
3. Performance implications of changes
|
|
593
|
+
4. Maintainability and technical debt
|
|
594
|
+
on: [pr_opened, pr_updated]
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
## 🔧 Advanced Configuration
|
|
598
|
+
|
|
599
|
+
### Check-Level AI Configuration
|
|
600
|
+
|
|
601
|
+
Override global AI settings for specific checks:
|
|
602
|
+
|
|
603
|
+
```yaml
|
|
604
|
+
# Global AI settings (optional)
|
|
605
|
+
ai_model: gpt-3.5-turbo
|
|
606
|
+
ai_provider: openai
|
|
607
|
+
|
|
608
|
+
checks:
|
|
609
|
+
security-advanced:
|
|
610
|
+
type: ai
|
|
611
|
+
prompt: "Perform advanced security analysis..."
|
|
612
|
+
# Override global settings for this check
|
|
613
|
+
ai_model: claude-3-opus
|
|
614
|
+
ai_provider: anthropic
|
|
615
|
+
on: [pr_opened]
|
|
616
|
+
|
|
617
|
+
performance-quick:
|
|
618
|
+
type: ai
|
|
619
|
+
prompt: "Quick performance check..."
|
|
620
|
+
# Use different model for performance checks
|
|
621
|
+
ai_model: gpt-4-turbo
|
|
622
|
+
# ai_provider will inherit global setting (openai)
|
|
623
|
+
on: [pr_updated]
|
|
624
|
+
|
|
625
|
+
quality-standard:
|
|
626
|
+
type: ai
|
|
627
|
+
prompt: "Standard quality review..."
|
|
628
|
+
# No overrides - uses global settings
|
|
629
|
+
on: [pr_opened]
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Environment Variable Configuration
|
|
633
|
+
|
|
634
|
+
Use environment variables with GitHub Actions-like syntax:
|
|
635
|
+
|
|
636
|
+
```yaml
|
|
637
|
+
# Global environment variables
|
|
638
|
+
env:
|
|
639
|
+
DEFAULT_TIMEOUT: "30000"
|
|
640
|
+
LOG_LEVEL: "info"
|
|
641
|
+
SHARED_SECRET: "${{ env.GITHUB_TOKEN }}"
|
|
642
|
+
|
|
643
|
+
checks:
|
|
644
|
+
security-with-env:
|
|
645
|
+
type: ai
|
|
646
|
+
prompt: |
|
|
647
|
+
Security analysis using timeout: ${{ env.SECURITY_TIMEOUT }}ms
|
|
648
|
+
API endpoint: ${{ env.SECURITY_API_ENDPOINT }}
|
|
649
|
+
|
|
650
|
+
Analyze these files for security issues...
|
|
651
|
+
# Check-specific environment variables
|
|
652
|
+
env:
|
|
653
|
+
SECURITY_API_KEY: "${{ env.ANTHROPIC_API_KEY }}"
|
|
654
|
+
SECURITY_TIMEOUT: "${DEFAULT_TIMEOUT}" # Reference global env
|
|
655
|
+
ANALYSIS_MODE: "comprehensive"
|
|
656
|
+
CUSTOM_RULES: "security,auth,crypto"
|
|
657
|
+
# Use environment variable for AI model
|
|
658
|
+
ai_model: "${{ env.SECURITY_MODEL }}"
|
|
659
|
+
ai_provider: "${{ env.PREFERRED_AI_PROVIDER }}"
|
|
660
|
+
on: [pr_opened, pr_updated]
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
#### Environment Variable Syntax
|
|
664
|
+
|
|
665
|
+
Visor supports multiple environment variable syntaxes:
|
|
666
|
+
|
|
667
|
+
```yaml
|
|
668
|
+
env:
|
|
669
|
+
# GitHub Actions style (recommended)
|
|
670
|
+
API_KEY: "${{ env.OPENAI_API_KEY }}"
|
|
671
|
+
|
|
672
|
+
# Shell style
|
|
673
|
+
MODEL_NAME: "${CUSTOM_MODEL}"
|
|
674
|
+
|
|
675
|
+
# Simple shell style
|
|
676
|
+
PROVIDER: "$AI_PROVIDER"
|
|
677
|
+
|
|
678
|
+
# Mixed usage
|
|
679
|
+
ENDPOINT: "https://${{ env.API_HOST }}/v1/${API_VERSION}"
|
|
680
|
+
|
|
681
|
+
# Static values
|
|
682
|
+
TIMEOUT: 45000
|
|
683
|
+
DEBUG_MODE: true
|
|
684
|
+
FEATURES: "security,performance"
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### Configuration Inheritance
|
|
688
|
+
|
|
689
|
+
Configuration follows this priority order:
|
|
690
|
+
|
|
691
|
+
1. **Check-level settings** (highest priority)
|
|
692
|
+
2. **Global configuration**
|
|
693
|
+
3. **Environment variables**
|
|
694
|
+
4. **Default values** (lowest priority)
|
|
695
|
+
|
|
696
|
+
```yaml
|
|
697
|
+
# Global defaults
|
|
698
|
+
ai_model: gpt-3.5-turbo
|
|
699
|
+
ai_provider: openai
|
|
700
|
+
env:
|
|
701
|
+
GLOBAL_TIMEOUT: "30000"
|
|
702
|
+
|
|
703
|
+
checks:
|
|
704
|
+
example-check:
|
|
705
|
+
type: ai
|
|
706
|
+
prompt: "Example analysis"
|
|
707
|
+
# These override global settings
|
|
708
|
+
ai_model: claude-3-opus # Overrides global ai_model
|
|
709
|
+
# ai_provider: inherits openai from global
|
|
710
|
+
|
|
711
|
+
env:
|
|
712
|
+
# Inherits GLOBAL_TIMEOUT from global env
|
|
713
|
+
CHECK_TIMEOUT: "45000" # Check-specific setting
|
|
714
|
+
API_KEY: "${{ env.ANTHROPIC_API_KEY }}" # From process env
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### Production Environment Setup
|
|
718
|
+
|
|
719
|
+
For production deployments, set up environment variables:
|
|
720
|
+
|
|
721
|
+
```bash
|
|
722
|
+
# AI Provider API Keys
|
|
723
|
+
export OPENAI_API_KEY="sk-your-openai-key"
|
|
724
|
+
export ANTHROPIC_API_KEY="sk-ant-your-anthropic-key"
|
|
725
|
+
export GOOGLE_API_KEY="your-google-api-key"
|
|
726
|
+
|
|
727
|
+
# GitHub Integration
|
|
728
|
+
export GITHUB_TOKEN="ghp_your-github-token"
|
|
729
|
+
|
|
730
|
+
# Custom Configuration
|
|
731
|
+
export SECURITY_MODEL="claude-3-opus"
|
|
732
|
+
export PERFORMANCE_MODEL="gpt-4-turbo"
|
|
733
|
+
export PREFERRED_AI_PROVIDER="anthropic"
|
|
734
|
+
export ANALYSIS_TIMEOUT="60000"
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Then reference them in your configuration:
|
|
738
|
+
|
|
739
|
+
```yaml
|
|
740
|
+
env:
|
|
741
|
+
# Production environment references
|
|
742
|
+
OPENAI_KEY: "${{ env.OPENAI_API_KEY }}"
|
|
743
|
+
ANTHROPIC_KEY: "${{ env.ANTHROPIC_API_KEY }}"
|
|
744
|
+
GITHUB_ACCESS_TOKEN: "${{ env.GITHUB_TOKEN }}"
|
|
745
|
+
|
|
746
|
+
checks:
|
|
747
|
+
production-security:
|
|
748
|
+
type: ai
|
|
749
|
+
ai_model: "${{ env.SECURITY_MODEL }}"
|
|
750
|
+
ai_provider: "${{ env.PREFERRED_AI_PROVIDER }}"
|
|
751
|
+
env:
|
|
752
|
+
API_KEY: "${{ env.ANTHROPIC_KEY }}"
|
|
753
|
+
TIMEOUT: "${{ env.ANALYSIS_TIMEOUT }}"
|
|
754
|
+
prompt: |
|
|
755
|
+
Production security analysis with ${{ env.ANALYSIS_TIMEOUT }}ms timeout
|
|
756
|
+
Using provider: ${{ env.PREFERRED_AI_PROVIDER }}
|
|
757
|
+
Model: ${{ env.SECURITY_MODEL }}
|
|
758
|
+
|
|
759
|
+
Perform comprehensive security analysis...
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
### Built-in Schemas
|
|
763
|
+
|
|
764
|
+
#### Code Review Schema (`code-review`)
|
|
765
|
+
Structured format for code analysis results:
|
|
766
|
+
```json
|
|
767
|
+
{
|
|
768
|
+
"issues": [
|
|
769
|
+
{
|
|
770
|
+
"file": "src/auth.ts",
|
|
771
|
+
"line": 15,
|
|
772
|
+
"ruleId": "security/hardcoded-secret",
|
|
773
|
+
"message": "Hardcoded API key detected",
|
|
774
|
+
"severity": "critical",
|
|
775
|
+
"category": "security",
|
|
776
|
+
"suggestion": "Use environment variables"
|
|
777
|
+
}
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
#### Text Schema (`text`)
|
|
783
|
+
Free-form text/markdown content:
|
|
784
|
+
```json
|
|
785
|
+
{
|
|
786
|
+
"content": "# PR Overview\n\nThis PR adds authentication features..."
|
|
787
|
+
}
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
### Output Templates
|
|
791
|
+
|
|
792
|
+
#### Code Review Template
|
|
793
|
+
Renders structured data as HTML tables with:
|
|
794
|
+
- Grouping by check name
|
|
795
|
+
- Severity indicators with emojis (🔴 🟠 🟡 🟢)
|
|
796
|
+
- Collapsible suggestion details
|
|
797
|
+
- File and line information
|
|
798
|
+
|
|
799
|
+
#### Text Template
|
|
800
|
+
Renders text/markdown content as-is for:
|
|
801
|
+
- PR overviews and summaries
|
|
802
|
+
- Architecture diagrams
|
|
803
|
+
- Custom formatted content
|
|
804
|
+
|
|
805
|
+
### Comment Grouping
|
|
806
|
+
|
|
807
|
+
The `group` property controls GitHub comment generation:
|
|
808
|
+
|
|
809
|
+
```yaml
|
|
810
|
+
checks:
|
|
811
|
+
security:
|
|
812
|
+
group: code-review # \
|
|
813
|
+
performance: # } All grouped in one comment
|
|
814
|
+
group: code-review # /
|
|
815
|
+
|
|
816
|
+
overview:
|
|
817
|
+
group: summary # Separate comment
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
### Custom Schemas and Templates
|
|
821
|
+
|
|
822
|
+
Add custom schemas in your config:
|
|
823
|
+
|
|
824
|
+
```yaml
|
|
825
|
+
schemas:
|
|
826
|
+
custom-metrics:
|
|
827
|
+
file: ./schemas/metrics.json # Local file
|
|
828
|
+
compliance:
|
|
829
|
+
url: https://example.com/compliance.json # Remote URL
|
|
830
|
+
|
|
831
|
+
checks:
|
|
832
|
+
metrics:
|
|
833
|
+
schema: custom-metrics # References custom schema
|
|
834
|
+
group: metrics # Separate comment group
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### Key Features Implemented
|
|
838
|
+
|
|
839
|
+
- ✅ **Check-Based Organization**: Issues grouped by check name, not artificial categories
|
|
840
|
+
- ✅ **Group-Based Comments**: Multiple GitHub comments based on `group` property
|
|
841
|
+
- ✅ **JSON Schema Validation**: Runtime validation with AJV library
|
|
842
|
+
- ✅ **Liquid Templates**: Dynamic rendering with conditional logic
|
|
843
|
+
- ✅ **Multiple Output Formats**: Structured tables vs free-form markdown
|
|
844
|
+
- ✅ **Backwards Compatibility**: Existing configurations continue to work
|
|
845
|
+
- ✅ **No False Categories**: Eliminates "logic" issues when no logic checks configured
|
|
846
|
+
- ✅ **Type Safety**: Structured data validation prevents malformed output
|
|
847
|
+
- ✅ **Extensible Design**: Easy to add custom schemas and templates
|
|
848
|
+
|
|
849
|
+
### Schema and Template Properties
|
|
850
|
+
|
|
851
|
+
The schema-template system introduces two new configuration properties:
|
|
852
|
+
|
|
853
|
+
#### Group Property
|
|
854
|
+
Controls GitHub comment organization:
|
|
855
|
+
```yaml
|
|
856
|
+
checks:
|
|
857
|
+
security:
|
|
858
|
+
group: code-review # Groups with other code-review checks
|
|
859
|
+
performance:
|
|
860
|
+
group: code-review # Same group = combined in one comment
|
|
861
|
+
overview:
|
|
862
|
+
group: pr-summary # Different group = separate comment
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
#### Schema Property
|
|
866
|
+
Enforces structured output format:
|
|
867
|
+
```yaml
|
|
868
|
+
checks:
|
|
869
|
+
security:
|
|
870
|
+
schema: code-review # Structured table format
|
|
871
|
+
prompt: "Return JSON matching code-review schema"
|
|
872
|
+
overview:
|
|
873
|
+
schema: text # Free-form markdown
|
|
874
|
+
prompt: "Return markdown content"
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
#### Benefits
|
|
878
|
+
- **Check-Based Organization**: Only configured checks appear in results
|
|
879
|
+
- **Multiple Comments**: Separate GitHub comments based on `group` property
|
|
880
|
+
- **Structured Output**: JSON Schema validation ensures consistent data
|
|
881
|
+
- **Flexible Rendering**: Different templates for different output types
|
|
882
|
+
|
|
883
|
+
## 🧠 Advanced AI Features
|
|
884
|
+
|
|
885
|
+
### XML-Formatted Analysis
|
|
886
|
+
Visor now uses structured XML formatting when sending data to AI providers, enabling more precise and context-aware analysis:
|
|
887
|
+
|
|
888
|
+
```xml
|
|
889
|
+
<pull_request>
|
|
890
|
+
<metadata>
|
|
891
|
+
<title>Add user authentication</title>
|
|
892
|
+
<author>developer</author>
|
|
893
|
+
<files_changed_count>3</files_changed_count>
|
|
894
|
+
</metadata>
|
|
895
|
+
<description>
|
|
896
|
+
This PR implements JWT-based authentication
|
|
897
|
+
</description>
|
|
898
|
+
<full_diff>
|
|
899
|
+
--- src/auth.ts
|
|
900
|
+
+++ src/auth.ts
|
|
901
|
+
@@ -1,3 +1,10 @@
|
|
902
|
+
+import jwt from 'jsonwebtoken';
|
|
903
|
+
...
|
|
904
|
+
</full_diff>
|
|
905
|
+
</pull_request>
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
### Incremental Commit Analysis
|
|
909
|
+
When new commits are pushed to a PR, Visor performs incremental analysis:
|
|
910
|
+
- **Full Analysis**: Reviews the entire PR on initial creation
|
|
911
|
+
- **Incremental Analysis**: On new commits, focuses only on the latest changes
|
|
912
|
+
- **Smart Updates**: Updates existing review comments instead of creating duplicates
|
|
913
|
+
|
|
914
|
+
### Intelligent Comment Management
|
|
915
|
+
- **Unique Comment IDs**: Each PR gets a unique review comment that persists across updates
|
|
916
|
+
- **Collision Detection**: Prevents conflicts when multiple reviews run simultaneously
|
|
917
|
+
- **Context-Aware Updates**: Comments are updated with relevant context (PR opened, updated, synchronized)
|
|
918
|
+
|
|
919
|
+
## 🔧 Pluggable Architecture
|
|
920
|
+
|
|
921
|
+
Visor features a pluggable provider system for extensibility:
|
|
922
|
+
|
|
923
|
+
### Supported Check Types
|
|
924
|
+
- **AI Provider**: Intelligent analysis using LLMs (Google Gemini, Anthropic Claude, OpenAI GPT)
|
|
925
|
+
- **Tool Provider**: Integration with external tools (ESLint, Prettier, SonarQube)
|
|
926
|
+
- **Script Provider**: Custom shell scripts and commands
|
|
927
|
+
- **Webhook Provider**: External service integration via HTTP calls
|
|
928
|
+
|
|
929
|
+
### Adding Custom Providers
|
|
930
|
+
```typescript
|
|
931
|
+
// Custom provider implementation
|
|
932
|
+
export class CustomCheckProvider extends CheckProvider {
|
|
933
|
+
getName(): string {
|
|
934
|
+
return 'custom-security-scan';
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
async execute(prInfo: PRInfo, config: CheckProviderConfig): Promise<ReviewSummary> {
|
|
938
|
+
// Your custom analysis logic
|
|
939
|
+
return {
|
|
940
|
+
issues: [...],
|
|
941
|
+
suggestions: [...]
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// Register your provider
|
|
947
|
+
CheckProviderRegistry.getInstance().registerProvider(new CustomCheckProvider());
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
## ⚙️ Configuration
|
|
951
|
+
|
|
952
|
+
Create `visor.config.yaml` in your project root:
|
|
953
|
+
|
|
954
|
+
```yaml
|
|
955
|
+
# .visor.yaml
|
|
956
|
+
version: "1.0"
|
|
957
|
+
|
|
958
|
+
# Project metadata
|
|
959
|
+
project:
|
|
960
|
+
name: "My Project"
|
|
961
|
+
description: "My awesome project"
|
|
962
|
+
language: "typescript" # primary language
|
|
963
|
+
frameworks: # frameworks in use
|
|
964
|
+
- "react"
|
|
965
|
+
- "nodejs"
|
|
966
|
+
|
|
967
|
+
# Analysis configuration
|
|
968
|
+
analysis:
|
|
969
|
+
# File patterns to include/exclude
|
|
970
|
+
include:
|
|
971
|
+
- "src/**/*" # Include all files in src
|
|
972
|
+
- "lib/**/*" # Include all files in lib
|
|
973
|
+
exclude:
|
|
974
|
+
- "node_modules/**" # Exclude node_modules
|
|
975
|
+
- "dist/**" # Exclude build output
|
|
976
|
+
- "**/*.test.ts" # Exclude test files
|
|
977
|
+
|
|
978
|
+
# Limits
|
|
979
|
+
maxFileSize: 500000 # Max file size in bytes (500KB)
|
|
980
|
+
maxFiles: 1000 # Max number of files to analyze
|
|
981
|
+
|
|
982
|
+
# Check-specific settings
|
|
983
|
+
checks:
|
|
984
|
+
security:
|
|
985
|
+
enabled: true # Enable/disable this check
|
|
986
|
+
severity: warning # Minimum severity: info, warning, error, critical
|
|
987
|
+
rules: # Specific rules to apply
|
|
988
|
+
- detect-secrets
|
|
989
|
+
- xss-prevention
|
|
990
|
+
- sql-injection
|
|
991
|
+
|
|
992
|
+
performance:
|
|
993
|
+
enabled: true
|
|
994
|
+
severity: info
|
|
995
|
+
rules:
|
|
996
|
+
- complexity-analysis
|
|
997
|
+
- memory-leaks
|
|
998
|
+
- algorithm-efficiency
|
|
999
|
+
depends_on: [security] # Run after security check completes
|
|
1000
|
+
|
|
1001
|
+
style:
|
|
1002
|
+
enabled: true
|
|
1003
|
+
severity: info
|
|
1004
|
+
extends: "eslint:recommended" # Extend from ESLint config
|
|
1005
|
+
rules:
|
|
1006
|
+
- naming-conventions
|
|
1007
|
+
- formatting
|
|
1008
|
+
depends_on: [security] # Ensure secure coding style
|
|
1009
|
+
|
|
1010
|
+
architecture:
|
|
1011
|
+
enabled: true
|
|
1012
|
+
severity: warning
|
|
1013
|
+
rules:
|
|
1014
|
+
- circular-dependencies
|
|
1015
|
+
- design-patterns
|
|
1016
|
+
depends_on: [security, performance] # Build on foundational checks
|
|
1017
|
+
|
|
1018
|
+
# Thresholds for pass/fail
|
|
1019
|
+
thresholds:
|
|
1020
|
+
minScore: 70 # Minimum overall score (0-100)
|
|
1021
|
+
maxIssues: 100 # Maximum total issues
|
|
1022
|
+
maxCriticalIssues: 0 # Maximum critical issues
|
|
1023
|
+
|
|
1024
|
+
# Output settings
|
|
1025
|
+
reporting:
|
|
1026
|
+
format: markdown # Default output format
|
|
1027
|
+
verbose: false # Show detailed output
|
|
1028
|
+
includeFixSuggestions: true # Include fix suggestions
|
|
1029
|
+
groupByFile: true # Group issues by file
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
## 🎯 GitHub Action Reference
|
|
1033
|
+
|
|
1034
|
+
### Inputs
|
|
1035
|
+
|
|
1036
|
+
| Input | Description | Default | Required |
|
|
1037
|
+
|-------|-------------|---------|----------|
|
|
1038
|
+
| `github-token` | GitHub token for API access | `${{ github.token }}` | Yes |
|
|
1039
|
+
| `auto-review` | Auto-review on PR open/update | `true` | No |
|
|
1040
|
+
| `checks` | Checks to run (comma-separated) | `all` | No |
|
|
1041
|
+
| `output-format` | Output format | `markdown` | No |
|
|
1042
|
+
| `config-path` | Path to config file | `visor.config.yaml` | No |
|
|
1043
|
+
| `comment-on-pr` | Post review as PR comment | `true` | No |
|
|
1044
|
+
| `create-check` | Create GitHub check run | `true` | No |
|
|
1045
|
+
| `add-labels` | Add quality labels to PR | `true` | No |
|
|
1046
|
+
| `fail-on-critical` | Fail if critical issues found | `false` | No |
|
|
1047
|
+
| `min-score` | Minimum score to pass (0-100) | `0` | No |
|
|
1048
|
+
|
|
1049
|
+
### Outputs
|
|
1050
|
+
|
|
1051
|
+
| Output | Description |
|
|
1052
|
+
|--------|-------------|
|
|
1053
|
+
| `review-score` | Overall code quality score (0-100) |
|
|
1054
|
+
| `total-issues` | Total number of issues found |
|
|
1055
|
+
| `critical-issues` | Number of critical issues |
|
|
1056
|
+
| `auto-review-completed` | Whether auto-review was completed (true/false) |
|
|
1057
|
+
| `pr-action` | The PR action that triggered the review (opened/synchronize/edited) |
|
|
1058
|
+
| `incremental-analysis` | Whether incremental analysis was used (true/false) |
|
|
1059
|
+
| `issues-found` | Total number of issues found (alias for total-issues) |
|
|
1060
|
+
| `review-url` | URL to the review comment |
|
|
1061
|
+
|
|
1062
|
+
### Example Workflows
|
|
1063
|
+
|
|
1064
|
+
#### Basic Review with Incremental Analysis
|
|
1065
|
+
```yaml
|
|
1066
|
+
name: PR Review
|
|
1067
|
+
on:
|
|
1068
|
+
pull_request:
|
|
1069
|
+
types: [opened, synchronize, edited] # Enable incremental analysis on new commits
|
|
1070
|
+
|
|
1071
|
+
jobs:
|
|
1072
|
+
review:
|
|
1073
|
+
runs-on: ubuntu-latest
|
|
1074
|
+
steps:
|
|
1075
|
+
- uses: actions/checkout@v4
|
|
1076
|
+
- uses: ./
|
|
1077
|
+
with:
|
|
1078
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
1079
|
+
auto-review: true # Enable automatic review
|
|
1080
|
+
env:
|
|
1081
|
+
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
|
1082
|
+
MODEL_NAME: gemini-2.0-flash-exp
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
#### Security Focus with SARIF Upload
|
|
1086
|
+
```yaml
|
|
1087
|
+
name: Security Scan
|
|
1088
|
+
on: [push, pull_request]
|
|
1089
|
+
|
|
1090
|
+
jobs:
|
|
1091
|
+
security:
|
|
1092
|
+
runs-on: ubuntu-latest
|
|
1093
|
+
steps:
|
|
1094
|
+
- uses: actions/checkout@v4
|
|
1095
|
+
- name: Run Visor Security Scan
|
|
1096
|
+
uses: ./
|
|
1097
|
+
with:
|
|
1098
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
1099
|
+
checks: security
|
|
1100
|
+
output-format: sarif
|
|
1101
|
+
|
|
1102
|
+
- name: Upload SARIF
|
|
1103
|
+
uses: github/codeql-action/upload-sarif@v2
|
|
1104
|
+
if: always()
|
|
1105
|
+
with:
|
|
1106
|
+
sarif_file: visor-results.sarif
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
#### Quality Gate
|
|
1110
|
+
```yaml
|
|
1111
|
+
name: Quality Gate
|
|
1112
|
+
on: pull_request
|
|
1113
|
+
|
|
1114
|
+
jobs:
|
|
1115
|
+
quality:
|
|
1116
|
+
runs-on: ubuntu-latest
|
|
1117
|
+
steps:
|
|
1118
|
+
- uses: actions/checkout@v4
|
|
1119
|
+
- uses: ./
|
|
1120
|
+
with:
|
|
1121
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
1122
|
+
min-score: 80
|
|
1123
|
+
fail-on-critical: true
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
#### Command-Triggered Review
|
|
1127
|
+
```yaml
|
|
1128
|
+
name: Manual Review
|
|
1129
|
+
on:
|
|
1130
|
+
issue_comment:
|
|
1131
|
+
types: [created]
|
|
1132
|
+
|
|
1133
|
+
jobs:
|
|
1134
|
+
review:
|
|
1135
|
+
if: |
|
|
1136
|
+
github.event.issue.pull_request &&
|
|
1137
|
+
startsWith(github.event.comment.body, '/review')
|
|
1138
|
+
runs-on: ubuntu-latest
|
|
1139
|
+
steps:
|
|
1140
|
+
- uses: actions/checkout@v4
|
|
1141
|
+
- uses: ./
|
|
1142
|
+
with:
|
|
1143
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
## 📊 Output Formats
|
|
1147
|
+
|
|
1148
|
+
### Table (Default)
|
|
1149
|
+
```
|
|
1150
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
1151
|
+
║ Analysis Summary ║
|
|
1152
|
+
╠════════════════════════════════════════════════════════════════╣
|
|
1153
|
+
║ Overall Score: 85/100 Issues Found: 12 ║
|
|
1154
|
+
╟────────────────────────────────────────────────────────────────╢
|
|
1155
|
+
║ ✓ Security: 92/100 ⚠ Performance: 78/100 ║
|
|
1156
|
+
║ ✓ Style: 88/100 ✓ Architecture: 82/100 ║
|
|
1157
|
+
╚════════════════════════════════════════════════════════════════╝
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
### JSON
|
|
1161
|
+
```json
|
|
1162
|
+
{
|
|
1163
|
+
"summary": {
|
|
1164
|
+
"overallScore": 85,
|
|
1165
|
+
"totalIssues": 12,
|
|
1166
|
+
"criticalIssues": 1
|
|
1167
|
+
},
|
|
1168
|
+
"issues": [
|
|
1169
|
+
{
|
|
1170
|
+
"file": "src/api.ts",
|
|
1171
|
+
"line": 45,
|
|
1172
|
+
"severity": "critical",
|
|
1173
|
+
"category": "security",
|
|
1174
|
+
"message": "Potential SQL injection"
|
|
1175
|
+
}
|
|
1176
|
+
]
|
|
1177
|
+
}
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
### SARIF
|
|
1181
|
+
Compatible with GitHub Security tab and other SARIF consumers.
|
|
1182
|
+
|
|
1183
|
+
## 🛠️ Development
|
|
1184
|
+
|
|
1185
|
+
### Setup
|
|
1186
|
+
```bash
|
|
1187
|
+
# Clone and install
|
|
1188
|
+
git clone https://github.com/your-org/visor.git
|
|
1189
|
+
cd visor
|
|
1190
|
+
npm install
|
|
1191
|
+
|
|
1192
|
+
# Build
|
|
1193
|
+
npm run build
|
|
1194
|
+
|
|
1195
|
+
# Test
|
|
1196
|
+
npm test
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
### Project Structure
|
|
1200
|
+
```
|
|
1201
|
+
visor/
|
|
1202
|
+
├── src/
|
|
1203
|
+
│ ├── cli-main.ts # CLI entry point
|
|
1204
|
+
│ ├── index.ts # GitHub Action entry
|
|
1205
|
+
│ ├── reviewer.ts # Core review logic
|
|
1206
|
+
│ └── output-formatters.ts # Output formatting
|
|
1207
|
+
├── tests/ # Test suites
|
|
1208
|
+
├── .github/workflows/ # GitHub workflows
|
|
1209
|
+
├── action.yml # Action metadata
|
|
1210
|
+
└── visor.config.yaml # Default config
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
### Available Scripts
|
|
1214
|
+
|
|
1215
|
+
| Command | Description |
|
|
1216
|
+
|---------|-------------|
|
|
1217
|
+
| `npm run build` | Build TypeScript |
|
|
1218
|
+
| `npm test` | Run tests |
|
|
1219
|
+
| `npm run test:watch` | Test watch mode |
|
|
1220
|
+
| `npm run test:coverage` | Coverage report |
|
|
1221
|
+
|
|
1222
|
+
## 🤝 Contributing
|
|
1223
|
+
|
|
1224
|
+
Contributions welcome! Please:
|
|
1225
|
+
|
|
1226
|
+
1. Fork the repository
|
|
1227
|
+
2. Create a feature branch
|
|
1228
|
+
3. Make your changes
|
|
1229
|
+
4. Add tests
|
|
1230
|
+
5. Submit a PR
|
|
1231
|
+
|
|
1232
|
+
## 📄 License
|
|
1233
|
+
|
|
1234
|
+
MIT License - see [LICENSE](LICENSE) file
|
|
1235
|
+
|
|
1236
|
+
---
|
|
1237
|
+
|
|
1238
|
+
<div align="center">
|
|
1239
|
+
Made with ❤️ by <a href="https://probelabs.com">Probe Labs</a>
|
|
1240
|
+
</div>
|