openpitstop 1.0.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.
Files changed (274) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/demo-repo/README.md +24 -0
  4. package/demo-repo/package-lock.json +4483 -0
  5. package/demo-repo/package.json +17 -0
  6. package/demo-repo/src/config.js +5 -0
  7. package/demo-repo/src/db.js +31 -0
  8. package/demo-repo/src/server.js +13 -0
  9. package/demo-repo/src/userController.js +22 -0
  10. package/demo-repo/src/userRepo.js +18 -0
  11. package/demo-repo/src/userService.js +59 -0
  12. package/demo-repo/test/user.test.js +12 -0
  13. package/demo-repo-fintech/README.md +27 -0
  14. package/demo-repo-fintech/package-lock.json +1023 -0
  15. package/demo-repo-fintech/package.json +14 -0
  16. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-conc-1-charged-2.test.mjs +175 -0
  17. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-retry-2-charged-2.test.mjs +175 -0
  18. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-webhook-3-charged-2.test.mjs +175 -0
  19. package/demo-repo-fintech/src/gateway.js +26 -0
  20. package/demo-repo-fintech/src/server.js +61 -0
  21. package/demo-repo-generators/package-lock.json +1508 -0
  22. package/demo-repo-generators/package.json +17 -0
  23. package/demo-repo-generators/public/index.html +10 -0
  24. package/demo-repo-generators/scripts/build.js +17 -0
  25. package/demo-repo-generators/src/counter.js +16 -0
  26. package/demo-repo-integrity/README.md +49 -0
  27. package/demo-repo-integrity/package.json +12 -0
  28. package/demo-repo-integrity/src/money.js +19 -0
  29. package/demo-repo-integrity/test/money.test.js +17 -0
  30. package/dist/analyzers/accessibility.d.ts +18 -0
  31. package/dist/analyzers/accessibility.js +248 -0
  32. package/dist/analyzers/accessibility.js.map +1 -0
  33. package/dist/analyzers/dependencyGraph.d.ts +14 -0
  34. package/dist/analyzers/dependencyGraph.js +206 -0
  35. package/dist/analyzers/dependencyGraph.js.map +1 -0
  36. package/dist/analyzers/devex.d.ts +19 -0
  37. package/dist/analyzers/devex.js +301 -0
  38. package/dist/analyzers/devex.js.map +1 -0
  39. package/dist/analyzers/duplication.d.ts +2 -0
  40. package/dist/analyzers/duplication.js +47 -0
  41. package/dist/analyzers/duplication.js.map +1 -0
  42. package/dist/analyzers/index.d.ts +12 -0
  43. package/dist/analyzers/index.js +38 -0
  44. package/dist/analyzers/index.js.map +1 -0
  45. package/dist/analyzers/integrity/assertionLiteralTamper.d.ts +2 -0
  46. package/dist/analyzers/integrity/assertionLiteralTamper.js +164 -0
  47. package/dist/analyzers/integrity/assertionLiteralTamper.js.map +1 -0
  48. package/dist/analyzers/integrity/exceptionSwallow.d.ts +2 -0
  49. package/dist/analyzers/integrity/exceptionSwallow.js +198 -0
  50. package/dist/analyzers/integrity/exceptionSwallow.js.map +1 -0
  51. package/dist/analyzers/integrity/exitCheat.d.ts +2 -0
  52. package/dist/analyzers/integrity/exitCheat.js +31 -0
  53. package/dist/analyzers/integrity/exitCheat.js.map +1 -0
  54. package/dist/analyzers/integrity/git.d.ts +10 -0
  55. package/dist/analyzers/integrity/git.js +181 -0
  56. package/dist/analyzers/integrity/git.js.map +1 -0
  57. package/dist/analyzers/integrity/hardcodedMatch.d.ts +2 -0
  58. package/dist/analyzers/integrity/hardcodedMatch.js +93 -0
  59. package/dist/analyzers/integrity/hardcodedMatch.js.map +1 -0
  60. package/dist/analyzers/integrity/helpers.d.ts +21 -0
  61. package/dist/analyzers/integrity/helpers.js +66 -0
  62. package/dist/analyzers/integrity/helpers.js.map +1 -0
  63. package/dist/analyzers/integrity/index.d.ts +10 -0
  64. package/dist/analyzers/integrity/index.js +27 -0
  65. package/dist/analyzers/integrity/index.js.map +1 -0
  66. package/dist/analyzers/integrity/mockOverreach.d.ts +2 -0
  67. package/dist/analyzers/integrity/mockOverreach.js +72 -0
  68. package/dist/analyzers/integrity/mockOverreach.js.map +1 -0
  69. package/dist/analyzers/integrity/suppressionCreep.d.ts +2 -0
  70. package/dist/analyzers/integrity/suppressionCreep.js +27 -0
  71. package/dist/analyzers/integrity/suppressionCreep.js.map +1 -0
  72. package/dist/analyzers/integrity/testTamper.d.ts +2 -0
  73. package/dist/analyzers/integrity/testTamper.js +153 -0
  74. package/dist/analyzers/integrity/testTamper.js.map +1 -0
  75. package/dist/analyzers/integrity/types.d.ts +63 -0
  76. package/dist/analyzers/integrity/types.js +13 -0
  77. package/dist/analyzers/integrity/types.js.map +1 -0
  78. package/dist/analyzers/ledger/attacks.d.ts +17 -0
  79. package/dist/analyzers/ledger/attacks.js +135 -0
  80. package/dist/analyzers/ledger/attacks.js.map +1 -0
  81. package/dist/analyzers/ledger/discover.d.ts +15 -0
  82. package/dist/analyzers/ledger/discover.js +122 -0
  83. package/dist/analyzers/ledger/discover.js.map +1 -0
  84. package/dist/analyzers/ledger/evidence.d.ts +22 -0
  85. package/dist/analyzers/ledger/evidence.js +127 -0
  86. package/dist/analyzers/ledger/evidence.js.map +1 -0
  87. package/dist/analyzers/ledger/harness.d.ts +4 -0
  88. package/dist/analyzers/ledger/harness.js +270 -0
  89. package/dist/analyzers/ledger/harness.js.map +1 -0
  90. package/dist/analyzers/ledger/index.d.ts +14 -0
  91. package/dist/analyzers/ledger/index.js +116 -0
  92. package/dist/analyzers/ledger/index.js.map +1 -0
  93. package/dist/analyzers/ledger/types.d.ts +31 -0
  94. package/dist/analyzers/ledger/types.js +2 -0
  95. package/dist/analyzers/ledger/types.js.map +1 -0
  96. package/dist/analyzers/perf.d.ts +2 -0
  97. package/dist/analyzers/perf.js +106 -0
  98. package/dist/analyzers/perf.js.map +1 -0
  99. package/dist/analyzers/reliability.d.ts +22 -0
  100. package/dist/analyzers/reliability.js +339 -0
  101. package/dist/analyzers/reliability.js.map +1 -0
  102. package/dist/analyzers/routes.d.ts +17 -0
  103. package/dist/analyzers/routes.js +115 -0
  104. package/dist/analyzers/routes.js.map +1 -0
  105. package/dist/analyzers/security.d.ts +2 -0
  106. package/dist/analyzers/security.js +302 -0
  107. package/dist/analyzers/security.js.map +1 -0
  108. package/dist/analyzers/suiteRunner.d.ts +64 -0
  109. package/dist/analyzers/suiteRunner.js +381 -0
  110. package/dist/analyzers/suiteRunner.js.map +1 -0
  111. package/dist/analyzers/tests.d.ts +2 -0
  112. package/dist/analyzers/tests.js +215 -0
  113. package/dist/analyzers/tests.js.map +1 -0
  114. package/dist/analyzers/types.d.ts +203 -0
  115. package/dist/analyzers/types.js +2 -0
  116. package/dist/analyzers/types.js.map +1 -0
  117. package/dist/analyzers/util.d.ts +35 -0
  118. package/dist/analyzers/util.js +209 -0
  119. package/dist/analyzers/util.js.map +1 -0
  120. package/dist/ciCheckA.d.ts +2 -0
  121. package/dist/ciCheckA.js +5 -0
  122. package/dist/ciCheckA.js.map +1 -0
  123. package/dist/ciCheckB.d.ts +2 -0
  124. package/dist/ciCheckB.js +6 -0
  125. package/dist/ciCheckB.js.map +1 -0
  126. package/dist/cli.d.ts +2 -0
  127. package/dist/cli.js +65 -0
  128. package/dist/cli.js.map +1 -0
  129. package/dist/commands/budget.d.ts +33 -0
  130. package/dist/commands/budget.js +108 -0
  131. package/dist/commands/budget.js.map +1 -0
  132. package/dist/commands/ci.d.ts +14 -0
  133. package/dist/commands/ci.js +157 -0
  134. package/dist/commands/ci.js.map +1 -0
  135. package/dist/commands/demo.d.ts +2 -0
  136. package/dist/commands/demo.js +163 -0
  137. package/dist/commands/demo.js.map +1 -0
  138. package/dist/commands/digest.d.ts +8 -0
  139. package/dist/commands/digest.js +189 -0
  140. package/dist/commands/digest.js.map +1 -0
  141. package/dist/commands/doctor.d.ts +2 -0
  142. package/dist/commands/doctor.js +98 -0
  143. package/dist/commands/doctor.js.map +1 -0
  144. package/dist/commands/drive.d.ts +3 -0
  145. package/dist/commands/drive.js +170 -0
  146. package/dist/commands/drive.js.map +1 -0
  147. package/dist/commands/gate.d.ts +2 -0
  148. package/dist/commands/gate.js +136 -0
  149. package/dist/commands/gate.js.map +1 -0
  150. package/dist/commands/honesty.d.ts +2 -0
  151. package/dist/commands/honesty.js +182 -0
  152. package/dist/commands/honesty.js.map +1 -0
  153. package/dist/commands/inspect.d.ts +2 -0
  154. package/dist/commands/inspect.js +244 -0
  155. package/dist/commands/inspect.js.map +1 -0
  156. package/dist/commands/install.d.ts +2 -0
  157. package/dist/commands/install.js +81 -0
  158. package/dist/commands/install.js.map +1 -0
  159. package/dist/commands/integrity.d.ts +2 -0
  160. package/dist/commands/integrity.js +74 -0
  161. package/dist/commands/integrity.js.map +1 -0
  162. package/dist/commands/memory.d.ts +6 -0
  163. package/dist/commands/memory.js +90 -0
  164. package/dist/commands/memory.js.map +1 -0
  165. package/dist/commands/pen.d.ts +17 -0
  166. package/dist/commands/pen.js +158 -0
  167. package/dist/commands/pen.js.map +1 -0
  168. package/dist/commands/prompt.d.ts +2 -0
  169. package/dist/commands/prompt.js +37 -0
  170. package/dist/commands/prompt.js.map +1 -0
  171. package/dist/commands/readyCheck.d.ts +21 -0
  172. package/dist/commands/readyCheck.js +68 -0
  173. package/dist/commands/readyCheck.js.map +1 -0
  174. package/dist/commands/report.d.ts +2 -0
  175. package/dist/commands/report.js +48 -0
  176. package/dist/commands/report.js.map +1 -0
  177. package/dist/commands/repro.d.ts +3 -0
  178. package/dist/commands/repro.js +61 -0
  179. package/dist/commands/repro.js.map +1 -0
  180. package/dist/commands/scan.d.ts +27 -0
  181. package/dist/commands/scan.js +348 -0
  182. package/dist/commands/scan.js.map +1 -0
  183. package/dist/commands/share.d.ts +2 -0
  184. package/dist/commands/share.js +163 -0
  185. package/dist/commands/share.js.map +1 -0
  186. package/dist/commands/trends.d.ts +2 -0
  187. package/dist/commands/trends.js +103 -0
  188. package/dist/commands/trends.js.map +1 -0
  189. package/dist/commands/try.d.ts +12 -0
  190. package/dist/commands/try.js +208 -0
  191. package/dist/commands/try.js.map +1 -0
  192. package/dist/commands/verify.d.ts +44 -0
  193. package/dist/commands/verify.js +381 -0
  194. package/dist/commands/verify.js.map +1 -0
  195. package/dist/commands/watch.d.ts +10 -0
  196. package/dist/commands/watch.js +70 -0
  197. package/dist/commands/watch.js.map +1 -0
  198. package/dist/evidence.d.ts +37 -0
  199. package/dist/evidence.js +61 -0
  200. package/dist/evidence.js.map +1 -0
  201. package/dist/graph/correlate.d.ts +7 -0
  202. package/dist/graph/correlate.js +246 -0
  203. package/dist/graph/correlate.js.map +1 -0
  204. package/dist/graph/integrity.d.ts +22 -0
  205. package/dist/graph/integrity.js +39 -0
  206. package/dist/graph/integrity.js.map +1 -0
  207. package/dist/installer/targets.d.ts +23 -0
  208. package/dist/installer/targets.js +162 -0
  209. package/dist/installer/targets.js.map +1 -0
  210. package/dist/memory/store.d.ts +33 -0
  211. package/dist/memory/store.js +131 -0
  212. package/dist/memory/store.js.map +1 -0
  213. package/dist/pen/dynamic.d.ts +36 -0
  214. package/dist/pen/dynamic.js +622 -0
  215. package/dist/pen/dynamic.js.map +1 -0
  216. package/dist/pen/fix.d.ts +35 -0
  217. package/dist/pen/fix.js +239 -0
  218. package/dist/pen/fix.js.map +1 -0
  219. package/dist/pen/proof.d.ts +46 -0
  220. package/dist/pen/proof.js +112 -0
  221. package/dist/pen/proof.js.map +1 -0
  222. package/dist/pen/report.d.ts +11 -0
  223. package/dist/pen/report.js +258 -0
  224. package/dist/pen/report.js.map +1 -0
  225. package/dist/pen/static.d.ts +17 -0
  226. package/dist/pen/static.js +565 -0
  227. package/dist/pen/static.js.map +1 -0
  228. package/dist/pen/store.d.ts +11 -0
  229. package/dist/pen/store.js +36 -0
  230. package/dist/pen/store.js.map +1 -0
  231. package/dist/pen/types.d.ts +112 -0
  232. package/dist/pen/types.js +53 -0
  233. package/dist/pen/types.js.map +1 -0
  234. package/dist/report/format.d.ts +126 -0
  235. package/dist/report/format.js +706 -0
  236. package/dist/report/format.js.map +1 -0
  237. package/dist/report/score.d.ts +47 -0
  238. package/dist/report/score.js +164 -0
  239. package/dist/report/score.js.map +1 -0
  240. package/dist/repro/framework.d.ts +26 -0
  241. package/dist/repro/framework.js +224 -0
  242. package/dist/repro/framework.js.map +1 -0
  243. package/dist/repro/generate.d.ts +14 -0
  244. package/dist/repro/generate.js +669 -0
  245. package/dist/repro/generate.js.map +1 -0
  246. package/dist/repro/ids.d.ts +32 -0
  247. package/dist/repro/ids.js +175 -0
  248. package/dist/repro/ids.js.map +1 -0
  249. package/dist/repro/index.d.ts +24 -0
  250. package/dist/repro/index.js +69 -0
  251. package/dist/repro/index.js.map +1 -0
  252. package/dist/repro/pen.d.ts +26 -0
  253. package/dist/repro/pen.js +321 -0
  254. package/dist/repro/pen.js.map +1 -0
  255. package/dist/repro/run.d.ts +18 -0
  256. package/dist/repro/run.js +36 -0
  257. package/dist/repro/run.js.map +1 -0
  258. package/dist/sandbox/proxy.d.ts +41 -0
  259. package/dist/sandbox/proxy.js +231 -0
  260. package/dist/sandbox/proxy.js.map +1 -0
  261. package/dist/sandbox/startCmd.d.ts +24 -0
  262. package/dist/sandbox/startCmd.js +71 -0
  263. package/dist/sandbox/startCmd.js.map +1 -0
  264. package/dist/ui/spinner.d.ts +18 -0
  265. package/dist/ui/spinner.js +26 -0
  266. package/dist/ui/spinner.js.map +1 -0
  267. package/dist/verify/metrics.d.ts +13 -0
  268. package/dist/verify/metrics.js +72 -0
  269. package/dist/verify/metrics.js.map +1 -0
  270. package/package.json +68 -0
  271. package/scripts/cheat-demo.cjs +102 -0
  272. package/templates/ledger/preload.cjs +331 -0
  273. package/templates/pen/preload.cjs +196 -0
  274. package/templates/pitstop.prompt.md +371 -0
@@ -0,0 +1,381 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { commandExists, detectLanguage, safeExecAsync } from "./util.js";
4
+ /** Run the suite for Go/Rust/Flutter/.NET/Java repos; null if no toolchain or no tests. */
5
+ export async function runNonJsSuite(repo) {
6
+ switch (detectLanguage(repo)) {
7
+ case "go":
8
+ return runGo(repo);
9
+ case "rust":
10
+ return runCargo(repo);
11
+ case "dart":
12
+ return runFlutter(repo);
13
+ case "dotnet":
14
+ return runDotnet(repo);
15
+ case "java":
16
+ return runJava(repo);
17
+ default:
18
+ return null;
19
+ }
20
+ }
21
+ /** True when the language's test toolchain is available (PATH or repo wrapper). */
22
+ export function nonJsToolchainPresent(lang, repo) {
23
+ switch (lang) {
24
+ case "go":
25
+ return commandExists("go");
26
+ case "rust":
27
+ return commandExists("cargo");
28
+ case "dart":
29
+ return commandExists("flutter");
30
+ case "dotnet":
31
+ return commandExists("dotnet");
32
+ case "java":
33
+ return commandExists("mvn") || gradleCommand(repo) !== null;
34
+ default:
35
+ return false;
36
+ }
37
+ }
38
+ function gradleCommand(repo) {
39
+ for (const f of ["gradlew.bat", "gradlew"]) {
40
+ const p = path.join(repo, f);
41
+ if (fs.existsSync(p))
42
+ return p;
43
+ }
44
+ return commandExists("gradle") ? "gradle" : null;
45
+ }
46
+ /** Strip ANSI escapes so text-summary regexes work across terminal configs. */
47
+ function stripAnsi(s) {
48
+ return s.replace(/\x1b\[[0-9;]*m/g, "");
49
+ }
50
+ function pseudoSuite(framework, failed, passed, total, durationMs) {
51
+ return {
52
+ framework,
53
+ tests: [
54
+ {
55
+ name: failed > 0 ? `(${framework} suite: failures)` : `(${framework} suite)`,
56
+ status: failed > 0 ? "failed" : "passed",
57
+ },
58
+ ],
59
+ total,
60
+ passed,
61
+ failed,
62
+ durationMs,
63
+ };
64
+ }
65
+ /* ------------------------------------------------------------------ */
66
+ /* Go: `go test -json ./...` */
67
+ /* ------------------------------------------------------------------ */
68
+ /** Pure parser for `go test -json` stream. Exported for unit tests. */
69
+ export function parseGoTestOutput(stdout) {
70
+ const tests = [];
71
+ let failed = 0;
72
+ let passed = 0;
73
+ for (const line of stdout.split(/\r?\n/)) {
74
+ const t = line.trim();
75
+ if (!t.startsWith("{"))
76
+ continue;
77
+ let obj;
78
+ try {
79
+ obj = JSON.parse(t);
80
+ }
81
+ catch {
82
+ continue;
83
+ }
84
+ if (typeof obj.Test !== "string" || !obj.Test)
85
+ continue;
86
+ if (obj.Action === "fail") {
87
+ failed++;
88
+ tests.push({ name: obj.Test, file: obj.Package, status: "failed" });
89
+ }
90
+ else if (obj.Action === "pass" || obj.Action === "skip") {
91
+ passed++;
92
+ tests.push({ name: obj.Test, file: obj.Package, status: "passed" });
93
+ }
94
+ }
95
+ return { tests, passed, failed };
96
+ }
97
+ async function runGo(repo) {
98
+ if (!commandExists("go"))
99
+ return null;
100
+ const start = performance.now();
101
+ const r = await safeExecAsync("go", ["test", "-json", "./..."], repo, 300000);
102
+ const durationMs = Math.round(performance.now() - start);
103
+ const { tests, passed, failed } = parseGoTestOutput(r.stdout);
104
+ if (tests.length === 0) {
105
+ if (r.code === 0)
106
+ return null;
107
+ return {
108
+ framework: "go test",
109
+ tests: [],
110
+ total: 0,
111
+ passed: 0,
112
+ failed: 0,
113
+ durationMs,
114
+ unparseable: "go test produced no parseable results",
115
+ };
116
+ }
117
+ return { framework: "go test", tests, total: tests.length, passed, failed, durationMs };
118
+ }
119
+ /* ------------------------------------------------------------------ */
120
+ /* Rust: `cargo test -- --format json` (libtest JSON, Rust >= 1.70) */
121
+ /* ------------------------------------------------------------------ */
122
+ /** Pure parser for cargo's libtest JSON stream. Exported for unit tests. */
123
+ export function parseCargoTestOutput(stdout) {
124
+ const tests = [];
125
+ let failed = 0;
126
+ let passed = 0;
127
+ for (const line of stdout.split(/\r?\n/)) {
128
+ const t = line.trim();
129
+ if (!t.startsWith("{"))
130
+ continue;
131
+ let obj;
132
+ try {
133
+ obj = JSON.parse(t);
134
+ }
135
+ catch {
136
+ continue;
137
+ }
138
+ if (obj.type !== "test" || typeof obj.event !== "string")
139
+ continue;
140
+ if (obj.event === "failed") {
141
+ failed++;
142
+ tests.push({ name: obj.name ?? "", status: "failed" });
143
+ }
144
+ else if (obj.event === "ok" || obj.event === "ignored") {
145
+ passed++;
146
+ tests.push({ name: obj.name ?? "", status: "passed" });
147
+ }
148
+ }
149
+ return { tests, passed, failed };
150
+ }
151
+ async function runCargo(repo) {
152
+ if (!commandExists("cargo"))
153
+ return null;
154
+ const start = performance.now();
155
+ const r = await safeExecAsync("cargo", ["test", "--", "--format", "json"], repo, 300000);
156
+ const durationMs = Math.round(performance.now() - start);
157
+ const { tests, passed, failed } = parseCargoTestOutput(r.stdout);
158
+ if (tests.length === 0) {
159
+ if (r.code === 0)
160
+ return null;
161
+ return {
162
+ framework: "cargo test",
163
+ tests: [],
164
+ total: 0,
165
+ passed: 0,
166
+ failed: 0,
167
+ durationMs,
168
+ unparseable: "cargo test produced no parseable results (--format json needs Rust >= 1.70)",
169
+ };
170
+ }
171
+ return { framework: "cargo test", tests, total: tests.length, passed, failed, durationMs };
172
+ }
173
+ /* ------------------------------------------------------------------ */
174
+ /* Flutter: `flutter test --machine` (JSON lines) */
175
+ /* ------------------------------------------------------------------ */
176
+ /** Pure parser for flutter --machine stream. Exported for unit tests. */
177
+ export function parseFlutterMachineOutput(stdout) {
178
+ const names = new Map();
179
+ const tests = [];
180
+ let failed = 0;
181
+ let passed = 0;
182
+ for (const line of stdout.split(/\r?\n/)) {
183
+ const t = line.trim();
184
+ if (!t.startsWith("{"))
185
+ continue;
186
+ let obj;
187
+ try {
188
+ obj = JSON.parse(t);
189
+ }
190
+ catch {
191
+ continue;
192
+ }
193
+ if (obj.type === "testStart" && typeof obj.testID === "number") {
194
+ names.set(obj.testID, obj.name ?? "");
195
+ }
196
+ else if (obj.type === "testDone" && typeof obj.testID === "number") {
197
+ if (obj.result === "failure") {
198
+ failed++;
199
+ tests.push({ name: names.get(obj.testID) ?? "", status: "failed" });
200
+ }
201
+ else if (obj.result === "success" || obj.result === "skipped") {
202
+ passed++;
203
+ tests.push({ name: names.get(obj.testID) ?? "", status: "passed" });
204
+ }
205
+ }
206
+ }
207
+ return { tests, passed, failed };
208
+ }
209
+ async function runFlutter(repo) {
210
+ if (!commandExists("flutter"))
211
+ return null;
212
+ const start = performance.now();
213
+ const r = await safeExecAsync("flutter", ["test", "--machine"], repo, 300000);
214
+ const durationMs = Math.round(performance.now() - start);
215
+ const { tests, passed, failed } = parseFlutterMachineOutput(r.stdout);
216
+ if (tests.length === 0) {
217
+ if (r.code === 0)
218
+ return null;
219
+ return {
220
+ framework: "flutter test",
221
+ tests: [],
222
+ total: 0,
223
+ passed: 0,
224
+ failed: 0,
225
+ durationMs,
226
+ unparseable: "flutter test produced no parseable results",
227
+ };
228
+ }
229
+ return { framework: "flutter test", tests, total: tests.length, passed, failed, durationMs };
230
+ }
231
+ /* ------------------------------------------------------------------ */
232
+ /* .NET: `dotnet test` (text summary) */
233
+ /* ------------------------------------------------------------------ */
234
+ /** Pure parser for the dotnet test summary line. Exported for unit tests. */
235
+ export function parseDotnetSummary(output) {
236
+ const out = stripAnsi(output);
237
+ const m = out.match(/\(?(?:Passed!|Failed!|Skipped!)\s*-\s*Failed:\s*(\d+),\s*Passed:\s*(\d+),\s*Skipped:\s*(\d+),\s*Total:\s*(\d+)/i);
238
+ if (!m)
239
+ return null;
240
+ return { passed: Number(m[2]), failed: Number(m[1]), total: Number(m[4]) };
241
+ }
242
+ async function runDotnet(repo) {
243
+ if (!commandExists("dotnet"))
244
+ return null;
245
+ const start = performance.now();
246
+ const r = await safeExecAsync("dotnet", ["test"], repo, 300000);
247
+ const durationMs = Math.round(performance.now() - start);
248
+ const parsed = parseDotnetSummary(r.stdout + "\n" + r.stderr);
249
+ if (!parsed) {
250
+ if (r.code === 0)
251
+ return null;
252
+ return {
253
+ framework: "dotnet test",
254
+ tests: [],
255
+ total: 0,
256
+ passed: 0,
257
+ failed: 0,
258
+ durationMs,
259
+ unparseable: "dotnet test output not parseable",
260
+ };
261
+ }
262
+ if (parsed.total === 0)
263
+ return null;
264
+ return pseudoSuite("dotnet test", parsed.failed, parsed.passed, parsed.total, durationMs);
265
+ }
266
+ /* ------------------------------------------------------------------ */
267
+ /* Java: maven (surefire summaries) or gradle (build/test-results XML) */
268
+ /* ------------------------------------------------------------------ */
269
+ async function runJava(repo) {
270
+ if (fs.existsSync(path.join(repo, "pom.xml")))
271
+ return runMaven(repo);
272
+ if (gradleCommand(repo))
273
+ return runGradle(repo);
274
+ return null;
275
+ }
276
+ /** Pure parser for maven surefire "Tests run:" summaries. Exported for unit tests. */
277
+ export function parseMavenSummary(output) {
278
+ let total = 0;
279
+ let failed = 0;
280
+ const re = /Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/gi;
281
+ let m;
282
+ while ((m = re.exec(output)) !== null) {
283
+ total += Number(m[1]);
284
+ failed += Number(m[2]) + Number(m[3]);
285
+ }
286
+ return { passed: total - failed, failed, total };
287
+ }
288
+ async function runMaven(repo) {
289
+ const start = performance.now();
290
+ const r = await safeExecAsync("mvn", ["test"], repo, 300000);
291
+ const durationMs = Math.round(performance.now() - start);
292
+ const parsed = parseMavenSummary(r.stdout + "\n" + r.stderr);
293
+ if (parsed.total === 0) {
294
+ if (r.code === 0)
295
+ return null;
296
+ return {
297
+ framework: "maven (surefire)",
298
+ tests: [],
299
+ total: 0,
300
+ passed: 0,
301
+ failed: 0,
302
+ durationMs,
303
+ unparseable: "maven produced no surefire test summary",
304
+ };
305
+ }
306
+ return pseudoSuite("maven (surefire)", parsed.failed, parsed.passed, parsed.total, durationMs);
307
+ }
308
+ /** Pure parser for gradle's build/test-results XML. Exported for unit tests. */
309
+ export function parseGradleXml(xml) {
310
+ let total = 0;
311
+ let failed = 0;
312
+ for (const tag of xml.matchAll(/<testsuite\b([^>]*)>/g)) {
313
+ const a = tag[1];
314
+ const tests = /tests="(\d+)"/.exec(a);
315
+ if (!tests)
316
+ continue;
317
+ const failures = /failures="(\d+)"/.exec(a);
318
+ const errors = /errors="(\d+)"/.exec(a);
319
+ total += Number(tests[1]);
320
+ failed += Number(failures?.[1] ?? 0) + Number(errors?.[1] ?? 0);
321
+ }
322
+ return { passed: total - failed, failed, total };
323
+ }
324
+ async function runGradle(repo) {
325
+ const cmd = gradleCommand(repo);
326
+ if (!cmd)
327
+ return null;
328
+ const start = performance.now();
329
+ const r = await safeExecAsync(cmd, ["test"], repo, 300000);
330
+ const durationMs = Math.round(performance.now() - start);
331
+ const out = r.stdout + "\n" + r.stderr;
332
+ let parsed = null;
333
+ const resultsDir = path.join(repo, "build", "test-results", "test");
334
+ if (fs.existsSync(resultsDir)) {
335
+ const stack = [resultsDir];
336
+ while (stack.length) {
337
+ const dir = stack.pop();
338
+ let entries;
339
+ try {
340
+ entries = fs.readdirSync(dir, { withFileTypes: true });
341
+ }
342
+ catch {
343
+ continue;
344
+ }
345
+ for (const e of entries) {
346
+ if (e.isDirectory())
347
+ stack.push(path.join(dir, e.name));
348
+ else if (e.isFile() && e.name.endsWith(".xml")) {
349
+ try {
350
+ const p = parseGradleXml(fs.readFileSync(path.join(dir, e.name), "utf8"));
351
+ parsed = parsed
352
+ ? {
353
+ passed: parsed.passed + p.passed,
354
+ failed: parsed.failed + p.failed,
355
+ total: parsed.total + p.total,
356
+ }
357
+ : p;
358
+ }
359
+ catch {
360
+ /* ignore */
361
+ }
362
+ }
363
+ }
364
+ }
365
+ }
366
+ if (!parsed || parsed.total === 0) {
367
+ if (/BUILD SUCCESSFUL/i.test(out))
368
+ return null;
369
+ return {
370
+ framework: "gradle",
371
+ tests: [],
372
+ total: 0,
373
+ passed: 0,
374
+ failed: 0,
375
+ durationMs,
376
+ unparseable: "gradle produced no test-results XML",
377
+ };
378
+ }
379
+ return pseudoSuite("gradle", parsed.failed, parsed.passed, parsed.total, durationMs);
380
+ }
381
+ //# sourceMappingURL=suiteRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suiteRunner.js","sourceRoot":"","sources":["../../src/analyzers/suiteRunner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { TestsResult } from "./types.js";
2
+ export declare function analyzeTests(repo: string): Promise<TestsResult>;
@@ -0,0 +1,215 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { commandExists, detectLanguage, safeExecAsync } from "./util.js";
4
+ import { nonJsToolchainPresent, runNonJsSuite } from "./suiteRunner.js";
5
+ export async function analyzeTests(repo) {
6
+ const lang = detectLanguage(repo);
7
+ const empty = {
8
+ status: "skipped",
9
+ note: "no test framework detected",
10
+ total: 0,
11
+ passed: 0,
12
+ failed: 0,
13
+ durationMs: 0,
14
+ };
15
+ if (lang === "go" || lang === "rust" || lang === "dart" || lang === "dotnet" || lang === "java") {
16
+ if (!nonJsToolchainPresent(lang, repo)) {
17
+ return { ...empty, note: `no ${lang} test toolchain found on PATH` };
18
+ }
19
+ const sr = await runNonJsSuite(repo);
20
+ if (!sr)
21
+ return { ...empty, note: `no tests discovered by the ${lang} runner` };
22
+ if (sr.total === 0) {
23
+ return {
24
+ status: "error",
25
+ note: sr.unparseable ?? "runner produced no results",
26
+ total: 0,
27
+ passed: 0,
28
+ failed: 0,
29
+ durationMs: sr.durationMs,
30
+ };
31
+ }
32
+ return {
33
+ status: "ok",
34
+ framework: sr.framework,
35
+ total: sr.total,
36
+ passed: sr.passed,
37
+ failed: sr.failed,
38
+ durationMs: sr.durationMs,
39
+ };
40
+ }
41
+ if (lang === "python") {
42
+ if (!commandExists("pytest"))
43
+ return empty;
44
+ const start = performance.now();
45
+ const r = await safeExecAsync("pytest", ["-q"], repo, 180000);
46
+ const durationMs = Math.round(performance.now() - start);
47
+ const m = r.stdout.match(/(\d+)\s+passed/);
48
+ const failed = r.stdout.match(/(\d+)\s+failed/);
49
+ const total = (m ? Number(m[1]) : 0) + (failed ? Number(failed[1]) : 0);
50
+ return {
51
+ status: "ok",
52
+ framework: "pytest",
53
+ total,
54
+ passed: m ? Number(m[1]) : 0,
55
+ failed: failed ? Number(failed[1]) : 0,
56
+ durationMs,
57
+ };
58
+ }
59
+ // JS/TS
60
+ const pkgPath = path.join(repo, "package.json");
61
+ let pkg = {};
62
+ if (fs.existsSync(pkgPath)) {
63
+ try {
64
+ pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
65
+ }
66
+ catch {
67
+ pkg = {};
68
+ }
69
+ }
70
+ const deps = {
71
+ ...(pkg.dependencies ?? {}),
72
+ ...(pkg.devDependencies ?? {}),
73
+ };
74
+ const hasJest = !!deps.jest ||
75
+ fs.existsSync(path.join(repo, "jest.config.js")) ||
76
+ fs.existsSync(path.join(repo, "jest.config.ts"));
77
+ const hasVitest = !!deps.vitest || fs.existsSync(path.join(repo, "vitest.config.ts"));
78
+ const hasBin = (name) => commandExists(name) || fs.existsSync(path.join(repo, "node_modules", ".bin", name));
79
+ if (hasJest && hasBin("jest")) {
80
+ return runJest(repo);
81
+ }
82
+ if (hasVitest && hasBin("vitest")) {
83
+ return runVitest(repo);
84
+ }
85
+ return empty;
86
+ }
87
+ function jestCommand(repo) {
88
+ const localCli = path.join(repo, "node_modules", "jest", "bin", "jest.js");
89
+ if (fs.existsSync(localCli))
90
+ return { cmd: "node", args: [localCli] };
91
+ if (commandExists("jest"))
92
+ return { cmd: "jest", args: [] };
93
+ return { cmd: "", args: [] };
94
+ }
95
+ async function runJest(repo) {
96
+ const j = jestCommand(repo);
97
+ if (!j.cmd) {
98
+ return {
99
+ status: "skipped",
100
+ note: "jest not installed",
101
+ total: 0,
102
+ passed: 0,
103
+ failed: 0,
104
+ durationMs: 0,
105
+ };
106
+ }
107
+ const cacheDir = path.join(repo, ".pitstop", "cache", "jest");
108
+ fs.mkdirSync(cacheDir, { recursive: true });
109
+ const start = performance.now();
110
+ const r = await safeExecAsync(j.cmd, [...j.args, "--json", "--coverage", "--coverageReporters=json-summary", "--cacheDirectory", cacheDir], repo, 180000);
111
+ const durationMs = Math.round(performance.now() - start);
112
+ let json;
113
+ try {
114
+ json = JSON.parse(r.stdout);
115
+ }
116
+ catch {
117
+ return {
118
+ status: "error",
119
+ note: "jest produced no JSON",
120
+ framework: "jest",
121
+ total: 0,
122
+ passed: 0,
123
+ failed: 0,
124
+ durationMs,
125
+ };
126
+ }
127
+ let coverage;
128
+ const summary = path.join(repo, "coverage", "coverage-summary.json");
129
+ if (fs.existsSync(summary)) {
130
+ try {
131
+ const c = JSON.parse(fs.readFileSync(summary, "utf8"));
132
+ coverage = c.total?.lines?.pct;
133
+ }
134
+ catch {
135
+ /* ignore */
136
+ }
137
+ }
138
+ return {
139
+ status: "ok",
140
+ framework: "jest",
141
+ total: json.numTotalTests ?? 0,
142
+ passed: json.numPassedTests ?? 0,
143
+ failed: json.numFailedTests ?? 0,
144
+ durationMs,
145
+ coverage,
146
+ };
147
+ }
148
+ function vitestCommand(repo) {
149
+ const localCli = path.join(repo, "node_modules", "vitest", "vitest.mjs");
150
+ if (fs.existsSync(localCli))
151
+ return { cmd: "node", args: [localCli] };
152
+ if (commandExists("vitest"))
153
+ return { cmd: "vitest", args: [] };
154
+ return { cmd: "", args: [] };
155
+ }
156
+ async function runVitest(repo) {
157
+ const v = vitestCommand(repo);
158
+ if (!v.cmd) {
159
+ return {
160
+ status: "skipped",
161
+ note: "vitest not installed",
162
+ total: 0,
163
+ passed: 0,
164
+ failed: 0,
165
+ durationMs: 0,
166
+ };
167
+ }
168
+ const tmp = path.join(repo, ".pitstop", "vitest-report.json");
169
+ fs.mkdirSync(path.dirname(tmp), { recursive: true });
170
+ const start = performance.now();
171
+ const r = await safeExecAsync(v.cmd, [...v.args, "run", "--reporter=json", "--outputFile", tmp], repo, 180000);
172
+ const durationMs = Math.round(performance.now() - start);
173
+ let json;
174
+ if (fs.existsSync(tmp)) {
175
+ try {
176
+ json = JSON.parse(fs.readFileSync(tmp, "utf8"));
177
+ }
178
+ catch {
179
+ json = undefined;
180
+ }
181
+ }
182
+ if (!json) {
183
+ return {
184
+ status: "error",
185
+ note: "vitest produced no JSON",
186
+ framework: "vitest",
187
+ total: 0,
188
+ passed: 0,
189
+ failed: 0,
190
+ durationMs,
191
+ };
192
+ }
193
+ const files = json.testResults ?? [];
194
+ let total = 0;
195
+ let passed = 0;
196
+ let failed = 0;
197
+ for (const f of files) {
198
+ total += f.assertionResults?.length ?? 0;
199
+ for (const a of f.assertionResults ?? []) {
200
+ if (a.status === "passed")
201
+ passed++;
202
+ else if (a.status === "failed")
203
+ failed++;
204
+ }
205
+ }
206
+ return {
207
+ status: "ok",
208
+ framework: "vitest",
209
+ total,
210
+ passed,
211
+ failed,
212
+ durationMs,
213
+ };
214
+ }
215
+ //# sourceMappingURL=tests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tests.js","sourceRoot":"","sources":["../../src/analyzers/tests.ts"],"names":[],"mappings":"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"}