repopilot 0.8.0 → 0.10.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 +88 -34
- package/package.json +5 -3
- package/scripts/smoke-product.sh +266 -0
- package/scripts/verify-release.sh +48 -12
package/README.md
CHANGED
|
@@ -7,9 +7,17 @@
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://github.com/MykytaStel/repopilot)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Audit your repository locally, turn the results into AI-ready remediation context,
|
|
11
|
+
and ship safer changes without sending source code to a hosted scanner.
|
|
11
12
|
|
|
12
|
-
RepoPilot is a local-first CLI
|
|
13
|
+
RepoPilot is a local-first CLI for architecture, security, code quality, testing,
|
|
14
|
+
and framework health checks. It gives developers useful terminal reports, CI gates,
|
|
15
|
+
SARIF for GitHub Code Scanning, and Markdown briefs that can be pasted into Claude
|
|
16
|
+
Code, ChatGPT, Cursor, or another coding assistant.
|
|
17
|
+
|
|
18
|
+
Version `0.10.0` is an adoption and stability release: it focuses on cleaner
|
|
19
|
+
rollout diagnostics, reproducible audit receipts, CI artifacts, and 0.x command
|
|
20
|
+
compatibility while keeping all scans local.
|
|
13
21
|
|
|
14
22
|
## Why RepoPilot?
|
|
15
23
|
|
|
@@ -25,38 +33,40 @@ Most linters and audit tools stop at the terminal. RepoPilot bridges the gap to
|
|
|
25
33
|
| CI gate on new findings only | ✅ | partial | ✅ |
|
|
26
34
|
|
|
27
35
|
```bash
|
|
28
|
-
repopilot
|
|
36
|
+
repopilot ai context . | pbcopy # macOS: paste into your coding assistant
|
|
29
37
|
```
|
|
30
38
|
|
|
31
39
|
## Features
|
|
32
40
|
|
|
33
41
|
- Repository scanning for projects, folders, and individual files
|
|
34
42
|
- Gitignore-aware walking with built-in ignores for common build, cache, vendor, and native platform directories
|
|
35
|
-
- Architecture findings: oversized files, deep nesting, too many modules per directory
|
|
43
|
+
- Architecture findings: oversized files, deep nesting, deep relative imports, risky barrel files, too many modules per directory
|
|
36
44
|
- Coupling analysis: excessive fan-out, high-instability hubs, circular dependencies
|
|
37
45
|
- Code quality findings: cyclomatic complexity density, long functions, TODO/FIXME/HACK markers
|
|
38
46
|
- Security findings: hardcoded secret candidates, committed private keys, committed `.env` files
|
|
39
47
|
- Testing findings: missing test folder, source files without test counterparts
|
|
40
|
-
- Framework findings for JavaScript, React, React Native, and
|
|
48
|
+
- Framework findings for JavaScript, React, React Native, Expo, and Django projects
|
|
41
49
|
- React Native architecture profile: project kind, New Architecture, Hermes, Codegen, platform mismatch, and package manager signals
|
|
42
50
|
- Workspace scanning (`--workspace`) for npm, yarn, pnpm, and Cargo workspaces with per-package risk summary — parallel per-package scans
|
|
43
51
|
- Evidence-backed findings with stable rule IDs, severity, file paths, line numbers, and snippets
|
|
44
|
-
-
|
|
52
|
+
- 46 built-in rules with titles, descriptions, recommendations, and docs links
|
|
45
53
|
- `repopilot.toml` configuration generated by `repopilot init`
|
|
46
54
|
- Configuration presets (`--preset strict|balanced|lenient`) for quick threshold tuning
|
|
47
55
|
- Baseline workflow for accepting existing findings in legacy repositories
|
|
48
56
|
- CI-friendly failure thresholds with `--fail-on`
|
|
49
57
|
- Git diff-aware review mode for prioritizing findings introduced by changed lines
|
|
58
|
+
- Doctor adoption guidance for config, baseline, CI gate, report, and receipt readiness
|
|
59
|
+
- Audit receipt JSON from `repopilot scan --receipt` for reproducible scan evidence
|
|
50
60
|
- Console, JSON, Markdown, HTML, and SARIF (2.1.0) scan output — SARIF includes per-result category and workspace package properties
|
|
51
|
-
- First-party GitHub Action wrapper for `scan`, `review`, `compare`,
|
|
61
|
+
- First-party GitHub Action wrapper for `scan`, `review`, `compare`, and `ai` workflows, with optional SARIF upload and receipt output for scans
|
|
52
62
|
- Compare mode for diffing two JSON scan reports
|
|
53
|
-
- **`repopilot
|
|
54
|
-
- **`repopilot
|
|
55
|
-
- **`repopilot prompt`** —
|
|
63
|
+
- **`repopilot ai context`** — formats scan output as LLM-ready markdown, paste into Claude Code or ChatGPT to start remediating
|
|
64
|
+
- **`repopilot ai plan`** — turns findings into a prioritized remediation plan
|
|
65
|
+
- **`repopilot ai prompt`** — exports an AI-ready remediation prompt with RepoPilot context
|
|
56
66
|
|
|
57
67
|
See [docs/rulesets.md](docs/rulesets.md) for the full list of rules and severity levels.
|
|
58
68
|
|
|
59
|
-
##
|
|
69
|
+
## Install
|
|
60
70
|
|
|
61
71
|
```bash
|
|
62
72
|
cargo install repopilot
|
|
@@ -71,20 +81,24 @@ npm install -g repopilot
|
|
|
71
81
|
Install with Homebrew:
|
|
72
82
|
|
|
73
83
|
```bash
|
|
74
|
-
brew
|
|
84
|
+
brew tap mykytastel/repopilot
|
|
85
|
+
brew install repopilot
|
|
75
86
|
```
|
|
76
87
|
|
|
77
88
|
Install with curl (Linux/macOS):
|
|
78
89
|
|
|
79
90
|
```bash
|
|
80
|
-
curl -fsSL https://raw.githubusercontent.com/MykytaStel/repopilot/main/install.sh |
|
|
91
|
+
curl -fsSL https://raw.githubusercontent.com/MykytaStel/repopilot/main/install.sh | bash
|
|
81
92
|
```
|
|
82
93
|
|
|
94
|
+
The curl installer verifies the GitHub Release SHA256 checksum and aborts if the checksum cannot be downloaded or verified.
|
|
95
|
+
|
|
83
96
|
Upgrade:
|
|
84
97
|
|
|
85
98
|
```bash
|
|
86
99
|
cargo install repopilot --force
|
|
87
100
|
npm update -g repopilot
|
|
101
|
+
brew update && brew upgrade repopilot
|
|
88
102
|
```
|
|
89
103
|
|
|
90
104
|
Build from source:
|
|
@@ -97,16 +111,36 @@ cargo build --release
|
|
|
97
111
|
|
|
98
112
|
## Quick Start
|
|
99
113
|
|
|
114
|
+
No config needed. Run this in any repository and see findings immediately:
|
|
115
|
+
|
|
100
116
|
```bash
|
|
101
|
-
repopilot init
|
|
102
117
|
repopilot scan .
|
|
103
118
|
```
|
|
104
119
|
|
|
105
|
-
|
|
120
|
+
Then get an AI-ready brief to paste into Claude Code, Cursor, or ChatGPT:
|
|
106
121
|
|
|
107
122
|
```bash
|
|
108
|
-
repopilot
|
|
109
|
-
repopilot
|
|
123
|
+
repopilot ai context . | pbcopy # macOS — copies to clipboard
|
|
124
|
+
repopilot ai context . # print to terminal
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
That's the two-minute loop. Scan, read the output, paste the context into your assistant, fix.
|
|
128
|
+
|
|
129
|
+
### Going deeper
|
|
130
|
+
|
|
131
|
+
Once you want CI integration, baseline tracking, or tighter configuration:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
repopilot init # generate repopilot.toml
|
|
135
|
+
repopilot doctor . # check CI / baseline readiness
|
|
136
|
+
repopilot baseline create . # accept existing findings as known debt
|
|
137
|
+
repopilot review . --base origin/main --fail-on new-high # CI gate on new findings only
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Save a shareable report:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
repopilot scan . --format markdown --output repopilot-report.md --receipt .repopilot/receipt.json
|
|
110
144
|
```
|
|
111
145
|
|
|
112
146
|
Reduce scan noise while iterating:
|
|
@@ -119,28 +153,31 @@ repopilot scan . --exclude fixtures --max-file-size 1mb --max-files 500
|
|
|
119
153
|
|
|
120
154
|
By default, RepoPilot skips low-signal audit paths such as tests, fixtures, examples, generated files, and benchmarks. Use `--include-low-signal` when you want those paths analyzed too.
|
|
121
155
|
|
|
122
|
-
##
|
|
156
|
+
## Local-First AI Workflow
|
|
123
157
|
|
|
124
|
-
|
|
158
|
+
RepoPilot does not call LLM APIs. AI commands scan local files and produce Markdown
|
|
159
|
+
that you decide where to paste.
|
|
160
|
+
|
|
161
|
+
`repopilot ai context` scans a project and formats all findings as structured markdown ready to paste into Claude Code, Cursor, ChatGPT, or any LLM assistant. It includes a risk level, tech stack summary, findings grouped by category with evidence snippets and fix recommendations, and a token-count estimate.
|
|
125
162
|
|
|
126
163
|
```bash
|
|
127
164
|
# Paste into Claude Code or ChatGPT
|
|
128
|
-
repopilot
|
|
165
|
+
repopilot ai context .
|
|
129
166
|
|
|
130
167
|
# Focus on security only, keep it short
|
|
131
|
-
repopilot
|
|
168
|
+
repopilot ai context . --focus security --budget 2k
|
|
132
169
|
|
|
133
170
|
# Save to file
|
|
134
|
-
repopilot
|
|
171
|
+
repopilot ai context . --output repopilot-context.md
|
|
135
172
|
|
|
136
173
|
# Pipe directly into clipboard (macOS)
|
|
137
|
-
repopilot
|
|
174
|
+
repopilot ai context . --no-header | pbcopy
|
|
138
175
|
```
|
|
139
176
|
|
|
140
177
|
## Example Output
|
|
141
178
|
|
|
142
179
|
```
|
|
143
|
-
$ repopilot
|
|
180
|
+
$ repopilot ai context .
|
|
144
181
|
|
|
145
182
|
# RepoPilot Vibe Check — my-app
|
|
146
183
|
|
|
@@ -168,16 +205,18 @@ $ repopilot vibe .
|
|
|
168
205
|
*~3.8k tokens (budget: 4k) · scanned in 312ms — paste into Claude Code, Cursor, or ChatGPT*
|
|
169
206
|
```
|
|
170
207
|
|
|
171
|
-
Paste this into
|
|
208
|
+
Paste this into a coding assistant and ask for a focused patch. For larger
|
|
209
|
+
repositories, start with one focus area instead of asking for every finding at
|
|
210
|
+
once.
|
|
172
211
|
|
|
173
|
-
##
|
|
212
|
+
## Recommended Remediation Loop
|
|
174
213
|
|
|
175
214
|
RepoPilot is a local-first safety layer for AI-assisted and vibe-coded changes. Run it after generating or refactoring code to catch newly introduced high-risk findings, workspace hotspots, missing tests, and architecture drift without uploading source code to an external service.
|
|
176
215
|
|
|
177
216
|
```bash
|
|
178
|
-
repopilot
|
|
179
|
-
repopilot
|
|
180
|
-
repopilot prompt . --budget 8k
|
|
217
|
+
repopilot ai context . --focus security # get an LLM brief for Claude Code
|
|
218
|
+
repopilot ai plan . --focus security # get a prioritized hardening plan
|
|
219
|
+
repopilot ai prompt . --budget 8k # generate a paste-ready remediation prompt
|
|
181
220
|
repopilot review . --base origin/main --baseline .repopilot/baseline.json --fail-on new-high
|
|
182
221
|
repopilot scan . --workspace --min-severity medium --format markdown --output repopilot-report.md
|
|
183
222
|
```
|
|
@@ -186,13 +225,14 @@ repopilot scan . --workspace --min-severity medium --format markdown --output re
|
|
|
186
225
|
|
|
187
226
|
| Command | Alias | Description |
|
|
188
227
|
|---------|-------|-------------|
|
|
189
|
-
| `repopilot vibe <path>` | `v` | **New in v0.8** — LLM-ready context from a scan |
|
|
190
|
-
| `repopilot harden <path>` | `h` | **New in v0.8** — prioritized remediation plan |
|
|
191
|
-
| `repopilot prompt <path>` | `p` | **New in v0.8** — AI-ready remediation prompt |
|
|
192
228
|
| `repopilot scan <path>` | `s` | Scan a project, folder, or file for findings |
|
|
193
229
|
| `repopilot review [path]` | `r` | Review findings that touch changed Git diff lines |
|
|
230
|
+
| `repopilot ai context <path>` | — | LLM-ready context from a scan |
|
|
231
|
+
| `repopilot ai plan <path>` | — | Prioritized remediation plan |
|
|
232
|
+
| `repopilot ai prompt <path>` | — | AI-ready remediation prompt |
|
|
194
233
|
| `repopilot compare <before> <after>` | `cmp` | Compare two JSON scan reports and show what changed |
|
|
195
234
|
| `repopilot baseline create <path>` | `bl` | Scan a path and store current findings as accepted debt |
|
|
235
|
+
| `repopilot doctor [path]` | `d` | Diagnose audit readiness |
|
|
196
236
|
| `repopilot init` | — | Generate a default `repopilot.toml` configuration file |
|
|
197
237
|
|
|
198
238
|
Use `--help` on any command for the full description and examples:
|
|
@@ -342,6 +382,7 @@ repopilot scan . --format sarif > repopilot.sarif
|
|
|
342
382
|
```
|
|
343
383
|
|
|
344
384
|
Use JSON when custom scripts need to parse RepoPilot results. Console, Markdown, and HTML reports include the RepoPilot version, risk summary, top rules, and grouped findings for human review. Use SARIF for CI and code scanning integrations, including GitHub Code Scanning.
|
|
385
|
+
Use `--receipt <path>` with `scan` when CI or release processes need compact evidence of the exact RepoPilot version, git state, scan scope, finding counts, language counts, and health score.
|
|
345
386
|
|
|
346
387
|
See [docs/integrations/github-code-scanning.md](docs/integrations/github-code-scanning.md) for a copy-paste GitHub Actions workflow, required permissions, and local validation commands.
|
|
347
388
|
|
|
@@ -362,7 +403,7 @@ Use `--fail-on new-high` to fail CI only when new high or critical findings are
|
|
|
362
403
|
When `--fail-on new-*` is used without `--baseline`, RepoPilot treats all current findings as new. For baseline-based adoption, commit an accepted baseline and scan against it in CI.
|
|
363
404
|
|
|
364
405
|
To upload RepoPilot findings to GitHub Code Scanning, generate SARIF and use `github/codeql-action/upload-sarif`. The workflow must include `security-events: write`.
|
|
365
|
-
The first-party action can also run `command:
|
|
406
|
+
The first-party action can also run `command: ai-context`, `command: ai-plan`, or `command: ai-prompt`; those commands emit Markdown and do not produce SARIF. Prefer typed action inputs such as `path`, `config`, `baseline`, `fail-on`, `focus`, `budget`, `output`, and `receipt`; `args` remains available for advanced flags.
|
|
366
407
|
|
|
367
408
|
```yaml
|
|
368
409
|
name: RepoPilot
|
|
@@ -388,7 +429,7 @@ jobs:
|
|
|
388
429
|
run: cargo install repopilot
|
|
389
430
|
|
|
390
431
|
- name: Run RepoPilot
|
|
391
|
-
run: repopilot scan . --baseline .repopilot/baseline.json --fail-on new-high
|
|
432
|
+
run: repopilot scan . --baseline .repopilot/baseline.json --fail-on new-high --receipt repopilot-receipt.json
|
|
392
433
|
|
|
393
434
|
- name: Run RepoPilot (SARIF)
|
|
394
435
|
run: repopilot scan . --format sarif --output repopilot.sarif
|
|
@@ -398,6 +439,13 @@ jobs:
|
|
|
398
439
|
if: always()
|
|
399
440
|
with:
|
|
400
441
|
sarif_file: repopilot.sarif
|
|
442
|
+
|
|
443
|
+
- name: Upload audit receipt
|
|
444
|
+
uses: actions/upload-artifact@v4
|
|
445
|
+
if: always()
|
|
446
|
+
with:
|
|
447
|
+
name: repopilot-receipt
|
|
448
|
+
path: repopilot-receipt.json
|
|
401
449
|
```
|
|
402
450
|
|
|
403
451
|
## Roadmap
|
|
@@ -412,12 +460,18 @@ These are planned ideas, not current features:
|
|
|
412
460
|
|
|
413
461
|
| Document | Description |
|
|
414
462
|
|---|---|
|
|
463
|
+
| [docs/install.md](docs/install.md) | Installation options for Cargo, npm, Homebrew, curl, and source builds |
|
|
464
|
+
| [docs/ai-workflows.md](docs/ai-workflows.md) | Claude Code, ChatGPT, Cursor, and AI remediation workflows |
|
|
465
|
+
| [docs/security.md](docs/security.md) | Local-first trust model, installer security, and vulnerability reporting |
|
|
466
|
+
| [docs/configuration.md](docs/configuration.md) | `repopilot.toml`, presets, ignore files, and baseline adoption |
|
|
467
|
+
| [docs/language-support.md](docs/language-support.md) | Supported language/framework tiers, rule families, and limitations |
|
|
415
468
|
| [docs/cli.md](docs/cli.md) | Complete CLI reference — all commands, flags, and exit codes |
|
|
416
469
|
| [docs/commands.md](docs/commands.md) | Task-oriented command guide and common patterns |
|
|
417
470
|
| [docs/rulesets.md](docs/rulesets.md) | Implemented audit rules, categories, and severity levels |
|
|
418
471
|
| [docs/react-native.md](docs/react-native.md) | React Native and Expo detection, findings, and limitations |
|
|
419
472
|
| [docs/integrations/github-code-scanning.md](docs/integrations/github-code-scanning.md) | GitHub Code Scanning SARIF workflow |
|
|
420
473
|
| [docs/release.md](docs/release.md) | Manual release process |
|
|
474
|
+
| [docs/release-checklist-0.10.md](docs/release-checklist-0.10.md) | 0.10.0 release readiness checklist |
|
|
421
475
|
| [docs/distribution.md](docs/distribution.md) | Distribution channels |
|
|
422
476
|
| [docs/github-ruleset.md](docs/github-ruleset.md) | GitHub branch ruleset configuration |
|
|
423
477
|
| [CHANGELOG.md](CHANGELOG.md) | Version history |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repopilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Local-first CLI for repository audit, architecture risk detection, baseline tracking, and CI-friendly code review.",
|
|
5
5
|
"license": "MIT OR Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"postinstall": "node scripts/install.js",
|
|
19
|
+
"test": "npm run test:npm",
|
|
19
20
|
"test:npm": "node --test tests/npm_wrapper.test.js",
|
|
20
|
-
"release:check": "bash scripts/verify-release.sh"
|
|
21
|
+
"release:check": "bash scripts/verify-release.sh",
|
|
22
|
+
"product:smoke": "bash scripts/smoke-product.sh"
|
|
21
23
|
},
|
|
22
24
|
"files": [
|
|
23
25
|
"bin",
|
|
@@ -36,4 +38,4 @@
|
|
|
36
38
|
"engines": {
|
|
37
39
|
"node": ">=18"
|
|
38
40
|
}
|
|
39
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
|
|
6
|
+
BINARY=""
|
|
7
|
+
REPO_PATH="$ROOT_DIR"
|
|
8
|
+
TMP_DIR=""
|
|
9
|
+
TMP_CREATED=0
|
|
10
|
+
KEEP_TMP=0
|
|
11
|
+
RUN_LEGACY=1
|
|
12
|
+
|
|
13
|
+
usage() {
|
|
14
|
+
cat <<'EOF'
|
|
15
|
+
Usage: scripts/smoke-product.sh [OPTIONS]
|
|
16
|
+
|
|
17
|
+
Run product-readiness smoke checks against RepoPilot.
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--binary PATH Use an already built repopilot binary.
|
|
21
|
+
--repo PATH Repository or project path to smoke test. Defaults to this repo.
|
|
22
|
+
--tmp-dir PATH Directory for generated smoke artifacts. Defaults to mktemp.
|
|
23
|
+
--keep-tmp Keep generated smoke artifacts when using a temporary directory.
|
|
24
|
+
--skip-legacy Skip hidden 0.x compatibility command checks.
|
|
25
|
+
-h, --help Show this help message.
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
scripts/smoke-product.sh
|
|
29
|
+
scripts/smoke-product.sh --binary ./target/release/repopilot
|
|
30
|
+
scripts/smoke-product.sh --repo /path/to/project --keep-tmp
|
|
31
|
+
EOF
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
while [[ $# -gt 0 ]]; do
|
|
35
|
+
case "$1" in
|
|
36
|
+
--binary)
|
|
37
|
+
BINARY="${2:-}"
|
|
38
|
+
shift 2
|
|
39
|
+
;;
|
|
40
|
+
--repo)
|
|
41
|
+
REPO_PATH="${2:-}"
|
|
42
|
+
shift 2
|
|
43
|
+
;;
|
|
44
|
+
--tmp-dir)
|
|
45
|
+
TMP_DIR="${2:-}"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
--keep-tmp)
|
|
49
|
+
KEEP_TMP=1
|
|
50
|
+
shift
|
|
51
|
+
;;
|
|
52
|
+
--skip-legacy)
|
|
53
|
+
RUN_LEGACY=0
|
|
54
|
+
shift
|
|
55
|
+
;;
|
|
56
|
+
-h|--help)
|
|
57
|
+
usage
|
|
58
|
+
exit 0
|
|
59
|
+
;;
|
|
60
|
+
*)
|
|
61
|
+
echo "Unknown argument: $1" >&2
|
|
62
|
+
usage >&2
|
|
63
|
+
exit 2
|
|
64
|
+
;;
|
|
65
|
+
esac
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
if [[ -z "$REPO_PATH" ]]; then
|
|
69
|
+
echo "--repo cannot be empty" >&2
|
|
70
|
+
exit 2
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
REPO_PATH="$(cd "$REPO_PATH" && pwd)"
|
|
74
|
+
|
|
75
|
+
if [[ -z "$BINARY" ]]; then
|
|
76
|
+
if [[ ! -x "$ROOT_DIR/target/debug/repopilot" ]]; then
|
|
77
|
+
echo "==> Building debug binary for product smoke checks" >&2
|
|
78
|
+
cargo build --manifest-path "$ROOT_DIR/Cargo.toml"
|
|
79
|
+
fi
|
|
80
|
+
BINARY="$ROOT_DIR/target/debug/repopilot"
|
|
81
|
+
else
|
|
82
|
+
case "$BINARY" in
|
|
83
|
+
/*) ;;
|
|
84
|
+
*)
|
|
85
|
+
BINARY="$(cd "$(dirname "$BINARY")" && pwd)/$(basename "$BINARY")"
|
|
86
|
+
;;
|
|
87
|
+
esac
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if [[ ! -x "$BINARY" ]]; then
|
|
91
|
+
echo "RepoPilot binary is not executable: $BINARY" >&2
|
|
92
|
+
exit 3
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
if [[ -z "$TMP_DIR" ]]; then
|
|
96
|
+
TMP_DIR="$(mktemp -d)"
|
|
97
|
+
TMP_CREATED=1
|
|
98
|
+
else
|
|
99
|
+
rm -rf "$TMP_DIR"
|
|
100
|
+
mkdir -p "$TMP_DIR"
|
|
101
|
+
TMP_DIR="$(cd "$TMP_DIR" && pwd)"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
cleanup() {
|
|
105
|
+
if [[ "$TMP_CREATED" -eq 1 && "$KEEP_TMP" -eq 0 ]]; then
|
|
106
|
+
rm -rf "$TMP_DIR"
|
|
107
|
+
fi
|
|
108
|
+
}
|
|
109
|
+
trap cleanup EXIT
|
|
110
|
+
|
|
111
|
+
run_repopilot() {
|
|
112
|
+
echo "==> repopilot $*" >&2
|
|
113
|
+
(
|
|
114
|
+
cd "$REPO_PATH"
|
|
115
|
+
"$BINARY" "$@"
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
assert_non_empty() {
|
|
120
|
+
local file="$1"
|
|
121
|
+
if [[ ! -s "$file" ]]; then
|
|
122
|
+
echo "Expected non-empty file: $file" >&2
|
|
123
|
+
exit 3
|
|
124
|
+
fi
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
assert_contains() {
|
|
128
|
+
local file="$1"
|
|
129
|
+
local expected="$2"
|
|
130
|
+
|
|
131
|
+
if ! grep -Fq "$expected" "$file"; then
|
|
132
|
+
echo "Expected '$file' to contain: $expected" >&2
|
|
133
|
+
echo "---- file content ----" >&2
|
|
134
|
+
cat "$file" >&2 || true
|
|
135
|
+
echo "----------------------" >&2
|
|
136
|
+
exit 3
|
|
137
|
+
fi
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
validate_json_if_possible() {
|
|
141
|
+
local file="$1"
|
|
142
|
+
|
|
143
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
144
|
+
python3 -m json.tool "$file" >/dev/null
|
|
145
|
+
fi
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
find_explain_file() {
|
|
149
|
+
local preferred="$REPO_PATH/src/main.rs"
|
|
150
|
+
|
|
151
|
+
if [[ -f "$preferred" ]]; then
|
|
152
|
+
printf '%s\n' "$preferred"
|
|
153
|
+
return 0
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
local discovered=""
|
|
157
|
+
while IFS= read -r candidate; do
|
|
158
|
+
discovered="$candidate"
|
|
159
|
+
break
|
|
160
|
+
done < <(
|
|
161
|
+
find "$REPO_PATH" \
|
|
162
|
+
-path "$REPO_PATH/.git" -prune -o \
|
|
163
|
+
-path "$REPO_PATH/target" -prune -o \
|
|
164
|
+
-path "$REPO_PATH/node_modules" -prune -o \
|
|
165
|
+
-type f \( \
|
|
166
|
+
-name '*.rs' -o \
|
|
167
|
+
-name '*.ts' -o \
|
|
168
|
+
-name '*.tsx' -o \
|
|
169
|
+
-name '*.js' -o \
|
|
170
|
+
-name '*.jsx' -o \
|
|
171
|
+
-name '*.py' -o \
|
|
172
|
+
-name '*.go' \
|
|
173
|
+
\) \
|
|
174
|
+
-print
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if [[ -n "$discovered" && -f "$discovered" ]]; then
|
|
178
|
+
printf '%s\n' "$discovered"
|
|
179
|
+
return 0
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
printf '%s\n' "$REPO_PATH/Cargo.toml"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
EXPLAIN_FILE="$(find_explain_file)"
|
|
186
|
+
|
|
187
|
+
echo "==> RepoPilot product smoke suite"
|
|
188
|
+
echo "Binary: $BINARY"
|
|
189
|
+
echo "Repo: $REPO_PATH"
|
|
190
|
+
echo "Tmp: $TMP_DIR"
|
|
191
|
+
echo
|
|
192
|
+
|
|
193
|
+
run_repopilot --version > "$TMP_DIR/version.txt"
|
|
194
|
+
assert_non_empty "$TMP_DIR/version.txt"
|
|
195
|
+
|
|
196
|
+
run_repopilot --help > "$TMP_DIR/help.txt"
|
|
197
|
+
assert_non_empty "$TMP_DIR/help.txt"
|
|
198
|
+
assert_contains "$TMP_DIR/help.txt" "scan"
|
|
199
|
+
assert_contains "$TMP_DIR/help.txt" "review"
|
|
200
|
+
assert_contains "$TMP_DIR/help.txt" "ai"
|
|
201
|
+
assert_contains "$TMP_DIR/help.txt" "inspect"
|
|
202
|
+
|
|
203
|
+
run_repopilot init --force --path "$TMP_DIR/repopilot.toml"
|
|
204
|
+
assert_non_empty "$TMP_DIR/repopilot.toml"
|
|
205
|
+
|
|
206
|
+
run_repopilot doctor . --format markdown --output "$TMP_DIR/doctor.md"
|
|
207
|
+
assert_non_empty "$TMP_DIR/doctor.md"
|
|
208
|
+
|
|
209
|
+
run_repopilot scan . --format json --output "$TMP_DIR/scan.json" --receipt "$TMP_DIR/receipt.json"
|
|
210
|
+
assert_non_empty "$TMP_DIR/scan.json"
|
|
211
|
+
validate_json_if_possible "$TMP_DIR/scan.json"
|
|
212
|
+
assert_non_empty "$TMP_DIR/receipt.json"
|
|
213
|
+
validate_json_if_possible "$TMP_DIR/receipt.json"
|
|
214
|
+
|
|
215
|
+
run_repopilot scan . --format markdown --output "$TMP_DIR/scan.md"
|
|
216
|
+
assert_non_empty "$TMP_DIR/scan.md"
|
|
217
|
+
|
|
218
|
+
if git -C "$REPO_PATH" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
219
|
+
run_repopilot review . --format markdown --output "$TMP_DIR/review.md"
|
|
220
|
+
assert_non_empty "$TMP_DIR/review.md"
|
|
221
|
+
else
|
|
222
|
+
echo "==> Skipping review smoke check because repo path is not inside a Git worktree" >&2
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
run_repopilot ai context . --focus security --budget 2k --output "$TMP_DIR/ai-context.md"
|
|
226
|
+
assert_non_empty "$TMP_DIR/ai-context.md"
|
|
227
|
+
|
|
228
|
+
run_repopilot ai plan . --focus all --budget 2k --output "$TMP_DIR/ai-plan.md"
|
|
229
|
+
assert_non_empty "$TMP_DIR/ai-plan.md"
|
|
230
|
+
|
|
231
|
+
run_repopilot ai prompt . --focus quality --budget 2k --output "$TMP_DIR/ai-prompt.md"
|
|
232
|
+
assert_non_empty "$TMP_DIR/ai-prompt.md"
|
|
233
|
+
|
|
234
|
+
run_repopilot inspect knowledge --format json --output "$TMP_DIR/inspect-knowledge.json"
|
|
235
|
+
assert_non_empty "$TMP_DIR/inspect-knowledge.json"
|
|
236
|
+
validate_json_if_possible "$TMP_DIR/inspect-knowledge.json"
|
|
237
|
+
|
|
238
|
+
run_repopilot inspect knowledge --section rules --format markdown --output "$TMP_DIR/inspect-knowledge-rules.md"
|
|
239
|
+
assert_non_empty "$TMP_DIR/inspect-knowledge-rules.md"
|
|
240
|
+
|
|
241
|
+
run_repopilot inspect explain "$EXPLAIN_FILE" --format json --output "$TMP_DIR/inspect-explain.json"
|
|
242
|
+
assert_non_empty "$TMP_DIR/inspect-explain.json"
|
|
243
|
+
validate_json_if_possible "$TMP_DIR/inspect-explain.json"
|
|
244
|
+
|
|
245
|
+
if [[ "$RUN_LEGACY" -eq 1 ]]; then
|
|
246
|
+
run_repopilot vibe . --focus security --budget 2k --output "$TMP_DIR/legacy-vibe.md"
|
|
247
|
+
assert_non_empty "$TMP_DIR/legacy-vibe.md"
|
|
248
|
+
|
|
249
|
+
run_repopilot harden . --focus all --budget 2k --output "$TMP_DIR/legacy-harden.md"
|
|
250
|
+
assert_non_empty "$TMP_DIR/legacy-harden.md"
|
|
251
|
+
|
|
252
|
+
run_repopilot prompt . --focus quality --budget 2k --output "$TMP_DIR/legacy-prompt.md"
|
|
253
|
+
assert_non_empty "$TMP_DIR/legacy-prompt.md"
|
|
254
|
+
|
|
255
|
+
run_repopilot knowledge --format json --output "$TMP_DIR/legacy-knowledge.json"
|
|
256
|
+
assert_non_empty "$TMP_DIR/legacy-knowledge.json"
|
|
257
|
+
validate_json_if_possible "$TMP_DIR/legacy-knowledge.json"
|
|
258
|
+
|
|
259
|
+
run_repopilot explain "$EXPLAIN_FILE" --format json --output "$TMP_DIR/legacy-explain.json"
|
|
260
|
+
assert_non_empty "$TMP_DIR/legacy-explain.json"
|
|
261
|
+
validate_json_if_possible "$TMP_DIR/legacy-explain.json"
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
echo
|
|
265
|
+
echo "==> Product smoke suite passed"
|
|
266
|
+
echo "Artifacts: $TMP_DIR"
|
|
@@ -15,6 +15,48 @@ cargo clippy --all-targets --all-features -- -D warnings
|
|
|
15
15
|
echo "==> Rust tests"
|
|
16
16
|
cargo test --all
|
|
17
17
|
|
|
18
|
+
echo "==> Rust dependency security audit"
|
|
19
|
+
cargo audit
|
|
20
|
+
|
|
21
|
+
echo "==> Cargo dependency policy"
|
|
22
|
+
cargo deny check advisories licenses
|
|
23
|
+
|
|
24
|
+
echo "==> Shell script syntax"
|
|
25
|
+
scripts=()
|
|
26
|
+
if [[ -f install.sh ]]; then
|
|
27
|
+
scripts+=(install.sh)
|
|
28
|
+
fi
|
|
29
|
+
if [[ -d scripts ]]; then
|
|
30
|
+
while IFS= read -r -d '' script; do
|
|
31
|
+
scripts+=("$script")
|
|
32
|
+
done < <(find scripts -maxdepth 1 -type f -name '*.sh' -print0)
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
if ((${#scripts[@]} > 0)); then
|
|
36
|
+
for script in "${scripts[@]}"; do
|
|
37
|
+
bash -n "$script"
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
echo "==> ShellCheck"
|
|
41
|
+
shellcheck "${scripts[@]}"
|
|
42
|
+
else
|
|
43
|
+
echo "==> No shell scripts found"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo "==> GitHub Actions validation"
|
|
47
|
+
workflows=()
|
|
48
|
+
if [[ -d .github/workflows ]]; then
|
|
49
|
+
while IFS= read -r -d '' workflow; do
|
|
50
|
+
workflows+=("$workflow")
|
|
51
|
+
done < <(find .github/workflows -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print0)
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if ((${#workflows[@]} > 0)); then
|
|
55
|
+
actionlint "${workflows[@]}"
|
|
56
|
+
else
|
|
57
|
+
echo "==> No GitHub Actions workflows found"
|
|
58
|
+
fi
|
|
59
|
+
|
|
18
60
|
echo "==> CLI release smoke tests"
|
|
19
61
|
cargo test --test cli_release_smoke
|
|
20
62
|
|
|
@@ -33,16 +75,10 @@ npm pack --dry-run
|
|
|
33
75
|
echo "==> Build release binary"
|
|
34
76
|
cargo build --release
|
|
35
77
|
|
|
36
|
-
echo "==>
|
|
37
|
-
./
|
|
38
|
-
./target/release/repopilot
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
./target/release/repopilot prompt . --focus quality --budget 4k --output /tmp/repopilot-release-prompt.md
|
|
42
|
-
|
|
43
|
-
test -s /tmp/repopilot-release-scan.md
|
|
44
|
-
test -s /tmp/repopilot-release-vibe.md
|
|
45
|
-
test -s /tmp/repopilot-release-harden.md
|
|
46
|
-
test -s /tmp/repopilot-release-prompt.md
|
|
78
|
+
echo "==> Product readiness smoke suite"
|
|
79
|
+
./scripts/smoke-product.sh \
|
|
80
|
+
--binary ./target/release/repopilot \
|
|
81
|
+
--repo . \
|
|
82
|
+
--tmp-dir /tmp/repopilot-release-smoke
|
|
47
83
|
|
|
48
|
-
echo "==> Release verification passed"
|
|
84
|
+
echo "==> Release verification passed"
|