diff --git a/.github/workflows/fw-lite.yaml b/.github/workflows/fw-lite.yaml
index 4167006a10..d42d65fc57 100644
--- a/.github/workflows/fw-lite.yaml
+++ b/.github/workflows/fw-lite.yaml
@@ -217,6 +217,21 @@ jobs:
dotnet publish -r linux-x64 --artifacts-path ../artifacts -p:PublishSingleFile=true -p:Version=${{ needs.build-and-test.outputs.semver-version }}
dotnet publish -r linux-arm64 --artifacts-path ../artifacts -p:PublishSingleFile=true -p:Version=${{ needs.build-and-test.outputs.semver-version }}
+ - name: Test Linux executable
+ working-directory: backend/FwLite/artifacts/publish/FwLiteWeb/release_linux-x64
+ run: |
+ set +e
+ chmod +x ./FwLiteWeb
+ output=$(timeout 10s ./FwLiteWeb 2>&1)
+ exit_code=$?
+ if [ $exit_code -eq 124 ] || [ $exit_code -eq 0 ]; then
+ echo "✅ Linux executable ran without crashing for 10s"
+ else
+ echo "❌ Linux executable exited with code $exit_code"
+ echo "$output"
+ exit 1
+ fi
+
- name: Upload FWLite Linux artifacts
uses: actions/upload-artifact@v4
with:
diff --git a/backend/FwLite/FwLiteWeb/FwLiteWeb.csproj b/backend/FwLite/FwLiteWeb/FwLiteWeb.csproj
index a62b9c365c..ff8b7a0adb 100644
--- a/backend/FwLite/FwLiteWeb/FwLiteWeb.csproj
+++ b/backend/FwLite/FwLiteWeb/FwLiteWeb.csproj
@@ -5,6 +5,7 @@
true
$(ApplicationDisplayVersion)
preview
+ false
diff --git a/backend/FwLite/FwLiteWeb/Program.cs b/backend/FwLite/FwLiteWeb/Program.cs
index e58a59753c..879f33f723 100644
--- a/backend/FwLite/FwLiteWeb/Program.cs
+++ b/backend/FwLite/FwLiteWeb/Program.cs
@@ -3,8 +3,13 @@
using Microsoft.Extensions.Options;
//paratext won't let us change the working directory, and if it's not set correctly then loading js files doesn't work
-Directory.SetCurrentDirectory(Path.GetDirectoryName(typeof(Program).Assembly.Location)!);
-var app = FwLiteWebServer.SetupAppServer(new() {Args = args});
+var assemblyLocation = typeof(Program).Assembly.Location;
+var assemblyDirectory = !string.IsNullOrEmpty(assemblyLocation)
+ ? Path.GetDirectoryName(assemblyLocation) : null;
+var appDirectory = assemblyDirectory ?? AppContext.BaseDirectory;
+Directory.SetCurrentDirectory(appDirectory);
+
+var app = FwLiteWebServer.SetupAppServer(new() { Args = args });
await using (app)
{
await app.StartAsync();
diff --git a/backend/FwLite/LcmCrdt/LcmCrdt.csproj b/backend/FwLite/LcmCrdt/LcmCrdt.csproj
index 88a09ac0a1..77ddfb05f0 100644
--- a/backend/FwLite/LcmCrdt/LcmCrdt.csproj
+++ b/backend/FwLite/LcmCrdt/LcmCrdt.csproj
@@ -20,6 +20,12 @@
+
+
+
+
+
+
diff --git a/backend/FwLite/MiniLcm/Models/RichString.cs b/backend/FwLite/MiniLcm/Models/RichString.cs
index 46b7a22aad..1128a4ecb6 100644
--- a/backend/FwLite/MiniLcm/Models/RichString.cs
+++ b/backend/FwLite/MiniLcm/Models/RichString.cs
@@ -327,7 +327,7 @@ public bool EqualsProps(RichSpan? other)
BulNumTxtAft == other.BulNumTxtAft && BulNumFontInfo == other.BulNumFontInfo &&
CustomBullet == other.CustomBullet && TabList == other.TabList && TableRule == other.TableRule &&
FieldName == other.FieldName && Equals(ObjData, other.ObjData) &&
- (Equals(Tags, other.Tags) || Tags.SequenceEqual(other.Tags));
+ (Equals(Tags, other.Tags) || (Tags is not null && other.Tags is not null && Tags.SequenceEqual(other.Tags)));
}
}
diff --git a/frontend/viewer/vite.config.ts b/frontend/viewer/vite.config.ts
index 05a1bfe18e..cd461baa32 100644
--- a/frontend/viewer/vite.config.ts
+++ b/frontend/viewer/vite.config.ts
@@ -9,6 +9,7 @@ export default defineConfig(({ mode, command }) => {
base: command == "build" ? '/_content/FwLiteShared/viewer' : '/',
build: {
outDir: '../../backend/FwLite/FwLiteShared/wwwroot/viewer',
+ emptyOutDir: true,
manifest: true,
minify: false,
sourcemap: true,