using System.Security; using System.Text.Json; namespace Zcbot.WindowsNode; internal interface IAnsysAcceptanceService { bool IsAvailable { get; } bool IsGateEnabled { get; } Task RunAsync( string workRoot, IProgress progress, CancellationToken cancellationToken); void EnableGate(string reportPath); } internal sealed class AnsysAcceptanceService : IAnsysAcceptanceService { private const string Capability = "ansys.mechanical.static_structural@v2"; private const string GateEnvironmentVariable = "ZCBOT_ANSYS_242_VALIDATED"; private readonly INodeAdapter? adapter; internal AnsysAcceptanceService(NodePaths paths) { adapter = AdapterCatalog.CreateDefault( new JobRepository(paths.JobsDirectory), paths).Find(Capability); } public bool IsAvailable => adapter?.SupportsLocalAcceptance == true; public bool IsGateEnabled => Environment.GetEnvironmentVariable( GateEnvironmentVariable, EnvironmentVariableTarget.Machine) == "1"; public Task RunAsync( string workRoot, IProgress progress, CancellationToken cancellationToken) => IsAvailable ? adapter!.RunLocalAcceptanceAsync(workRoot, progress, cancellationToken) : throw new InvalidOperationException( "当前安装包没有 ANSYS 验收工具。请先安装新版完整 Node 包。"); public void EnableGate(string reportPath) { if (!ReportPassed(reportPath)) { throw new InvalidDataException("没有可验证的本次验收通过报告,执行门不会开启。"); } Environment.SetEnvironmentVariable( GateEnvironmentVariable, "1", EnvironmentVariableTarget.Machine); } internal static bool ReportPassed(string path) { try { using var document = JsonDocument.Parse(File.ReadAllBytes(path)); return document.RootElement.TryGetProperty("passed", out var passed) && passed.ValueKind == JsonValueKind.True; } catch (Exception exception) when ( exception is IOException or JsonException or SecurityException or UnauthorizedAccessException) { return false; } } }