bugproof 0.2.12 → 1.0.1
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 +43 -103
- package/dist/capture/engine.d.ts.map +1 -1
- package/dist/capture/engine.js +7 -2
- package/dist/capture/engine.js.map +1 -1
- package/dist/capture/packager.d.ts.map +1 -1
- package/dist/capture/packager.js +11 -5
- package/dist/capture/packager.js.map +1 -1
- package/dist/cli.js +101 -18
- package/dist/cli.js.map +1 -1
- package/dist/replay/engine.d.ts +2 -0
- package/dist/replay/engine.d.ts.map +1 -1
- package/dist/replay/engine.js +2 -1
- package/dist/replay/engine.js.map +1 -1
- package/dist/sandbox/container.js +4 -4
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/cross-platform.d.ts +5 -1
- package/dist/sandbox/cross-platform.d.ts.map +1 -1
- package/dist/sandbox/cross-platform.js +13 -3
- package/dist/sandbox/cross-platform.js.map +1 -1
- package/dist/share/gist.d.ts.map +1 -1
- package/dist/share/gist.js +4 -0
- package/dist/share/gist.js.map +1 -1
- package/dist/utils/cleanup.d.ts +5 -0
- package/dist/utils/cleanup.d.ts.map +1 -0
- package/dist/utils/cleanup.js +53 -0
- package/dist/utils/cleanup.js.map +1 -0
- package/dist/utils/secrets.d.ts +1 -0
- package/dist/utils/secrets.d.ts.map +1 -1
- package/dist/utils/secrets.js +16 -0
- package/dist/utils/secrets.js.map +1 -1
- package/dist/utils/ui.d.ts +10 -0
- package/dist/utils/ui.d.ts.map +1 -1
- package/dist/utils/ui.js +39 -0
- package/dist/utils/ui.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# BugProof
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
@@ -117,7 +117,7 @@ Examples:
|
|
|
117
117
|
bugproof capture -- npm test
|
|
118
118
|
bugproof capture -n auth-crash -d "Login fails on expired session" -- node server.js
|
|
119
119
|
bugproof capture --include-untracked -- python app.py
|
|
120
|
-
bugproof capture -
|
|
120
|
+
bugproof capture -x "*.log" -x "*.tmp" -- go test ./...
|
|
121
121
|
bugproof capture --timeout 600000 -- java -cp . Main
|
|
122
122
|
bugproof capture --json -- node script.js
|
|
123
123
|
```
|
|
@@ -128,7 +128,7 @@ Options:
|
|
|
128
128
|
- `--timeout <ms>` Command timeout in milliseconds (default: `300000`)
|
|
129
129
|
- `-n, --name <name>` Human-readable artifact name
|
|
130
130
|
- `-d, --description <desc>` Bug description
|
|
131
|
-
- `-
|
|
131
|
+
- `-x, --exclude <pattern>` Exclude files matching pattern (repeatable)
|
|
132
132
|
- `--json` Structured JSON output
|
|
133
133
|
|
|
134
134
|
### `bugproof replay <artifact>`
|
|
@@ -143,6 +143,7 @@ bugproof replay --version-match strict my-bug.bug
|
|
|
143
143
|
bugproof replay --version-match branch my-bug.bug
|
|
144
144
|
bugproof replay --sandbox isolated my-bug.bug
|
|
145
145
|
bugproof replay --env API_URL=https://staging.local --env DEBUG=true my-bug.bug
|
|
146
|
+
bugproof replay --replay-count 5 my-bug.bug
|
|
146
147
|
bugproof replay --json my-bug.bug
|
|
147
148
|
```
|
|
148
149
|
|
|
@@ -150,6 +151,7 @@ Options:
|
|
|
150
151
|
- `--version-match <mode>` `strict | current | branch` (default: `current`)
|
|
151
152
|
- `--sandbox <level>` `workspace | isolated | full` (default: `workspace`)
|
|
152
153
|
- `--env <var=value>` Override environment variable (repeatable)
|
|
154
|
+
- `--replay-count <n>` Run the replay up to N times (useful for flaky bugs/race conditions)
|
|
153
155
|
- `--json` Structured JSON output
|
|
154
156
|
|
|
155
157
|
### `bugproof inspect <artifact>`
|
|
@@ -236,12 +238,28 @@ bugproof share my-bug.bug
|
|
|
236
238
|
bugproof share --public my-bug.bug
|
|
237
239
|
```
|
|
238
240
|
|
|
239
|
-
Requires `GITHUB_TOKEN` or `BUGPROOF_GITHUB_TOKEN` env var with `gist` scope.
|
|
241
|
+
Requires `GITHUB_TOKEN` or `BUGPROOF_GITHUB_TOKEN` env var with `gist` scope. Automatically respects `HTTP_PROXY` and `HTTPS_PROXY` for corporate environments.
|
|
240
242
|
|
|
241
243
|
Options:
|
|
242
244
|
- `--public` Create a public gist (default: secret/unlisted)
|
|
243
245
|
- `--json` Structured JSON output
|
|
244
246
|
|
|
247
|
+
### `bugproof prune`
|
|
248
|
+
|
|
249
|
+
Clean up orphaned temporary directories and sandbox containers from aborted runs to reclaim disk space.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
bugproof prune
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### `bugproof doctor`
|
|
256
|
+
|
|
257
|
+
Run a self-diagnostic to verify host OS support for native sandboxing features (Job Objects, Linux namespaces, Apple Seatbelt).
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
bugproof doctor
|
|
261
|
+
```
|
|
262
|
+
|
|
245
263
|
## Smart Features
|
|
246
264
|
|
|
247
265
|
### Dependency Detection
|
|
@@ -356,34 +374,16 @@ bash scripts/bugproof-file-association-macos.sh
|
|
|
356
374
|
| macOS | Yes | Yes | Yes |
|
|
357
375
|
|
|
358
376
|
Notes:
|
|
377
|
+
- **Cross-Architecture Guardrails**: BugProof actively detects and warns on CPU architecture mismatches (e.g., replaying an `x64` bug on an `arm64` machine), advising on Rosetta/translation impacts.
|
|
359
378
|
- Exit codes may differ by OS for signals/crashes.
|
|
360
379
|
- Fingerprint/error-pattern matching is used for reproduction verdict.
|
|
361
380
|
|
|
362
|
-
##
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
-
|
|
366
|
-
-
|
|
367
|
-
-
|
|
368
|
-
- Reproducibility over screenshots/log snippets
|
|
369
|
-
|
|
370
|
-
## Roadmap
|
|
371
|
-
|
|
372
|
-
- [x] v0.1: CLI core (capture/replay/inspect/diff)
|
|
373
|
-
- [x] v0.1: Cross-platform replay support
|
|
374
|
-
- [x] v0.1: Secret redaction and sandbox layers
|
|
375
|
-
- [x] v0.2: Watch command (auto-capture on failure)
|
|
376
|
-
- [x] v0.2: Project config (`.bugproofrc`)
|
|
377
|
-
- [x] v0.2: Dependency detection (Node/Python/Ruby/Go/Rust)
|
|
378
|
-
- [x] v0.2: Smart hints on replay failure
|
|
379
|
-
- [x] v0.2: Share via GitHub Gist
|
|
380
|
-
- [x] v0.2.1: Smart source strategy (git-full/git-patch/stacktrace/minimal)
|
|
381
|
-
- [x] v0.2.1: BugBox Container (lightweight Docker-like isolation)
|
|
382
|
-
- [x] v0.2.1: Environment snapshot + mismatch warnings
|
|
383
|
-
- [ ] v0.3: Web UI for artifact inspection
|
|
384
|
-
- [ ] v0.3: Artifact signing and verification
|
|
385
|
-
- [ ] v0.4: GitHub issue integration and richer diff visualization
|
|
386
|
-
- [ ] v0.4: CI/CD plugins (GitHub Actions, GitLab CI)
|
|
381
|
+
## Design Principles
|
|
382
|
+
|
|
383
|
+
- Security-first default behavior (secrets redacted by default)
|
|
384
|
+
- Language-agnostic command capture (works with any CLI tool)
|
|
385
|
+
- Minimal runtime dependencies (Node.js + Git only)
|
|
386
|
+
- Reproducibility over screenshots or log snippets
|
|
387
387
|
|
|
388
388
|
## Development
|
|
389
389
|
|
|
@@ -393,87 +393,27 @@ npm run build
|
|
|
393
393
|
npm test
|
|
394
394
|
```
|
|
395
395
|
|
|
396
|
-
##
|
|
397
|
-
|
|
398
|
-
This section helps maintainers and integrators understand the architecture, testing, and shipping process for BugProof.
|
|
399
|
-
|
|
400
|
-
- Architecture: modular pipeline (Capture → Packager → Replay → Verdict). Key modules:
|
|
401
|
-
- `src/capture/*` — execution capture and environment snapshot
|
|
402
|
-
- `src/capture/language-support.ts` — multi-language detection and language-context.json generation
|
|
403
|
-
- `src/replay/*` — artifact restore, sandboxing, and verdict generation
|
|
404
|
-
- `src/replay/verdict.ts` — fingerprint and normalized-pattern matching logic
|
|
405
|
-
|
|
406
|
-
- Testing: unit tests (Jest) live under `tests/`; integration tests under `tests/integration/`.
|
|
407
|
-
- Run `npm test` for full suite. Use `npm run test:e2e` for cross-platform orchestrator (requires SSH hosts configured).
|
|
408
|
-
|
|
409
|
-
- Cross-platform QA: use `scripts/e2e-matrix.js` to run Windows↔Linux scenarios. Configure SSH in `scripts/e2e-matrix.js` or provide `E2E_TARGET` env.
|
|
410
|
-
|
|
411
|
-
- Shipping checklist (short):
|
|
412
|
-
1. Ensure `npm run build` passes and `npm test` is green locally on both Windows and Linux runners.
|
|
413
|
-
2. Update `CHANGELOG.md` and bump `package.json` version.
|
|
414
|
-
3. Tag a release `git tag -a vX.Y.Z -m "Release vX.Y.Z"` and push tags.
|
|
415
|
-
4. CI will run `prepublishOnly` and publish on tag events.
|
|
396
|
+
## Architecture
|
|
416
397
|
|
|
417
|
-
|
|
398
|
+
BugProof follows a modular pipeline: **Capture → Package → Replay → Verdict**.
|
|
418
399
|
|
|
419
|
-
|
|
400
|
+
| Module | Purpose |
|
|
401
|
+
|--------|---------|
|
|
402
|
+
| `src/capture/` | Execution capture, environment snapshot, source strategy |
|
|
403
|
+
| `src/replay/` | Artifact restore, sandboxing, verdict generation |
|
|
404
|
+
| `src/replay/verdict.ts` | Fingerprint and normalized-pattern matching |
|
|
405
|
+
| `src/capture/language-support.ts` | Multi-language detection |
|
|
420
406
|
|
|
421
|
-
|
|
407
|
+
Tests use Jest and live under `tests/`. Run `npm test` for the full suite. Cross-platform QA uses `scripts/e2e-matrix.js` with SSH-configured Linux hosts.
|
|
422
408
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
**Every push to `main` automatically:**
|
|
426
|
-
1. ✅ Runs tests on 6 combinations (Ubuntu/Windows/macOS × Node 18+20)
|
|
427
|
-
2. ✅ Runs security audit (npm audit)
|
|
428
|
-
3. ✅ Validates installation on all platforms
|
|
429
|
-
4. ✅ Auto-bumps patch version
|
|
430
|
-
5. ✅ Publishes to npm registry
|
|
431
|
-
6. ✅ Creates GitHub Release
|
|
432
|
-
|
|
433
|
-
**Result:** Zero manual steps for releases after initial NPM_TOKEN setup.
|
|
434
|
-
|
|
435
|
-
### Setup
|
|
436
|
-
|
|
437
|
-
**One-time configuration (5 minutes):**
|
|
438
|
-
|
|
439
|
-
1. Generate npm automation token: https://www.npmjs.com/settings/~/tokens
|
|
440
|
-
2. Add to GitHub: Settings → Secrets → `NPM_TOKEN` → Save
|
|
441
|
-
|
|
442
|
-
See [CI_CD_QUICKSTART.md](./CI_CD_QUICKSTART.md) for step-by-step instructions.
|
|
443
|
-
|
|
444
|
-
### Test Matrix
|
|
445
|
-
|
|
446
|
-
| OS | Node 18 | Node 20 | Status |
|
|
447
|
-
|-----------|---------|---------|--------|
|
|
448
|
-
| Ubuntu | ✅ | ✅ | 2 runs |
|
|
449
|
-
| Windows | ✅ | ✅ | 2 runs |
|
|
450
|
-
| macOS | ✅ | ✅ | 2 runs |
|
|
451
|
-
|
|
452
|
-
**Per run:** 276 Jest tests + ESLint checks
|
|
453
|
-
|
|
454
|
-
### Documentation
|
|
455
|
-
|
|
456
|
-
- **Quick setup:** [CI_CD_QUICKSTART.md](./CI_CD_QUICKSTART.md) (5 min)
|
|
457
|
-
- **Full guide:** [CI_CD_GUIDE.md](./CI_CD_GUIDE.md) (detailed reference)
|
|
458
|
-
- **Implementation:** [CI_CD_IMPLEMENTATION_SUMMARY.md](./CI_CD_IMPLEMENTATION_SUMMARY.md)
|
|
459
|
-
- **Workflow file:** [`.github/workflows/release.yml`](.github/workflows/release.yml)
|
|
460
|
-
|
|
461
|
-
### Local Validation
|
|
462
|
-
|
|
463
|
-
Before pushing, run the CI health check locally:
|
|
464
|
-
|
|
465
|
-
```bash
|
|
466
|
-
node scripts/ci-health-check.js
|
|
467
|
-
```
|
|
409
|
+
## CI/CD
|
|
468
410
|
|
|
469
|
-
|
|
411
|
+
Every push to `main` triggers automated testing across Ubuntu, Windows, and macOS via GitHub Actions. On success, the pipeline auto-bumps the version, publishes to npm, and creates a GitHub Release. The workflow file is at `.github/workflows/ci.yml`.
|
|
470
412
|
|
|
471
|
-
###
|
|
413
|
+
### One-time setup
|
|
472
414
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
- Publishing to npmjs.com runs automatically on `main` push (after all tests pass).
|
|
476
|
-
- GitHub Releases are created automatically with generated release notes.
|
|
415
|
+
1. Generate an npm automation token at https://www.npmjs.com/settings/~/tokens
|
|
416
|
+
2. Add it as `NPM_TOKEN` in GitHub: Settings → Secrets and variables → Actions
|
|
477
417
|
|
|
478
418
|
## License
|
|
479
419
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/capture/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/capture/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKpD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA6I9H"}
|
package/dist/capture/engine.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
2
|
import { generateExactFingerprint, extractErrorPatterns } from '../utils/fingerprint.js';
|
|
3
|
+
import { sanitizePII } from '../utils/secrets.js';
|
|
3
4
|
/**
|
|
4
5
|
* Spawns the command, captures its output, and produces a FailureRecord.
|
|
5
6
|
* Uses streaming to handle large output without memory issues.
|
|
@@ -42,7 +43,8 @@ export async function executeAndCapture(config) {
|
|
|
42
43
|
}
|
|
43
44
|
catch (err) {
|
|
44
45
|
// Command not found or spawn error
|
|
45
|
-
|
|
46
|
+
let errStr = String(err);
|
|
47
|
+
errStr = sanitizePII(errStr);
|
|
46
48
|
safeResolve({
|
|
47
49
|
failure: {
|
|
48
50
|
exit_code: 1,
|
|
@@ -84,6 +86,8 @@ export async function executeAndCapture(config) {
|
|
|
84
86
|
proc.on('close', (code, signal) => {
|
|
85
87
|
clearTimeout(timeoutHandle);
|
|
86
88
|
const duration = Date.now() - startTime;
|
|
89
|
+
stdoutBuffer = sanitizePII(stdoutBuffer);
|
|
90
|
+
stderrBuffer = sanitizePII(stderrBuffer);
|
|
87
91
|
// Determine snippet (last 5 lines of stderr)
|
|
88
92
|
const lines = stderrBuffer.trim().split('\n');
|
|
89
93
|
const snippet = lines.slice(Math.max(0, lines.length - 5)).join('\n');
|
|
@@ -106,7 +110,8 @@ export async function executeAndCapture(config) {
|
|
|
106
110
|
});
|
|
107
111
|
proc.on('error', (err) => {
|
|
108
112
|
clearTimeout(timeoutHandle);
|
|
109
|
-
|
|
113
|
+
let errStr = String(err);
|
|
114
|
+
errStr = sanitizePII(errStr);
|
|
110
115
|
stderrBuffer += errStr;
|
|
111
116
|
safeResolve({
|
|
112
117
|
failure: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/capture/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/capture/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packager.d.ts","sourceRoot":"","sources":["../../src/capture/packager.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,mDAAmD;IACnD,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"packager.d.ts","sourceRoot":"","sources":["../../src/capture/packager.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,mDAAmD;IACnD,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,CA+G9E"}
|
package/dist/capture/packager.js
CHANGED
|
@@ -6,8 +6,9 @@ import { spawnSync } from 'child_process';
|
|
|
6
6
|
import { zipDirectory } from '../utils/archive.js';
|
|
7
7
|
import { filterByExcludePatterns } from '../utils/exclude.js';
|
|
8
8
|
import { isPathWithinBoundary } from '../utils/security.js';
|
|
9
|
-
const MAX_ARTIFACT_SIZE =
|
|
10
|
-
const WARN_THRESHOLD =
|
|
9
|
+
const MAX_ARTIFACT_SIZE = 100 * 1024 * 1024; // 100MB hard limit
|
|
10
|
+
const WARN_THRESHOLD = 50 * 1024 * 1024; // 50MB warning
|
|
11
|
+
const MAX_FILE_COUNT = 10000; // 10k files hard limit
|
|
11
12
|
/**
|
|
12
13
|
* Packages the artifact into the .bug directory format specified in DESIGN.md.
|
|
13
14
|
*
|
|
@@ -142,9 +143,14 @@ function copySourceFiles(filesDir, workingDir, includeUntracked, excludePatterns
|
|
|
142
143
|
if (!stats.isFile())
|
|
143
144
|
continue;
|
|
144
145
|
runningSize += stats.size;
|
|
145
|
-
if (runningSize > MAX_ARTIFACT_SIZE) {
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
if (runningSize > MAX_ARTIFACT_SIZE || entries.length >= MAX_FILE_COUNT) {
|
|
147
|
+
process.stderr.write(`\n [WARNING] Repository exceeds hardware limits (50MB or 10,000 files).\n` +
|
|
148
|
+
` Gracefully falling back to "stacktrace-only" mode. The bug artifact will\n` +
|
|
149
|
+
` contain the command, logs, and environment, but NO source files.\n\n`);
|
|
150
|
+
// Clean up partially copied files
|
|
151
|
+
fs.rmSync(filesDir, { recursive: true, force: true });
|
|
152
|
+
fs.mkdirSync(filesDir, { recursive: true });
|
|
153
|
+
return [];
|
|
148
154
|
}
|
|
149
155
|
if (runningSize > WARN_THRESHOLD && entries.length > 0 && entries.length % 50 === 0) {
|
|
150
156
|
process.stderr.write(` Warning: artifact is ${(runningSize / 1024 / 1024).toFixed(1)} MB and growing...\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packager.js","sourceRoot":"","sources":["../../src/capture/packager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAgC5D,MAAM,iBAAiB,GAAG,
|
|
1
|
+
{"version":3,"file":"packager.js","sourceRoot":"","sources":["../../src/capture/packager.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -6,17 +6,19 @@ import * as path from 'path';
|
|
|
6
6
|
import { executeAndCapture } from './capture/engine.js';
|
|
7
7
|
import { packageArtifact } from './capture/packager.js';
|
|
8
8
|
import { scanEnvironmentForSecrets, buildEnvironmentSchema } from './utils/secrets.js';
|
|
9
|
+
import { detectCapabilities } from './sandbox/capabilities.js';
|
|
9
10
|
import { getGitContext } from './utils/git.js';
|
|
10
11
|
import { formatCaptureJson, formatReplayJson, formatInspectJson } from './utils/json-output.js';
|
|
11
12
|
import { extractZip } from './utils/archive.js';
|
|
12
13
|
import { diffArtifacts } from './diff/engine.js';
|
|
13
14
|
import { replayArtifact } from './replay/engine.js';
|
|
14
15
|
import { generateVerdict } from './replay/verdict.js';
|
|
15
|
-
import { banner, section, success, warn, error, info, kvLine, c, icons } from './utils/ui.js';
|
|
16
|
+
import { banner, section, success, warn, error, info, kvLine, c, icons, Spinner, statusBadge } from './utils/ui.js';
|
|
16
17
|
import { loadConfig, generateDefaultConfig, applyNameTemplate } from './config/loader.js';
|
|
17
18
|
import { generateHints } from './replay/hints.js';
|
|
18
19
|
import { shareToGist } from './share/gist.js';
|
|
19
20
|
import { sanitizeShareError } from './share/gist.js';
|
|
21
|
+
import { pruneTempDirectories } from './utils/cleanup.js';
|
|
20
22
|
import { detectMissingDependencies } from './utils/dependencies.js';
|
|
21
23
|
import { determineSourceStrategy } from './capture/source-strategy.js';
|
|
22
24
|
import { captureEnvSnapshot, compareEnvSnapshots } from './capture/env-snapshot.js';
|
|
@@ -269,6 +271,7 @@ program
|
|
|
269
271
|
return arr;
|
|
270
272
|
}, [])
|
|
271
273
|
.option('--json', 'Output structured JSON instead of human-readable text')
|
|
274
|
+
.option('--replay-count <n>', 'Number of times to retry replay for flaky bugs', '1')
|
|
272
275
|
.action(async (artifact, options) => {
|
|
273
276
|
const jsonMode = options.json === true;
|
|
274
277
|
if (!fs.existsSync(artifact)) {
|
|
@@ -285,16 +288,21 @@ program
|
|
|
285
288
|
const stat = fs.statSync(artifact);
|
|
286
289
|
let targetPath = artifact;
|
|
287
290
|
let tempDir;
|
|
291
|
+
let extractSpinner;
|
|
288
292
|
try {
|
|
289
293
|
if (stat.isFile()) {
|
|
290
|
-
if (!jsonMode)
|
|
291
|
-
|
|
294
|
+
if (!jsonMode) {
|
|
295
|
+
extractSpinner = new Spinner('Extracting compressed artifact');
|
|
296
|
+
extractSpinner.start();
|
|
297
|
+
}
|
|
292
298
|
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bugproof-extract-'));
|
|
293
299
|
targetPath = tempDir;
|
|
294
300
|
try {
|
|
295
301
|
await extractZip(artifact, tempDir);
|
|
302
|
+
extractSpinner?.stop();
|
|
296
303
|
}
|
|
297
304
|
catch {
|
|
305
|
+
extractSpinner?.stop();
|
|
298
306
|
if (jsonMode) {
|
|
299
307
|
console.log(JSON.stringify({ reproduced: false, error: 'Corrupted artifact: Invalid or damaged .bug file' }));
|
|
300
308
|
}
|
|
@@ -368,16 +376,31 @@ program
|
|
|
368
376
|
info('Replaying command...');
|
|
369
377
|
console.log();
|
|
370
378
|
}
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
379
|
+
const replayCount = parseInt(options.replayCount, 10) || 1;
|
|
380
|
+
let replayResult;
|
|
381
|
+
let verdict;
|
|
382
|
+
for (let i = 0; i < replayCount; i++) {
|
|
383
|
+
if (replayCount > 1 && !jsonMode) {
|
|
384
|
+
info(`Replay attempt ${i + 1}/${replayCount}...`);
|
|
385
|
+
}
|
|
386
|
+
replayResult = await replayArtifact(runConfig, expectedFailure, {
|
|
387
|
+
artifactPath: targetPath,
|
|
388
|
+
versionMatch: options.versionMatch,
|
|
389
|
+
sandboxLevel: options.sandbox,
|
|
390
|
+
envOverrides,
|
|
391
|
+
gitCommit: manifest.captured_on.git_commit,
|
|
392
|
+
gitBranch: manifest.captured_on.git_branch,
|
|
393
|
+
capturedPlatform: manifest.captured_on.os,
|
|
394
|
+
capturedArch: manifest.captured_on.arch,
|
|
395
|
+
});
|
|
396
|
+
verdict = generateVerdict(replayResult);
|
|
397
|
+
if (verdict.status === 'confirmed') {
|
|
398
|
+
if (replayCount > 1 && !jsonMode) {
|
|
399
|
+
success(`Reproduced successfully on attempt ${i + 1}!`);
|
|
400
|
+
}
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
381
404
|
if (jsonMode) {
|
|
382
405
|
console.log(formatReplayJson({
|
|
383
406
|
verdict,
|
|
@@ -797,6 +820,11 @@ program
|
|
|
797
820
|
fs.mkdirSync(artifactDir, { recursive: true });
|
|
798
821
|
}
|
|
799
822
|
const artifactPath = path.join(artifactDir, `${artifactName}.bug`);
|
|
823
|
+
let packSpinner;
|
|
824
|
+
if (!jsonMode) {
|
|
825
|
+
packSpinner = new Spinner('Packaging artifact');
|
|
826
|
+
packSpinner.start();
|
|
827
|
+
}
|
|
800
828
|
try {
|
|
801
829
|
const packResult = await packageArtifact(artifactPath, {
|
|
802
830
|
manifest,
|
|
@@ -824,6 +852,7 @@ program
|
|
|
824
852
|
}, null, 2));
|
|
825
853
|
}
|
|
826
854
|
else {
|
|
855
|
+
packSpinner?.stop();
|
|
827
856
|
console.log();
|
|
828
857
|
success(`Artifact auto-captured: ${c.cyan(artifactPath)}`);
|
|
829
858
|
kvLine('Files', `${packResult.filesCount} files (${(packResult.totalSize / 1024).toFixed(1)} KB)`);
|
|
@@ -839,7 +868,7 @@ program
|
|
|
839
868
|
console.log(JSON.stringify({ success: false, error: String(err) }));
|
|
840
869
|
}
|
|
841
870
|
else {
|
|
842
|
-
|
|
871
|
+
packSpinner?.stop(`Auto-capture failed: ${err}`, true);
|
|
843
872
|
}
|
|
844
873
|
}
|
|
845
874
|
process.exit(result.failure.exit_code);
|
|
@@ -880,9 +909,11 @@ program
|
|
|
880
909
|
}
|
|
881
910
|
process.exit(1);
|
|
882
911
|
}
|
|
912
|
+
let spinner;
|
|
883
913
|
if (!jsonMode) {
|
|
884
914
|
banner(`${icons.arrow} BugProof Share`);
|
|
885
|
-
|
|
915
|
+
spinner = new Spinner('Uploading artifact to GitHub Gist');
|
|
916
|
+
spinner.start();
|
|
886
917
|
}
|
|
887
918
|
try {
|
|
888
919
|
const result = await shareToGist(artifact, { public: options.public });
|
|
@@ -894,8 +925,7 @@ program
|
|
|
894
925
|
}, null, 2));
|
|
895
926
|
}
|
|
896
927
|
else {
|
|
897
|
-
|
|
898
|
-
success('Artifact shared!');
|
|
928
|
+
spinner?.stop('Artifact shared!');
|
|
899
929
|
console.log();
|
|
900
930
|
kvLine('URL', c.cyan(result.url));
|
|
901
931
|
kvLine('Gist ID', result.gistId);
|
|
@@ -909,10 +939,63 @@ program
|
|
|
909
939
|
console.log(JSON.stringify({ success: false, error: sanitizeShareError(String(err)) }));
|
|
910
940
|
}
|
|
911
941
|
else {
|
|
912
|
-
|
|
942
|
+
spinner?.stop(sanitizeShareError(String(err)), true);
|
|
913
943
|
}
|
|
914
944
|
process.exit(1);
|
|
915
945
|
}
|
|
916
946
|
});
|
|
947
|
+
// ─── PRUNE ──────────────────────────────────────────────────────────────────
|
|
948
|
+
program
|
|
949
|
+
.command('prune')
|
|
950
|
+
.description('Clean up temporary sandbox and artifact directories')
|
|
951
|
+
.action(() => {
|
|
952
|
+
banner(`${icons.arrow} BugProof Prune`);
|
|
953
|
+
info('Scanning temporary directories...');
|
|
954
|
+
const result = pruneTempDirectories();
|
|
955
|
+
if (result.prunedCount === 0) {
|
|
956
|
+
success('Nothing to clean up. Temp directory is pristine.');
|
|
957
|
+
}
|
|
958
|
+
else {
|
|
959
|
+
success(`Pruned ${result.prunedCount} orphan directories.`);
|
|
960
|
+
kvLine('Reclaimed', `${(result.prunedBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
961
|
+
}
|
|
962
|
+
console.log();
|
|
963
|
+
});
|
|
964
|
+
// ─── DOCTOR ─────────────────────────────────────────────────────────────────
|
|
965
|
+
program
|
|
966
|
+
.command('doctor')
|
|
967
|
+
.description('Verify host OS support for sandboxing and features')
|
|
968
|
+
.action(() => {
|
|
969
|
+
banner(`${icons.arrow} BugProof Doctor`);
|
|
970
|
+
const caps = detectCapabilities();
|
|
971
|
+
section('Host Information');
|
|
972
|
+
kvLine('OS', `${os.type()} ${os.release()}`);
|
|
973
|
+
kvLine('Platform', caps.platform);
|
|
974
|
+
kvLine('Architecture', os.arch());
|
|
975
|
+
kvLine('Node Version', process.version);
|
|
976
|
+
console.log();
|
|
977
|
+
section('Sandbox Capabilities');
|
|
978
|
+
if (caps.platform === 'linux') {
|
|
979
|
+
statusBadge('Linux unshare (Namespaces)', caps.hasUnshare);
|
|
980
|
+
statusBadge('cgroups v2 (Resource Limits)', caps.hasCgroupsV2);
|
|
981
|
+
if (!caps.hasUnshare) {
|
|
982
|
+
warn('Missing unshare. BugProof will run without namespace isolation.');
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
else if (caps.platform === 'win32') {
|
|
986
|
+
statusBadge('Job Objects (Process Isolation)', caps.hasJobObjects);
|
|
987
|
+
statusBadge('netsh (Network Firewall)', caps.hasNetsh);
|
|
988
|
+
}
|
|
989
|
+
else if (caps.platform === 'darwin') {
|
|
990
|
+
statusBadge('sandbox-exec (Apple Seatbelt)', caps.hasSandboxExec);
|
|
991
|
+
if (!caps.hasSandboxExec) {
|
|
992
|
+
warn('Missing sandbox-exec. macOS sandbox profile isolation will be disabled.');
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
else {
|
|
996
|
+
warn(`Unsupported platform for native sandboxing: ${caps.platform}`);
|
|
997
|
+
}
|
|
998
|
+
console.log();
|
|
999
|
+
});
|
|
917
1000
|
program.parse(process.argv);
|
|
918
1001
|
//# sourceMappingURL=cli.js.map
|