Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ The newest come first, and a press on When turns the order round. A search box a
Started by buttons narrow the events already loaded, and the count says how many of them match. A
row about a Bot (a message routed to it, say) now names it under Bot.

### The desktop app starts OpenBot when it is opened from Finder

Opened from Finder or the Dock, the desktop app stopped at Start with "OpenBot did not start", and
the app's log said `bun: command not found`. The app part of OpenBot runs as a package script that
starts `bun` again by name, and an app opened that way has no `bun` on its `PATH`. The desktop now
hands every process it starts the directory of the Bun it installed.

### The desktop setup page does not freeze when it loads during an install

If the setup page loaded again while the desktop app downloaded local software, the window showed a
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ fn command_at(engine: Engine, binary: &Path) -> Command {
///
/// In front, so the provider OpenBot placed is the one found; appended, a broken `docker-compose`
/// earlier on PATH would still win.
fn path_with(first: &Path) -> OsString {
pub(crate) fn path_with(first: &Path) -> OsString {
let mut joined = OsString::from(first);
if let Some(existing) = std::env::var_os("PATH") {
if !existing.is_empty() {
Expand Down
46 changes: 45 additions & 1 deletion desktop/src-tauri/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,7 @@ pub fn spawn_host_process(
let out = std::fs::File::create(logs.join(format!("{}.log", process.name)))?;
let err = out.try_clone()?;

let mut command = command(bun);
let mut command = bun_command(bun);
command.current_dir(root.join(process.cwd));
let ports = crate::env::Ports::read(root)?;
if process.name == LOCAL_BROWSER {
Expand Down Expand Up @@ -1638,6 +1638,23 @@ pub fn spawn_host_process(
command.spawn()
}

/// The installation's Bun, with its own directory first on `PATH`.
///
/// The app runs as a package script (`serve`), and that script runs `bun` again by name. A desktop
/// app opened from Finder has the system's minimal `PATH`, where there is no `bun`, so the app
/// exited with status 127 the moment it started. First, so the Bun this installation downloaded is
/// the one found, not an older one somebody has on `PATH`.
fn bun_command(bun: &Path) -> Command {
let mut command = command(bun);
if let Some(directory) = bun
.parent()
.filter(|directory| !directory.as_os_str().is_empty())
{
command.env("PATH", crate::engine::path_with(directory));
}
command
}

/// The person's browser is started the way `scripts/start-local-chrome-computer.ts` starts it, and
/// is handed only what it needs (see `local_browser::environment`).
///
Expand Down Expand Up @@ -3660,6 +3677,33 @@ fn dirs_home() -> PathBuf {
#[cfg(test)]
mod tests {
use super::*;

/// The app's `serve` script runs `bun` by name. Opened from Finder, the desktop has no `bun` on
/// `PATH`, so a host process has to be handed the directory of the Bun that started it.
#[test]
fn a_host_process_finds_the_installations_own_bun_by_name() {
let bun = Path::new("/installation/openbot-engine/bun-1.4.3/bun");
let command = bun_command(bun);
let path = command
.get_envs()
.find(|(name, _)| *name == "PATH")
.and_then(|(_, value)| value)
.expect("a host process is given a PATH");
let mut entries = std::env::split_paths(path);
assert_eq!(
entries.next().as_deref(),
Some(Path::new("/installation/openbot-engine/bun-1.4.3")),
"the installation's Bun comes first"
);
let inherited: Vec<_> = std::env::var_os("PATH")
.map(|path| std::env::split_paths(&path).collect())
.unwrap_or_default();
assert_eq!(
entries.collect::<Vec<_>>(),
inherited,
"and the rest of PATH is kept"
);
}
use crate::test_support::temp_root;

#[test]
Expand Down
Loading