From 9f1dd640c8c40959fc93badd04ab8e8b1b12365b Mon Sep 17 00:00:00 2001 From: somebody1234 Date: Fri, 23 Jan 2026 20:28:25 +1000 Subject: [PATCH 1/2] Fix loading GUI env values from config --- app/electron-client/src/guiConfig.ts | 4 +++- app/electron-client/watch.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/electron-client/src/guiConfig.ts b/app/electron-client/src/guiConfig.ts index 2d6a6a8ddcb3..c3aedb664eb3 100644 --- a/app/electron-client/src/guiConfig.ts +++ b/app/electron-client/src/guiConfig.ts @@ -11,7 +11,9 @@ const GUI_ENV_DIR = fileURLToPath(new URL('../../gui', import.meta.url)) function envToConfig(env: Record): $Config { // Conversion is technically unsafe, but practically is only used in Electron watch mode. return Object.fromEntries( - Object.entries(env).filter(([key]) => key.startsWith(GUI_ENV_PREFIX)), + Object.entries(env).flatMap(([key, value]) => + key.startsWith(GUI_ENV_PREFIX) ? [[key.slice(GUI_ENV_PREFIX.length), value]] : [], + ), ) as $Config } diff --git a/app/electron-client/watch.ts b/app/electron-client/watch.ts index 76d63d187750..a480bab67b94 100644 --- a/app/electron-client/watch.ts +++ b/app/electron-client/watch.ts @@ -65,6 +65,7 @@ console.log( ), ) await symlink(BACKEND_BUNDLE_PATH, path.join(IDE_DIR_PATH, 'enso'), 'dir') +await symlink(path.resolve('../gui'), path.resolve(IDE_DIR_PATH, '../../gui'), 'dir') const ELECTRON_FLAGS = process.env.ELECTRON_FLAGS == null ? [] : String(process.env.ELECTRON_FLAGS).split(' ') From aa977100e368ad6d066c18b205eb34c0bb1f28e7 Mon Sep 17 00:00:00 2001 From: somebody1234 Date: Fri, 23 Jan 2026 20:37:28 +1000 Subject: [PATCH 2/2] Forward exit code of project on executions list --- app/electron-client/src/index.ts | 10 ++++++---- .../src/projectService/ensoRunner.ts | 14 ++++---------- .../src/projectService/index.ts | 5 +++-- app/project-manager-shim/src/runProjects.ts | 16 ++++++++++------ 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/app/electron-client/src/index.ts b/app/electron-client/src/index.ts index 6ba0a7a49bc5..54e9885a2525 100644 --- a/app/electron-client/src/index.ts +++ b/app/electron-client/src/index.ts @@ -520,19 +520,21 @@ class App { const projectToOpen = args.startup.project if (projectToOpen.startsWith(`${DEEP_LINK_SCHEME}:`)) { try { - await runHybridProjectByUrl( + const exitCode = await runHybridProjectByUrl( EnsoPath(projectToOpen.toString()), await createRemoteBackend(), ) - this.exit(0) + // Forward exact failure exit code if available (or 0 if no error). + this.exit(exitCode) } catch (error) { console.error(`Error starting hybrid project '${projectToOpen}':`, error) return this.exit(1) } } else if (projectToOpen) { try { - await runLocalProjectByPath(Path(projectToOpen)) - this.exit(0) + const exitCode = await runLocalProjectByPath(Path(projectToOpen)) + // Forward exact failure exit code if available (or 0 if no error). + this.exit(exitCode) } catch (error) { console.error(`Error starting local project '${projectToOpen}':`, error) return this.exit(1) diff --git a/app/project-manager-shim/src/projectService/ensoRunner.ts b/app/project-manager-shim/src/projectService/ensoRunner.ts index ba0246223265..12ac4a943092 100644 --- a/app/project-manager-shim/src/projectService/ensoRunner.ts +++ b/app/project-manager-shim/src/projectService/ensoRunner.ts @@ -10,7 +10,7 @@ import { extract } from 'tar' import { Path } from './types.js' export interface Runner { - runProject(projectPath: Path, extraEnv?: readonly (readonly [string, string])[]): Promise + runProject(projectPath: Path, extraEnv?: readonly (readonly [string, string])[]): Promise createProject(path: Path, name: string, projectTemplate?: string): Promise openProject( projectPath: Path, @@ -129,11 +129,11 @@ export class EnsoRunner implements Runner { }) } - /** Run an existing Enso project at the specified path. */ + /** Run an existing Enso project at the specified path. Returns the exit code of the process. */ async runProject( projectPath: Path, extraEnv?: readonly (readonly [string, string])[], - ): Promise { + ): Promise { const args = ['--run', projectPath] const env = { ...process.env, ...(extraEnv ? Object.fromEntries(extraEnv) : {}) } const cwd = path.dirname(projectPath) @@ -144,13 +144,7 @@ export class EnsoRunner implements Runner { spawnedProcess.on('error', (error) => { reject(new Error(`Failed to spawn enso process: ${error.message}`)) }) - spawnedProcess.on('exit', (code) => { - if (code === 0) { - resolve() - } else { - reject(new Error(`Enso process exited with code ${code}.`)) - } - }) + spawnedProcess.on('exit', resolve) }) } diff --git a/app/project-manager-shim/src/projectService/index.ts b/app/project-manager-shim/src/projectService/index.ts index 4d49a7a1b34e..90ee21dd724d 100644 --- a/app/project-manager-shim/src/projectService/index.ts +++ b/app/project-manager-shim/src/projectService/index.ts @@ -175,11 +175,12 @@ export class ProjectService { } /** Run an existing Enso project at the specified path. */ - async runProject(projectId: UUID, projectsDirectory: Path, cloud?: CloudParams): Promise { + async runProject(projectId: UUID, projectsDirectory: Path, cloud?: CloudParams): Promise { const project = await this.getProject(projectId, projectsDirectory, true) this.logger.debug(`Running project '${project.path}'`) - await this.runner.runProject(project.path, this.projectEnvVars(cloud)) + const exitCode = await this.runner.runProject(project.path, this.projectEnvVars(cloud)) this.logger.debug(`Project '${project.path}' finished running`) + return exitCode } /** Open a project and starts its language server. */ diff --git a/app/project-manager-shim/src/runProjects.ts b/app/project-manager-shim/src/runProjects.ts index dc4cd53f62ca..02d182c789d5 100644 --- a/app/project-manager-shim/src/runProjects.ts +++ b/app/project-manager-shim/src/runProjects.ts @@ -29,7 +29,7 @@ function createProjectService(): ProjectService { export async function runHybridProjectByUrl( path: EnsoPath, remoteBackend: RemoteBackend, -): Promise { +): Promise { let project: ProjectEntry | undefined let asset: ProjectAsset | undefined try { @@ -56,13 +56,15 @@ export async function runHybridProjectByUrl( } const cloudProjectDirectoryPath = Path(asset.ensoPath.slice(0, asset.ensoPath.lastIndexOf('/'))) await remoteBackend.setHybridOpened(asset.id, asset.title) - await runLocalProjectByUuid(project.metadata.id, parentPath, { + const exitCode = await runLocalProjectByUuid(project.metadata.id, parentPath, { cloudProjectDirectoryPath, cloudProjectId: asset.id, cloudProjectSessionId, }) + return exitCode } catch (error) { console.error(`Error starting hybrid project '${asset?.title ?? '(unknown)'}':`, error) + return 1 } finally { if (asset) { await remoteBackend.closeProject(asset.id, asset.title) @@ -75,10 +77,11 @@ export async function runLocalProjectByUuid( projectId: UUID, projectsDirectory: Path, cloudParams?: CloudParams, -): Promise { +): Promise { const projectService = createProjectService() try { - await projectService.runProject(projectId, projectsDirectory, cloudParams) + const exitCode = await projectService.runProject(projectId, projectsDirectory, cloudParams) + return exitCode } catch (error) { console.error(`Error starting local project '${projectId}':`, error) await projectService.closeProject(projectId) @@ -87,11 +90,12 @@ export async function runLocalProjectByUuid( } /** Run a local project by path. */ -export async function runLocalProjectByPath(projectPath: Path): Promise { +export async function runLocalProjectByPath(projectPath: Path): Promise { const directoryId = Path(dirname(projectPath)) const project = await getFileSystemEntry(projectPath) if (project.type !== 'ProjectEntry') { throw new Error(`The path '${projectPath}' does not point to a project.`) } - await runLocalProjectByUuid(project.metadata.id as UUID, directoryId) + const exitCode = await runLocalProjectByUuid(project.metadata.id as UUID, directoryId) + return exitCode }