fix.继续修ci,ci怎么天天炸

This commit is contained in:
lincube
2026-04-19 02:12:34 +08:00
parent 9cf3a15c89
commit 4f9feafbbe
13 changed files with 117 additions and 88 deletions

View File

@@ -32,6 +32,7 @@ jobs:
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}
@@ -66,12 +67,15 @@ jobs:
libx11-6 libxrandr2 libxinerama1 \ libx11-6 libxrandr2 libxinerama1 \
libxi6 libxcursor1 libxext6 \ libxi6 libxcursor1 libxext6 \
libxrender1 libxkbcommon-x11-0 \ libxrender1 libxkbcommon-x11-0 \
clang zlib1g-dev clang zlib1g-dev \
libportaudio2 libasound2 \
libwebkit2gtk-4.1-dev
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}
@@ -98,10 +102,14 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: recursive submodules: recursive
- name: Install dependencies
run: brew install portaudio
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}
@@ -132,6 +140,7 @@ jobs:
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Pack SDK and template packages - name: Pack SDK and template packages
shell: pwsh shell: pwsh

View File

@@ -31,6 +31,7 @@ jobs:
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}

View File

@@ -88,6 +88,7 @@ jobs:
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}
@@ -515,12 +516,15 @@ jobs:
libx11-6 libxrandr2 libxinerama1 \ libx11-6 libxrandr2 libxinerama1 \
libxi6 libxcursor1 libxext6 \ libxi6 libxcursor1 libxext6 \
libxrender1 libxkbcommon-x11-0 \ libxrender1 libxkbcommon-x11-0 \
clang zlib1g-dev clang zlib1g-dev \
libportaudio2 libasound2 \
libwebkit2gtk-4.1-dev
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}
@@ -707,10 +711,14 @@ jobs:
submodules: recursive submodules: recursive
ref: ${{ needs.prepare.outputs.checkout_ref }} ref: ${{ needs.prepare.outputs.checkout_ref }}
- name: Install dependencies
run: brew install portaudio
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: ${{ env.DOTNET_VERSION }} dotnet-version: ${{ env.DOTNET_VERSION }}
dotnet-quality: 'preview'
- name: Restore - name: Restore
run: dotnet restore ${{ env.Solution_Name }} run: dotnet restore ${{ env.Solution_Name }}

View File

@@ -0,0 +1,23 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using LanMountainDesktop.Launcher.Models;
using LanMountainDesktop.Launcher.Services;
using LanMountainDesktop.Shared.Contracts.Launcher;
namespace LanMountainDesktop.Launcher;
[JsonSourceGenerationOptions(WriteIndented = true, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(SignedFileMap))]
[JsonSerializable(typeof(UpdateFileEntry))]
[JsonSerializable(typeof(SnapshotMetadata))]
[JsonSerializable(typeof(AppVersionInfo))]
[JsonSerializable(typeof(StartupProgressMessage))]
[JsonSerializable(typeof(LauncherResult))]
[JsonSerializable(typeof(HostDiscoveryConfig))]
[JsonSerializable(typeof(PluginManifest))]
[JsonSerializable(typeof(PendingUpgrade))]
[JsonSerializable(typeof(List<PendingUpgrade>))]
[JsonSerializable(typeof(GitHubRelease))]
[JsonSerializable(typeof(GitHubAsset))]
[JsonSerializable(typeof(List<GitHubRelease>))]
internal sealed partial class AppJsonContext : JsonSerializerContext;

View File

@@ -56,7 +56,11 @@
<!-- 允许 IL 警告 --> <!-- 允许 IL 警告 -->
<TrimmerSingleWarn>false</TrimmerSingleWarn> <TrimmerSingleWarn>false</TrimmerSingleWarn>
<!-- FluentAvaloniaUI 需要启用反射序列化AOT 兼容模式) --> <!-- AOT 模式下禁用反射式 JSON 序列化,强制使用 Source Generator -->
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault> <!-- 之前设置为 true 与 AOT 矛盾,导致 IL2026/IL3050 警告和运行时失败 -->
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
<!-- 启用 ISerializable 支持(部分库需要) -->
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@@ -149,10 +149,7 @@ internal static class Commands
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
} }
var json = JsonSerializer.Serialize(result, new JsonSerializerOptions var json = JsonSerializer.Serialize(result, AppJsonContext.Default.LauncherResult);
{
WriteIndented = true
});
await File.WriteAllTextAsync(fullPath, json, Encoding.UTF8).ConfigureAwait(false); await File.WriteAllTextAsync(fullPath, json, Encoding.UTF8).ConfigureAwait(false);
} }

View File

@@ -322,7 +322,7 @@ internal sealed class DeploymentLocator
try try
{ {
var json = File.ReadAllText(snapshotFile); var json = File.ReadAllText(snapshotFile);
var snapshot = System.Text.Json.JsonSerializer.Deserialize<SnapshotMetadata>(json); var snapshot = System.Text.Json.JsonSerializer.Deserialize(json, AppJsonContext.Default.SnapshotMetadata);
if (snapshot != null && !string.IsNullOrEmpty(snapshot.SourceDirectory)) if (snapshot != null && !string.IsNullOrEmpty(snapshot.SourceDirectory))
{ {
if (Directory.Exists(snapshot.SourceDirectory)) if (Directory.Exists(snapshot.SourceDirectory))
@@ -445,7 +445,7 @@ internal sealed class DeploymentLocator
try try
{ {
var json = File.ReadAllText(versionFile); var json = File.ReadAllText(versionFile);
var info = JsonSerializer.Deserialize<AppVersionInfo>(json); var info = JsonSerializer.Deserialize(json, AppJsonContext.Default.AppVersionInfo);
if (info is not null) if (info is not null)
{ {
return info; return info;

View File

@@ -159,7 +159,7 @@ namespace LanMountainDesktop.Launcher.Services;
try try
{ {
var json = File.ReadAllText(configPath); var json = File.ReadAllText(configPath);
var config = JsonSerializer.Deserialize<HostDiscoveryConfig>(json); var config = JsonSerializer.Deserialize(json, AppJsonContext.Default.HostDiscoveryConfig);
if (config?.HostPath != null && File.Exists(config.HostPath)) if (config?.HostPath != null && File.Exists(config.HostPath))
{ {
return config.HostPath; return config.HostPath;
@@ -617,13 +617,13 @@ namespace LanMountainDesktop.Launcher.Services;
public required string AppRoot { get; set; } public required string AppRoot { get; set; }
public required HostDiscoveryOptions Options { get; set; } public required HostDiscoveryOptions Options { get; set; }
} }
}
/// <summary> /// <summary>
/// 发现配置文件 /// 发现配置文件
/// </summary> /// </summary>
private class HostDiscoveryConfig internal class HostDiscoveryConfig
{ {
public string? HostPath { get; set; } public string? HostPath { get; set; }
public List<string>? AdditionalPaths { get; set; } public List<string>? AdditionalPaths { get; set; }
}
} }

View File

@@ -143,7 +143,7 @@ public class LauncherIpcServer : IDisposable
// 3. 反序列化并回调 // 3. 反序列化并回调
var json = System.Text.Encoding.UTF8.GetString(payloadBuffer, 0, payloadLength); var json = System.Text.Encoding.UTF8.GetString(payloadBuffer, 0, payloadLength);
var message = JsonSerializer.Deserialize<StartupProgressMessage>(json); var message = JsonSerializer.Deserialize(json, AppJsonContext.Default.StartupProgressMessage);
if (message is not null) if (message is not null)
{ {
_onProgress(message); _onProgress(message);

View File

@@ -73,7 +73,7 @@ internal sealed class PluginInstallerService
using var stream = entries[0].Open(); using var stream = entries[0].Open();
using var reader = new StreamReader(stream); using var reader = new StreamReader(stream);
var json = reader.ReadToEnd(); var json = reader.ReadToEnd();
var manifest = JsonSerializer.Deserialize<PluginManifest>(json); var manifest = JsonSerializer.Deserialize(json, AppJsonContext.Default.PluginManifest);
if (manifest == null) if (manifest == null)
{ {
throw new InvalidOperationException($"Failed to deserialize manifest from '{packagePath}'."); throw new InvalidOperationException($"Failed to deserialize manifest from '{packagePath}'.");

View File

@@ -29,7 +29,7 @@ internal sealed class PluginUpgradeQueueService
} }
var text = File.ReadAllText(pendingPath); var text = File.ReadAllText(pendingPath);
var pending = JsonSerializer.Deserialize<List<PendingUpgrade>>(text) ?? []; var pending = JsonSerializer.Deserialize(text, AppJsonContext.Default.ListPendingUpgrade) ?? [];
var failures = new List<string>(); var failures = new List<string>();
var succeeded = new List<PendingUpgrade>(); var succeeded = new List<PendingUpgrade>();
@@ -63,10 +63,7 @@ internal sealed class PluginUpgradeQueueService
} }
else else
{ {
File.WriteAllText(pendingPath, JsonSerializer.Serialize(remaining, new JsonSerializerOptions File.WriteAllText(pendingPath, JsonSerializer.Serialize(remaining, AppJsonContext.Default.ListPendingUpgrade));
{
WriteIndented = true
}));
} }
return new LauncherResult return new LauncherResult
@@ -79,13 +76,14 @@ internal sealed class PluginUpgradeQueueService
: $"Applied {succeeded.Count} upgrades, failed: {string.Join(", ", failures)}." : $"Applied {succeeded.Count} upgrades, failed: {string.Join(", ", failures)}."
}; };
} }
}
private sealed record PendingUpgrade( internal sealed record PendingUpgrade(
string PluginId, string PluginId,
string SourcePackagePath, string SourcePackagePath,
string TargetVersion, string TargetVersion,
DateTimeOffset CreatedAt) DateTimeOffset CreatedAt)
{ {
public bool IsValid() public bool IsValid()
{ {
return !string.IsNullOrWhiteSpace(PluginId) && return !string.IsNullOrWhiteSpace(PluginId) &&
@@ -93,5 +91,4 @@ internal sealed class PluginUpgradeQueueService
!string.IsNullOrWhiteSpace(TargetVersion) && !string.IsNullOrWhiteSpace(TargetVersion) &&
File.Exists(SourcePackagePath); File.Exists(SourcePackagePath);
} }
}
} }

View File

@@ -15,7 +15,6 @@ internal sealed class UpdateCheckService
private readonly string _repoOwner; private readonly string _repoOwner;
private readonly string _repoName; private readonly string _repoName;
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
private readonly JsonSerializerOptions _jsonOptions;
public UpdateCheckService(string repoOwner, string repoName) public UpdateCheckService(string repoOwner, string repoName)
{ {
@@ -24,12 +23,6 @@ internal sealed class UpdateCheckService
_httpClient = new HttpClient(); _httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("User-Agent", "LanMountainDesktop-Launcher"); _httpClient.DefaultRequestHeaders.Add("User-Agent", "LanMountainDesktop-Launcher");
_httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github+json"); _httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github+json");
_jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
};
} }
/// <summary> /// <summary>
@@ -97,7 +90,7 @@ internal sealed class UpdateCheckService
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync(cancellationToken); var json = await response.Content.ReadAsStringAsync(cancellationToken);
var releases = JsonSerializer.Deserialize<List<GitHubRelease>>(json, _jsonOptions); var releases = JsonSerializer.Deserialize(json, AppJsonContext.Default.ListGitHubRelease);
return releases?.Select(r => new ReleaseInfo return releases?.Select(r => new ReleaseInfo
{ {
@@ -131,10 +124,11 @@ internal sealed class UpdateCheckService
var cleaned = ParseVersionString(versionString); var cleaned = ParseVersionString(versionString);
return Version.TryParse(cleaned, out var version) ? version : new Version(0, 0, 0); return Version.TryParse(cleaned, out var version) ? version : new Version(0, 0, 0);
} }
}
// GitHub API 响应模型 // GitHub API 响应模型
private sealed class GitHubRelease internal sealed class GitHubRelease
{ {
[JsonPropertyName("tag_name")] [JsonPropertyName("tag_name")]
public string? TagName { get; set; } public string? TagName { get; set; }
@@ -152,10 +146,10 @@ internal sealed class UpdateCheckService
[JsonPropertyName("assets")] [JsonPropertyName("assets")]
public List<GitHubAsset>? Assets { get; set; } public List<GitHubAsset>? Assets { get; set; }
} }
private sealed class GitHubAsset internal sealed class GitHubAsset
{ {
[JsonPropertyName("name")] [JsonPropertyName("name")]
public string? Name { get; set; } public string? Name { get; set; }
@@ -164,5 +158,4 @@ internal sealed class UpdateCheckService
[JsonPropertyName("size")] [JsonPropertyName("size")]
public long Size { get; set; } public long Size { get; set; }
}
} }

View File

@@ -48,7 +48,7 @@ internal sealed class UpdateEngineService
} }
var fileMapText = File.ReadAllText(fileMapPath); var fileMapText = File.ReadAllText(fileMapPath);
var fileMap = JsonSerializer.Deserialize<SignedFileMap>(fileMapText); var fileMap = JsonSerializer.Deserialize(fileMapText, AppJsonContext.Default.SignedFileMap);
if (fileMap is null) if (fileMap is null)
{ {
return Failed("update.check", "invalid_manifest", "files.json is invalid."); return Failed("update.check", "invalid_manifest", "files.json is invalid.");
@@ -137,7 +137,7 @@ internal sealed class UpdateEngineService
} }
var fileMapText = await File.ReadAllTextAsync(fileMapPath); var fileMapText = await File.ReadAllTextAsync(fileMapPath);
var fileMap = JsonSerializer.Deserialize<SignedFileMap>(fileMapText); var fileMap = JsonSerializer.Deserialize(fileMapText, AppJsonContext.Default.SignedFileMap);
if (fileMap is null || fileMap.Files.Count == 0) if (fileMap is null || fileMap.Files.Count == 0)
{ {
return Failed("update.apply", "invalid_manifest", "No update file entries were found."); return Failed("update.apply", "invalid_manifest", "No update file entries were found.");
@@ -438,7 +438,7 @@ internal sealed class UpdateEngineService
return Failed("update.rollback", "no_snapshot", "No snapshot found."); return Failed("update.rollback", "no_snapshot", "No snapshot found.");
} }
var snapshot = JsonSerializer.Deserialize<SnapshotMetadata>(File.ReadAllText(snapshotPath)); var snapshot = JsonSerializer.Deserialize(File.ReadAllText(snapshotPath), AppJsonContext.Default.SnapshotMetadata);
if (snapshot is null || string.IsNullOrWhiteSpace(snapshot.SourceDirectory)) if (snapshot is null || string.IsNullOrWhiteSpace(snapshot.SourceDirectory))
{ {
return Failed("update.rollback", "invalid_snapshot", "Invalid snapshot metadata."); return Failed("update.rollback", "invalid_snapshot", "Invalid snapshot metadata.");
@@ -656,10 +656,7 @@ internal sealed class UpdateEngineService
private static void SaveSnapshot(string path, SnapshotMetadata snapshot) private static void SaveSnapshot(string path, SnapshotMetadata snapshot)
{ {
File.WriteAllText(path, JsonSerializer.Serialize(snapshot, new JsonSerializerOptions File.WriteAllText(path, JsonSerializer.Serialize(snapshot, AppJsonContext.Default.SnapshotMetadata));
{
WriteIndented = true
}));
} }
private static LauncherResult Failed(string stage, string code, string message) private static LauncherResult Failed(string stage, string code, string message)