Skip to content

Commit 752d891

Browse files
committed
feat: making multi repo
1 parent 443d1fc commit 752d891

File tree

5 files changed

+94
-28
lines changed

5 files changed

+94
-28
lines changed

vscode/extension/package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@
3232
"type": "object",
3333
"title": "SQLMesh",
3434
"properties": {
35-
"sqlmesh.projectPath": {
36-
"type": "string",
37-
"default": "",
38-
"markdownDescription": "The path to the SQLMesh project. If not set, the extension will try to find the project root automatically. If set, the extension will use the project root as the workspace path, e.g. it will run `sqlmesh` and `sqlmesh_lsp` in the project root. The path can be absolute `/Users/sqlmesh_user/sqlmesh_project/sushi` or relative `./project_folder/sushi` to the workspace root."
35+
"sqlmesh.projectPaths": {
36+
"type": "array",
37+
"items": {
38+
"type": "string"
39+
},
40+
"default": [],
41+
"description": "The path to the SQLMesh project. If not set, the extension will try to find the project root automatically. If set, the extension will use the project root as the workspace path, e.g. it will run `sqlmesh` and `sqlmesh_lsp` in the project root. The path can be absolute `/Users/sqlmesh_user/sqlmesh_project/sushi` or relative `./project_folder/sushi` to the workspace root. Multiple paths can be used for multi-project setups."
3942
},
4043
"sqlmesh.lspEntrypoint": {
4144
"type": "string",

vscode/extension/src/utilities/config.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { workspace, WorkspaceFolder } from 'vscode'
22
import path from 'path'
33
import fs from 'fs'
4-
import { Result, err, ok } from '@bus/result'
4+
import { Result, err, isErr, ok } from '@bus/result'
55
import { traceVerbose, traceInfo } from './common/log'
66
import { parse } from 'shell-quote'
77
import { z } from 'zod'
88

9-
export interface SqlmeshConfiguration {
10-
projectPath: string
11-
lspEntryPoint: string
12-
}
9+
const sqlmeshConfigurationSchema = z.object({
10+
projectPaths: z.array(z.string()),
11+
lspEntryPoint: z.string(),
12+
})
13+
14+
export type SqlmeshConfiguration = z.infer<typeof sqlmeshConfigurationSchema>
1315

1416
/**
1517
* Get the SQLMesh configuration from VS Code settings.
@@ -18,12 +20,18 @@ export interface SqlmeshConfiguration {
1820
*/
1921
function getSqlmeshConfiguration(): SqlmeshConfiguration {
2022
const config = workspace.getConfiguration('sqlmesh')
21-
const projectPath = config.get<string>('projectPath', '')
23+
const projectPaths = config.get<string[]>('projectPaths', [])
2224
const lspEntryPoint = config.get<string>('lspEntrypoint', '')
23-
return {
24-
projectPath,
25+
const parsed = sqlmeshConfigurationSchema.safeParse({
26+
projectPaths,
2527
lspEntryPoint,
28+
})
29+
if (!parsed.success) {
30+
throw new Error(
31+
`Invalid SQLMesh configuration: ${JSON.stringify(parsed.error)}`,
32+
)
2633
}
34+
return parsed.data
2735
}
2836

2937
const stringsArray = z.array(z.string())
@@ -57,31 +65,47 @@ export function getSqlmeshLspEntryPoint():
5765
}
5866

5967
/**
60-
* Validate and resolve the project path from configuration.
68+
* Validate and resolve the project paths from configuration.
6169
* If no project path is configured, use the workspace folder.
6270
* If the project path is configured, it must be a directory that contains a SQLMesh project.
6371
*
6472
* @param workspaceFolder The current workspace folder
65-
* @returns A Result containing the resolved project path or an error
73+
* @returns A Result containing the resolved project paths or an error
6674
*/
6775
export function resolveProjectPath(
6876
workspaceFolder: WorkspaceFolder,
69-
): Result<string, string> {
77+
): Result<string[], string> {
7078
const config = getSqlmeshConfiguration()
7179

72-
if (!config.projectPath) {
80+
if (config.projectPaths.length === 0) {
7381
// If no project path is configured, use the workspace folder
7482
traceVerbose('No project path configured, using workspace folder')
75-
return ok(workspaceFolder.uri.fsPath)
83+
return ok([workspaceFolder.uri.fsPath])
7684
}
85+
86+
const resolvedPaths: string[] = []
87+
for (const projectPath of config.projectPaths) {
88+
const result = resolveSingleProjectPath(workspaceFolder, projectPath)
89+
if (isErr(result)) {
90+
return result
91+
}
92+
resolvedPaths.push(result.value)
93+
}
94+
return ok(resolvedPaths)
95+
}
96+
97+
function resolveSingleProjectPath(
98+
workspaceFolder: WorkspaceFolder,
99+
projectPath: string,
100+
): Result<string, string> {
77101
let resolvedPath: string
78102

79103
// Check if the path is absolute
80-
if (path.isAbsolute(config.projectPath)) {
81-
resolvedPath = config.projectPath
104+
if (path.isAbsolute(projectPath)) {
105+
resolvedPath = projectPath
82106
} else {
83107
// Resolve relative path from workspace root
84-
resolvedPath = path.join(workspaceFolder.uri.fsPath, config.projectPath)
108+
resolvedPath = path.join(workspaceFolder.uri.fsPath, projectPath)
85109
}
86110

87111
// Normalize the path

vscode/extension/src/utilities/sqlmesh/sqlmesh.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ export const isTcloudProject = async (): Promise<Result<boolean, string>> => {
6969
if (isErr(resolvedPath)) {
7070
return err(resolvedPath.error)
7171
}
72-
const tcloudYamlPath = path.join(resolvedPath.value, 'tcloud.yaml')
73-
const tcloudYmlPath = path.join(resolvedPath.value, 'tcloud.yml')
72+
const tcloudYamlPath = path.join(resolvedPath.value[0], 'tcloud.yaml')
73+
const tcloudYmlPath = path.join(resolvedPath.value[0], 'tcloud.yml')
7474
const isTcloudYamlFilePresent = fs.existsSync(tcloudYamlPath)
7575
const isTcloudYmlFilePresent = fs.existsSync(tcloudYmlPath)
7676
if (isTcloudYamlFilePresent || isTcloudYmlFilePresent) {
@@ -144,7 +144,7 @@ export const isSqlmeshEnterpriseInstalled = async (): Promise<
144144
})
145145
}
146146
const called = await execAsync(tcloudBin.value.bin, ['is_sqlmesh_installed'], {
147-
cwd: resolvedPath.value,
147+
cwd: resolvedPath.value[0],
148148
env: tcloudBin.value.env,
149149
})
150150
if (called.exitCode !== 0) {
@@ -185,7 +185,7 @@ export const installSqlmeshEnterprise = async (
185185
}
186186
const called = await execAsync(tcloudBin.value.bin, ['install_sqlmesh'], {
187187
signal: abortController.signal,
188-
cwd: resolvedPath.value,
188+
cwd: resolvedPath.value[0],
189189
env: tcloudBin.value.env,
190190
})
191191
if (called.exitCode !== 0) {
@@ -325,7 +325,7 @@ export const sqlmeshLspExec = async (): Promise<
325325
traceLog(`Using configured SQLMesh LSP entry point: ${configuredLSPExec.entrypoint} ${configuredLSPExec.args.join(' ')}`)
326326
return ok({
327327
bin: configuredLSPExec.entrypoint,
328-
workspacePath,
328+
workspacePath: workspacePath[0],
329329
env: process.env,
330330
args: configuredLSPExec.args,
331331
})
@@ -381,7 +381,7 @@ export const sqlmeshLspExec = async (): Promise<
381381
if (isSemVerGreaterThanOrEqual(tcloudBinVersion.value, [2, 10, 1])) {
382382
return ok ({
383383
bin: tcloudBin.value.bin,
384-
workspacePath,
384+
workspacePath: workspacePath[0],
385385
env: tcloudBin.value.env,
386386
args: ['sqlmesh_lsp'],
387387
})
@@ -407,7 +407,7 @@ export const sqlmeshLspExec = async (): Promise<
407407
}
408408
return ok({
409409
bin: binPath,
410-
workspacePath,
410+
workspacePath: workspacePath[0],
411411
env: env.value,
412412
args: [],
413413
})
@@ -427,7 +427,7 @@ export const sqlmeshLspExec = async (): Promise<
427427
}
428428
return ok({
429429
bin: sqlmeshLSP,
430-
workspacePath,
430+
workspacePath: workspacePath[0],
431431
env: env.value,
432432
args: [],
433433
})
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import path from 'path'
2+
import { test, expect } from './fixtures'
3+
import { MULTI_SOURCE_PATH, openLineageView, openServerPage, SUSHI_SOURCE_PATH, waitForLoadedSQLMesh } from './utils'
4+
import fs from 'fs-extra'
5+
6+
test('should work with multi-project setups', async ({
7+
page,
8+
sharedCodeServer,
9+
tempDir,
10+
}) => {
11+
await fs.copy(MULTI_SOURCE_PATH, tempDir)
12+
13+
// Create the multi project config file
14+
const settingsFilePath = path.join(tempDir, '.vscode','settings.json')
15+
const settings = {
16+
"sqlmesh.projectPaths": [
17+
"./repo_1",
18+
"./repo_2"
19+
]
20+
}
21+
await fs.writeJson(settingsFilePath, settings)
22+
23+
// Open the server
24+
await openServerPage(page, tempDir, sharedCodeServer)
25+
26+
// Wait for for the project to be loaded
27+
await waitForLoadedSQLMesh(page)
28+
29+
// Open the linage view
30+
await openLineageView(page)
31+
})

vscode/extension/tests/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ export const SUSHI_SOURCE_PATH = path.join(
1414
'examples',
1515
'sushi',
1616
)
17+
export const MULTI_SOURCE_PATH = path.join(
18+
__dirname,
19+
'..',
20+
'..',
21+
'..',
22+
'examples',
23+
'multi',
24+
)
1725
export const REPO_ROOT = path.join(__dirname, '..', '..', '..')
1826

1927
/**

0 commit comments

Comments
 (0)