Preview local git repo project workspace files

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-06-09 21:35:48 +00:00
1 parent df1ab634f7
commit 50feeb312a
2 files changed
+47 -3

No files matched your search

+44 -1
View File
@@ -58,6 +58,7 @@ async function seedGraph(db: Db, input: {
targetProjectRoot?: string;
executionRoot?: string | null;
projectSourceType?: string;
targetProjectSourceType?: string;
}): Promise<TestGraph> {
const suffix = crypto.randomUUID().slice(0, 8);
const companyId = crypto.randomUUID();
@@ -111,7 +112,7 @@ async function seedGraph(db: Db, input: {
companyId,
projectId: targetProjectId,
name: "Target workspace",
sourceType: "local_path",
sourceType: input.targetProjectSourceType ?? "local_path",
cwd: input.targetProjectRoot ?? input.projectRoot,
isPrimary: true,
},
@@ -286,6 +287,48 @@ describeEmbeddedPostgres("workspace file resources", () => {
expect(JSON.stringify(read?.details)).not.toContain(targetProjectRoot);
});
it("reads explicit cross-project git_repo workspaces with a local checkout", async () => {
const { root, projectRoot, targetProjectRoot, executionRoot } = await makeWorkspace();
const graph = await seedGraph(db, {
projectRoot,
targetProjectRoot,
executionRoot,
targetProjectSourceType: "git_repo",
});
const readmePath = "content-os/cases/active/2026-06-06-pap-10199-bundled-skills/README.md";
await fs.mkdir(path.join(targetProjectRoot, path.dirname(readmePath)), { recursive: true });
await fs.writeFile(path.join(targetProjectRoot, readmePath), "# Bundled skills\n\nRendered from content project.\n", "utf8");
const app = createApp(db, {
type: "board",
userId: "board-user",
companyIds: [graph.companyId],
source: "session",
isInstanceAdmin: false,
});
const res = await request(app)
.get(`/api/issues/${graph.issueId}/file-resources/content`)
.query({
projectId: graph.targetProjectId,
workspaceId: graph.targetProjectWorkspaceId,
path: readmePath,
});
expect(res.status).toBe(200);
expect(res.body.resource).toMatchObject({
workspaceKind: "project_workspace",
workspaceId: graph.targetProjectWorkspaceId,
projectId: graph.targetProjectId,
projectName: "Target project",
displayPath: `Target project / ${readmePath}`,
provider: "git_repo",
previewKind: "text",
});
expect(res.body.content.encoding).toBe("utf8");
expect(res.body.content.data).toContain("# Bundled skills");
expect(JSON.stringify(res.body)).not.toContain(root);
});
it("denies explicit cross-company project workspaces", async () => {
const { projectRoot, targetProjectRoot, executionRoot } = await makeWorkspace();
const graph = await seedGraph(db, { projectRoot, targetProjectRoot, executionRoot });
@@ -27,6 +27,7 @@ const TEXT_SNIFF_BYTES = 4096;
const MAX_LIST_DEPTH = 20;
const GIT_STATUS_MAX_BUFFER_BYTES = 1024 * 1024;
const execFileAsync = promisify(execFile);
const LOCAL_PROJECT_WORKSPACE_SOURCE_TYPES = new Set(["local_path", "non_git_path", "git_repo", "git_worktree"]);
const DENIED_SEGMENTS = new Set([
".git",
@@ -315,9 +316,9 @@ function candidateFromProjectWorkspace(
row: ProjectWorkspaceRow,
project?: { id: string; name: string } | null,
): WorkspaceCandidate {
const provider = row.sourceType === "git_worktree" ? "git_worktree" : row.sourceType === "local_path" ? "local_fs" : row.sourceType;
const provider = row.sourceType === "local_path" ? "local_fs" : row.sourceType;
const rootPath = row.cwd ?? null;
const remote = !["local_fs", "git_worktree"].includes(provider) || !rootPath;
const remote = !LOCAL_PROJECT_WORKSPACE_SOURCE_TYPES.has(row.sourceType) || !rootPath;
return {
workspaceKind: "project_workspace",
workspaceId: row.id,