maybe fixed running on other OS's

This commit is contained in:
stan44 2026-02-28 14:46:59 -06:00
parent 47aadde2b2
commit 4e2eaf9059
6 changed files with 205 additions and 52 deletions

View File

@ -222,37 +222,47 @@ fn effective_root(root_override: &Option<PathBuf>) -> Result<PathBuf, String> {
}
fn resolve_sidecar_path(root: &Path) -> Result<PathBuf, String> {
let root_exe_path = root.join("Journal.Sidecar.exe");
if root_exe_path.exists() {
return Ok(root_exe_path);
#[cfg(windows)]
let exe_name = "Journal.Sidecar.exe";
#[cfg(not(windows))]
let exe_name = "Journal.Sidecar";
// 1. If root is explicitly pointing to the executable file itself:
if root.is_file() && root.file_name().and_then(|n| n.to_str()) == Some(exe_name) {
return Ok(root.to_path_buf());
}
let root_publish_exe_path = root.join("publish").join("Journal.Sidecar.exe");
if root_publish_exe_path.exists() {
return Ok(root_publish_exe_path);
// 2. Direct paths relative to the folder:
let direct_paths = [
root.join(exe_name),
root.join("output").join(exe_name),
root.join("publish").join(exe_name),
root.join("Journal.Sidecar/bin/Debug/net10.0").join(exe_name),
root.join("Journal.Sidecar/bin/Release/net10.0/win-x64/publish").join(exe_name),
];
for path in direct_paths {
if path.exists() {
return Ok(path);
}
}
let debug_path = root.join("Journal.Sidecar/bin/Debug/net10.0/Journal.Sidecar.exe");
if debug_path.exists() {
return Ok(debug_path);
}
let release_path =
root.join("Journal.Sidecar/bin/Release/net10.0/win-x64/publish/Journal.Sidecar.exe");
if release_path.exists() {
return Ok(release_path);
}
let sidecar_root = root.join("Journal.Sidecar");
if let Some(path) = find_sidecar_executable(&sidecar_root) {
// 3. Fallback: recursively search the known sidecar folder
let sidecar_src_root = root.join("Journal.Sidecar");
if let Some(path) = find_sidecar_executable(&sidecar_src_root, exe_name) {
return Ok(path);
}
Err("Journal.Sidecar.exe not found. Build Journal.Sidecar first.".to_string())
// 4. Fallback: recursively search the provided root itself
if let Some(path) = find_sidecar_executable(root, exe_name) {
return Ok(path);
}
Err(format!("{exe_name} not found in {}. Build Journal.Sidecar first.", root.display()))
}
fn find_sidecar_executable(search_root: &Path) -> Option<PathBuf> {
if !search_root.exists() {
fn find_sidecar_executable(search_root: &Path, exe_name: &str) -> Option<PathBuf> {
if !search_root.is_dir() {
return None;
}
@ -268,6 +278,11 @@ fn find_sidecar_executable(search_root: &Path) -> Option<PathBuf> {
};
let path = entry.path();
if path.is_dir() {
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
if name == "node_modules" || name == ".git" || name == ".vs" {
continue;
}
}
stack.push(path);
continue;
}
@ -275,7 +290,7 @@ fn find_sidecar_executable(search_root: &Path) -> Option<PathBuf> {
let is_sidecar_exe = path
.file_name()
.and_then(|name| name.to_str())
.map(|name| name.eq_ignore_ascii_case("Journal.Sidecar.exe"))
.map(|name| name.eq_ignore_ascii_case(exe_name))
.unwrap_or(false);
if is_sidecar_exe {
return Some(path);

View File

@ -36,13 +36,29 @@ public static class ProcessRunner
var sw = Stopwatch.StartNew();
using var process = new Process { StartInfo = psi };
process.Start();
var stdoutTask = DrainAsync(process.StandardOutput, line => onOutput(line, false), cancellationToken);
var stderrTask = DrainAsync(process.StandardError, line => onOutput(line, true), cancellationToken);
void OnCancel(object? sender, ConsoleCancelEventArgs e)
{
e.Cancel = true; // Prevent SDT from exiting immediately
try { process.Kill(entireProcessTree: true); } catch { }
}
await Task.WhenAll(stdoutTask, stderrTask).ConfigureAwait(false);
await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
Console.CancelKeyPress += OnCancel;
try
{
process.Start();
var stdoutTask = DrainAsync(process.StandardOutput, line => onOutput(line, false), cancellationToken);
var stderrTask = DrainAsync(process.StandardError, line => onOutput(line, true), cancellationToken);
await Task.WhenAll(stdoutTask, stderrTask).ConfigureAwait(false);
await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
}
finally
{
Console.CancelKeyPress -= OnCancel;
}
sw.Stop();
return new RunResult(process.ExitCode, sw.Elapsed);

View File

@ -2,6 +2,9 @@ using Microsoft.Extensions.DependencyInjection;
using Journal.Core;
using Journal.Core.Services.Sidecar;
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.InputEncoding = System.Text.Encoding.UTF8;
var services = new ServiceCollection();
services.AddFragmentServices();
services.AddSingleton<Entry>();

View File

@ -74,6 +74,22 @@
"workingDir": ".",
"dependsOn": []
},
{
"id": "sync-output",
"label": "Sync Build Assets to Output",
"description": "Sweep repo for newest builds (Web/Sidecar/Gateway/Tauri) and copy them to the output dir",
"group": "Build",
"command": "pwsh",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"scripts/sync-output.ps1"
],
"workingDir": ".",
"dependsOn": []
},
{
"id": "webgateway",
"label": "Publish WebGateway",
@ -168,9 +184,9 @@
]
},
{
"id": "run-gateway",
"label": "Run WebGateway",
"description": "Start HTTP gateway dev server at http://localhost:5180",
"id": "run-gateway-dev",
"label": "Run WebGateway Server (Dev)",
"description": "Start HTTP gateway via 'dotnet run' at http://localhost:5180",
"group": "Dev",
"command": "pwsh",
"args": [
@ -178,7 +194,27 @@
"-ExecutionPolicy",
"Bypass",
"-File",
"scripts/run-webgateway.ps1"
"scripts/run-webgateway.ps1",
"-Mode",
"Dev"
],
"workingDir": ".",
"dependsOn": []
},
{
"id": "run-gateway-prod",
"label": "Run WebGateway Server (Output)",
"description": "Start compiled gateway from output/webgateway at http://localhost:5180",
"group": "Dev",
"command": "pwsh",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"scripts/run-webgateway.ps1",
"-Mode",
"Output"
],
"workingDir": ".",
"dependsOn": []
@ -244,8 +280,7 @@
],
"workingDir": ".",
"dependsOn": []
}
,
},
{
"id": "npm-clean",
"label": "Clean Node Modules",
@ -261,8 +296,7 @@
],
"workingDir": ".",
"dependsOn": []
}
,
},
{
"id": "stage-output",
"label": "Stage Output Bundle",
@ -332,4 +366,4 @@
"options": []
}
]
}
}

View File

@ -2,7 +2,9 @@ param(
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[string]$Urls = "http://0.0.0.0:5180",
[string]$ProjectRoot
[string]$ProjectRoot,
[ValidateSet("Dev", "Output")]
[string]$Mode = "Dev"
)
$commonScript = Join-Path $PSScriptRoot "script-common.ps1"
@ -29,20 +31,39 @@ Clear-JournalProxyEnv
Initialize-JournalDotnetEnv -RepoRoot $repoRoot
$env:JOURNAL_PROJECT_ROOT = $effectiveProjectRoot
Write-Host "Running Journal.WebGateway ($Configuration)..." -ForegroundColor Cyan
Write-Host "Project: $gatewayProject" -ForegroundColor DarkGray
Write-Host "URLs: $Urls" -ForegroundColor DarkGray
Write-Host "JOURNAL_PROJECT_ROOT: $effectiveProjectRoot" -ForegroundColor DarkGray
if ($Mode -eq "Output") {
$exeName = if ([System.Environment]::OSVersion.Platform -eq "Win32NT") { "Journal.WebGateway.exe" } else { "Journal.WebGateway" }
$exePath = Join-Path $repoRoot "output\webgateway\$exeName"
if (-not (Test-Path $exePath)) {
Write-Host "Output executable not found at $exePath" -ForegroundColor Red
Write-Host "Please build WebGateway first (e.g. scripts\publish-webgateway.ps1)" -ForegroundColor Yellow
exit 1
}
$runArgs = @(
"run",
"--project", $gatewayProject,
"-c", $Configuration,
"--no-launch-profile",
"--urls", $Urls,
"-p:RestoreIgnoreFailedSources=true",
"-p:NuGetAudit=false"
)
Write-Host "Running Journal.WebGateway (Published Output)..." -ForegroundColor Cyan
Write-Host "Executable: $exePath" -ForegroundColor DarkGray
Write-Host "URLs: $Urls" -ForegroundColor DarkGray
Write-Host "JOURNAL_PROJECT_ROOT: $effectiveProjectRoot" -ForegroundColor DarkGray
& dotnet @runArgs
& $exePath --urls $Urls
}
else {
Write-Host "Running Journal.WebGateway ($Configuration Dev Server)..." -ForegroundColor Cyan
Write-Host "Project: $gatewayProject" -ForegroundColor DarkGray
Write-Host "URLs: $Urls" -ForegroundColor DarkGray
Write-Host "JOURNAL_PROJECT_ROOT: $effectiveProjectRoot" -ForegroundColor DarkGray
$runArgs = @(
"run",
"--project", $gatewayProject,
"-c", $Configuration,
"--no-launch-profile",
"--urls", $Urls,
"-p:RestoreIgnoreFailedSources=true",
"-p:NuGetAudit=false"
)
& dotnet @runArgs
}
exit $LASTEXITCODE

64
scripts/sync-output.ps1 Normal file
View File

@ -0,0 +1,64 @@
param()
$commonScript = Join-Path $PSScriptRoot "script-common.ps1"
if (-not (Test-Path $commonScript)) {
throw "Missing helper script: $commonScript"
}
. $commonScript
$repoRoot = Resolve-JournalRepoRoot -StartPath $PSScriptRoot
$outputDir = Join-Path $repoRoot "output"
# Ensure output exists
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
Write-Host "Syncing all recent built assets to output directory..." -ForegroundColor Cyan
# Helper to find the newest compiled binary
function Find-NewestBin([string]$SearchPath, [string]$Pattern) {
if (-not (Test-Path $SearchPath)) { return $null }
$files = Get-ChildItem -Path $SearchPath -Filter $Pattern -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\\obj\\' } |
Sort-Object LastWriteTime -Descending
if ($files) { return $files[0] }
return $null
}
# 1. Front-end Web Assets
$webBuildDir = Join-Path $repoRoot "Journal.App\build"
if (Test-Path $webBuildDir) {
$webOutputDir = Join-Path $outputDir "webgateway\wwwroot"
New-Item -ItemType Directory -Force -Path $webOutputDir | Out-Null
Copy-Item -Path (Join-Path $webBuildDir "*") -Destination $webOutputDir -Recurse -Force
Write-Host "Synced web assets -> $webOutputDir" -ForegroundColor Green
}
# 2. Sidecar
$sidecarExeName = if ([System.Environment]::OSVersion.Platform -eq "Win32NT") { "Journal.Sidecar.exe" } else { "Journal.Sidecar" }
$sidecarExe = Find-NewestBin -SearchPath (Join-Path $repoRoot "Journal.Sidecar\bin") -Pattern $sidecarExeName
if ($sidecarExe) {
Copy-Item -Path (Join-Path $sidecarExe.DirectoryName "*") -Destination $outputDir -Recurse -Force
Write-Host "Synced Journal.Sidecar -> $outputDir" -ForegroundColor Green
}
# 3. WebGateway
$gwExeName = if ([System.Environment]::OSVersion.Platform -eq "Win32NT") { "Journal.WebGateway.exe" } else { "Journal.WebGateway" }
$gwExe = Find-NewestBin -SearchPath (Join-Path $repoRoot "Journal.WebGateway\bin") -Pattern $gwExeName
if ($gwExe) {
$gwOutputDir = Join-Path $outputDir "webgateway"
New-Item -ItemType Directory -Force -Path $gwOutputDir | Out-Null
Copy-Item -Path (Join-Path $gwExe.DirectoryName "*") -Destination $gwOutputDir -Recurse -Force
Write-Host "Synced Journal.WebGateway -> $gwOutputDir" -ForegroundColor Green
}
# 4. Tauri Desktop App
$tauriExe = Find-NewestBin -SearchPath (Join-Path $repoRoot "Journal.App\src-tauri\target") -Pattern "*.exe"
if ($tauriExe) {
# Don't try to copy sidecar.exe again if it ended up in tauri target dir
if ($tauriExe.Name -ne "Journal.Sidecar.exe") {
Copy-Item -Path $tauriExe.FullName -Destination $outputDir -Force
Write-Host "Synced Tauri App ($($tauriExe.Name)) -> $outputDir" -ForegroundColor Green
}
}
Write-Host "Sync complete!" -ForegroundColor Cyan