Skip to content

Commit 50b5238

Browse files
committed
refactor(qa): share repo path resolution
1 parent 0cf9413 commit 50b5238

3 files changed

Lines changed: 43 additions & 52 deletions

File tree

extensions/qa-lab/src/repo-path.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
4+
export type QaRepoPathKind = "file" | "directory";
5+
6+
function walkUpDirectories(start: string): string[] {
7+
const roots: string[] = [];
8+
let current = path.resolve(start);
9+
while (true) {
10+
roots.push(current);
11+
const parent = path.dirname(current);
12+
if (parent === current) {
13+
return roots;
14+
}
15+
current = parent;
16+
}
17+
}
18+
19+
export function resolveQaRepoPath(
20+
startDir: string,
21+
relativePath: string,
22+
kind: QaRepoPathKind = "file",
23+
): string | null {
24+
for (const dir of walkUpDirectories(startDir)) {
25+
const candidate = path.join(dir, relativePath);
26+
if (!fs.existsSync(candidate)) {
27+
continue;
28+
}
29+
const stat = fs.statSync(candidate);
30+
if ((kind === "file" && stat.isFile()) || (kind === "directory" && stat.isDirectory())) {
31+
return candidate;
32+
}
33+
}
34+
return null;
35+
}

extensions/qa-lab/src/scenario-catalog.ts

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import path from "node:path";
44
import YAML from "yaml";
55
import { z } from "zod";
66
import { isRepoRootRelativeRef } from "./cli-paths.js";
7+
import { resolveQaRepoPath, type QaRepoPathKind } from "./repo-path.js";
78

89
export const DEFAULT_QA_AGENT_IDENTITY_MARKDOWN = `# Dev C-3PO
910
@@ -292,37 +293,14 @@ const repoPathCache = new Map<string, string | null>();
292293
let qaScenarioYamlPathsCache: string[] | null = null;
293294
let qaScenarioPackCache: QaScenarioPack | null = null;
294295

295-
function walkUpDirectories(start: string): string[] {
296-
const roots: string[] = [];
297-
let current = path.resolve(start);
298-
while (true) {
299-
roots.push(current);
300-
const parent = path.dirname(current);
301-
if (parent === current) {
302-
return roots;
303-
}
304-
current = parent;
305-
}
306-
}
307-
308-
function resolveRepoPath(relativePath: string, kind: "file" | "directory" = "file"): string | null {
296+
function resolveRepoPath(relativePath: string, kind: QaRepoPathKind = "file"): string | null {
309297
const cacheKey = `${kind}:${relativePath}`;
310298
if (repoPathCache.has(cacheKey)) {
311299
return repoPathCache.get(cacheKey) ?? null;
312300
}
313-
for (const dir of walkUpDirectories(import.meta.dirname)) {
314-
const candidate = path.join(dir, relativePath);
315-
if (!fs.existsSync(candidate)) {
316-
continue;
317-
}
318-
const stat = fs.statSync(candidate);
319-
if ((kind === "file" && stat.isFile()) || (kind === "directory" && stat.isDirectory())) {
320-
repoPathCache.set(cacheKey, candidate);
321-
return candidate;
322-
}
323-
}
324-
repoPathCache.set(cacheKey, null);
325-
return null;
301+
const resolved = resolveQaRepoPath(import.meta.dirname, relativePath, kind);
302+
repoPathCache.set(cacheKey, resolved);
303+
return resolved;
326304
}
327305

328306
export function hasQaScenarioPack(): boolean {

extensions/qa-lab/src/scorecard-taxonomy.ts

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import fs from "node:fs";
33
import path from "node:path";
44
import YAML from "yaml";
55
import { z } from "zod";
6+
import { resolveQaRepoPath, type QaRepoPathKind } from "./repo-path.js";
67
import type { QaSeedScenarioWithSource } from "./scenario-catalog.js";
78

89
export const QA_MATURITY_TAXONOMY_PATH = "taxonomy.yaml";
@@ -191,31 +192,8 @@ type MaturityCoverageRef = {
191192
surfaceId: string;
192193
};
193194

194-
function walkUpDirectories(start: string): string[] {
195-
const roots: string[] = [];
196-
let current = path.resolve(start);
197-
while (true) {
198-
roots.push(current);
199-
const parent = path.dirname(current);
200-
if (parent === current) {
201-
return roots;
202-
}
203-
current = parent;
204-
}
205-
}
206-
207-
function resolveRepoPath(relativePath: string, kind: "file" | "directory" = "file") {
208-
for (const dir of walkUpDirectories(import.meta.dirname)) {
209-
const candidate = path.join(dir, relativePath);
210-
if (!fs.existsSync(candidate)) {
211-
continue;
212-
}
213-
const stat = fs.statSync(candidate);
214-
if ((kind === "file" && stat.isFile()) || (kind === "directory" && stat.isDirectory())) {
215-
return candidate;
216-
}
217-
}
218-
return null;
195+
function resolveRepoPath(relativePath: string, kind: QaRepoPathKind = "file") {
196+
return resolveQaRepoPath(import.meta.dirname, relativePath, kind);
219197
}
220198

221199
function repoRootFromPath(filePath: string) {

0 commit comments

Comments
 (0)