Skip to content

Commit 8cd45bb

Browse files
[idp-1511] Support updating spectral without ejecting (#59)
* Working stades * Refactor * Fixing bugs, remaining cleanup * Cleanup * Missing document * Cleanup in system test * Add debugging logs * Put back incremental build * Try pinpoint problem source * Try addig a nuget.config * Cleanup * Revert blind fix-try * Fix targets * Cleanup * CR fixes * Add unit test for RulesetManager * Fix sealed --------- Co-authored-by: Mathieu Gamache <mathieu.gamache@workleap.com>
1 parent f90150d commit 8cd45bb

28 files changed

+594
-176
lines changed

Run-SystemTest.ps1

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Process {
1919

2020
Exec { & dotnet add package Workleap.OpenApi.MSBuild --prerelease --source $openApiMsBuildSource }
2121

22+
Write-Information "dotnet build -c Release $extraArgs"
2223
$buildProcess = Start-Process -FilePath "dotnet" -ArgumentList "build -c Release $extraArgs" -NoNewWindow -PassThru -Wait
2324

2425
Exec { & dotnet remove package Workleap.OpenApi.MSBuild }
@@ -27,6 +28,8 @@ Process {
2728
Write-Error "The build for project $projectPath was expected to fail, but it succeeded."
2829
} elseif (!$isFailureExpected -and $buildProcess.ExitCode -ne 0) {
2930
Write-Error "The build for project $projectPath was expected to succeed, but it failed."
31+
} else {
32+
Write-Information "The validation succeeded."
3033
}
3134
}
3235
finally {
@@ -54,16 +57,44 @@ Process {
5457
# Build the OpenApi.MSBuild package to be used in the system tests
5558
Exec { & dotnet pack -c Release -o "$outputDir" }
5659

60+
### Testing Generate Contract Mode ###
61+
62+
# Then Should Successfully Build
63+
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=GenerateContract"
64+
# When using legacy name / Then Should Successfully Build
5765
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=CodeFirst"
66+
# When Comparing Spec and No Diff Error / Then Should Successfully Build
67+
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=GenerateContract;OpenApiCompareCodeAgainstSpecFile=true"
68+
# When Comparing Spec and Have Diff / Then Should Fail Build
69+
BuildProject -openApiMsBuildSource $outputDir -projectPath $oasDiffErrorSysTestDir -isFailureExpected $true -extraArgs "/p:OpenApiDevelopmentMode=GenerateContract;OpenApiCompareCodeAgainstSpecFile=true"
70+
71+
### Testing Compare Contract Mode ###
72+
73+
# Given no diff / Then Should Successfully Build
74+
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=ValidateContract"
75+
# Given no diff / When using legacy name / Then Should Successfully Build
5876
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=ContractFirst"
59-
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=ValidateContract;OpenApiCompareCodeAgainstSpecFile=true"
60-
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=GenerateContract"
77+
# Given diff / Then Should Fail Build
78+
BuildProject -openApiMsBuildSource $outputDir -projectPath $oasDiffErrorSysTestDir -isFailureExpected $true -extraArgs "/p:OpenApiDevelopmentMode=ValidateContract"
79+
# Given diff / When OpenApiTreatWarningsAsErrors=false / Then Should Successfully Build
80+
BuildProject -openApiMsBuildSource $outputDir -projectPath $oasDiffErrorSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiTreatWarningsAsErrors=false"
81+
82+
### Testing Spectral Validation ###
83+
84+
# Given no spectral violation / When using frontend profile / Then Should Successfully Build
6185
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiDevelopmentMode=GenerateContract;OpenApiServiceProfile=frontend"
86+
# Given no spectral violation / When using invalid profile / Then Should Fail Build
6287
BuildProject -openApiMsBuildSource $outputDir -projectPath $genericSysTestDir -isFailureExpected $true -extraArgs "/p:OpenApiDevelopmentMode=GenerateContract;OpenApiServiceProfile=scrap"
63-
BuildProject -openApiMsBuildSource $outputDir -projectPath $oasDiffErrorSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiTreatWarningsAsErrors=false"
64-
BuildProject -openApiMsBuildSource $outputDir -projectPath $spectralErrorSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiTreatWarningsAsErrors=false"
65-
BuildProject -openApiMsBuildSource $outputDir -projectPath $oasDiffErrorSysTestDir -isFailureExpected $true
88+
# Given spectral violations / When using default ruleset / Then Should Fail Build
6689
BuildProject -openApiMsBuildSource $outputDir -projectPath $spectralErrorSysTestDir -isFailureExpected $true
90+
# Given spectral violations / When using default ruleset And OpenApiTreatWarningsAsErrors=false / Then Should Successfully Build
91+
BuildProject -openApiMsBuildSource $outputDir -projectPath $spectralErrorSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiTreatWarningsAsErrors=false"
92+
# Given workleap spectral violations / When ejecting ruleset / Then Should Successfully Build
93+
BuildProject -openApiMsBuildSource $outputDir -projectPath $spectralErrorSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiSpectralRulesetUrl=./eject.spectral.yaml"
94+
# Given spectral violations / When overriding ruleset without disabling problematic ruleset / Then Should Fail Build
95+
BuildProject -openApiMsBuildSource $outputDir -projectPath $spectralErrorSysTestDir -isFailureExpected $true -extraArgs "/p:OpenApiSpectralRulesetUrl=./override.spectral.yaml"
96+
# Given spectral violations / When overriding ruleset while disabling problematic ruleset / Then Should Successfully Build
97+
BuildProject -openApiMsBuildSource $outputDir -projectPath $spectralErrorSysTestDir -isFailureExpected $false -extraArgs "/p:OpenApiSpectralRulesetUrl=./override.fixed.spectral.yaml"
6798
}
6899
finally {
69100
Pop-Location

src/WebApiDebugger/Properties/launchSettings.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,31 @@
44
"ValidateContractWithoutCompare": {
55
"commandName": "Executable",
66
"executablePath": "dotnet",
7-
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiDevelopmentMode=ValidateContract /p:OpenApiCompareCodeAgainstSpecFile=false",
7+
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiEnabled=true /p:OpenApiDevelopmentMode=ValidateContract /p:OpenApiCompareCodeAgainstSpecFile=false",
88
"workingDirectory": "$(ProjectDir)"
99
},
1010
"ValidateContractWithCompare": {
1111
"commandName": "Executable",
1212
"executablePath": "dotnet",
13-
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiDevelopmentMode=ValidateContract /p:OpenApiCompareCodeAgainstSpecFile=true",
13+
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiEnabled=true /p:OpenApiDevelopmentMode=ValidateContract /p:OpenApiCompareCodeAgainstSpecFile=true",
1414
"workingDirectory": "$(ProjectDir)"
1515
},
1616
"GenerateContract": {
1717
"commandName": "Executable",
1818
"executablePath": "dotnet",
19-
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiDevelopmentMode=GenerateContract",
19+
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiEnabled=true /p:OpenApiEnabled=true /p:OpenApiDevelopmentMode=GenerateContract",
20+
"workingDirectory": "$(ProjectDir)"
21+
},
22+
"CustomSpectral": {
23+
"commandName": "Executable",
24+
"executablePath": "dotnet",
25+
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiEnabled=true /p:OpenApiDevelopmentMode=GenerateContract /p:OpenApiSpectralRulesetUrl=./custom.spectral.yaml",
2026
"workingDirectory": "$(ProjectDir)"
2127
},
2228
"GenerateContractOnCI": {
2329
"commandName": "Executable",
2430
"executablePath": "dotnet",
25-
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiDevelopmentMode=GenerateContract /p:OpenApiCompareCodeAgainstSpecFile=true",
31+
"commandLineArgs": "msbuild /t:ValidateOpenApi /p:OpenApiEnabled=true /p:OpenApiDevelopmentMode=GenerateContract /p:OpenApiCompareCodeAgainstSpecFile=true",
2632
"workingDirectory": "$(ProjectDir)"
2733
},
2834
"WebApiDebugger": {

src/WebApiDebugger/WebApiDebugger.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
<ItemGroup>
1212
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
1313
</ItemGroup>
14-
1514
<PropertyGroup>
15+
<OpenApiEnabled>false</OpenApiEnabled>
1616
<OpenApiDebuggingEnabled>true</OpenApiDebuggingEnabled>
1717
<OpenApiDevelopmentMode>GenerateContract</OpenApiDevelopmentMode>
1818
</PropertyGroup>
@@ -21,5 +21,11 @@
2121
<ProjectReference Include="..\Workleap.OpenApi.MSBuild\Workleap.OpenApi.MSBuild.csproj" ReferenceOutputAssembly="false" />
2222
</ItemGroup>
2323

24+
<ItemGroup>
25+
<None Update="custom.spectral.yaml">
26+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
27+
</None>
28+
</ItemGroup>
29+
2430
<Import Project="..\Workleap.OpenApi.MSBuild\msbuild\build\Workleap.OpenApi.MSBuild.targets" />
2531
</Project>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extends: [https://raw.githubusercontent.com/gsoft-inc/wl-api-guidelines/0.1.0/.spectral.yaml]

src/Workleap.OpenApi.MSBuild.sln

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi.MsBuild.SystemTest.S
2323
EndProject
2424
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi.MsBuild.SystemTest.GenericTest", "tests\WebApi.MsBuild.SystemTest.GenericTest\WebApi.MsBuild.SystemTest.GenericTest.csproj", "{502CEF5F-350E-4498-BA3C-3C09C9620737}"
2525
EndProject
26-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workleap.OpenApi.MSBuild.Tests", "tests\Workleap.OpenApi.MSBuild.Tests\Workleap.OpenApi.MSBuild.Tests.csproj", "{7CD01912-BA30-4F96-A397-E79A7E670E27}"
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workleap.OpenApi.MSBuild.Tests", "tests\Workleap.OpenApi.MSBuild.Tests\Workleap.OpenApi.MSBuild.Tests.csproj", "{E5EC1EFE-2271-4AFF-BED6-FEFD2B301423}"
2727
EndProject
2828
Global
2929
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -51,10 +51,10 @@ Global
5151
{502CEF5F-350E-4498-BA3C-3C09C9620737}.Debug|Any CPU.Build.0 = Debug|Any CPU
5252
{502CEF5F-350E-4498-BA3C-3C09C9620737}.Release|Any CPU.ActiveCfg = Release|Any CPU
5353
{502CEF5F-350E-4498-BA3C-3C09C9620737}.Release|Any CPU.Build.0 = Release|Any CPU
54-
{7CD01912-BA30-4F96-A397-E79A7E670E27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55-
{7CD01912-BA30-4F96-A397-E79A7E670E27}.Debug|Any CPU.Build.0 = Debug|Any CPU
56-
{7CD01912-BA30-4F96-A397-E79A7E670E27}.Release|Any CPU.ActiveCfg = Release|Any CPU
57-
{7CD01912-BA30-4F96-A397-E79A7E670E27}.Release|Any CPU.Build.0 = Release|Any CPU
54+
{E5EC1EFE-2271-4AFF-BED6-FEFD2B301423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55+
{E5EC1EFE-2271-4AFF-BED6-FEFD2B301423}.Debug|Any CPU.Build.0 = Debug|Any CPU
56+
{E5EC1EFE-2271-4AFF-BED6-FEFD2B301423}.Release|Any CPU.ActiveCfg = Release|Any CPU
57+
{E5EC1EFE-2271-4AFF-BED6-FEFD2B301423}.Release|Any CPU.Build.0 = Release|Any CPU
5858
EndGlobalSection
5959
GlobalSection(SolutionProperties) = preSolution
6060
HideSolutionNode = FALSE
@@ -64,7 +64,7 @@ Global
6464
{3909D38E-7584-4206-9CDC-3E56203BE6DB} = {4DDE83BF-D190-4CC9-AD36-E9250DABB27D}
6565
{C42C2836-4997-49D3-9BC6-E6A0E1B8C472} = {4DDE83BF-D190-4CC9-AD36-E9250DABB27D}
6666
{502CEF5F-350E-4498-BA3C-3C09C9620737} = {4DDE83BF-D190-4CC9-AD36-E9250DABB27D}
67-
{7CD01912-BA30-4F96-A397-E79A7E670E27} = {4DDE83BF-D190-4CC9-AD36-E9250DABB27D}
67+
{E5EC1EFE-2271-4AFF-BED6-FEFD2B301423} = {4DDE83BF-D190-4CC9-AD36-E9250DABB27D}
6868
EndGlobalSection
6969
GlobalSection(ExtensibilityGlobals) = postSolution
7070
SolutionGuid = {BCD029BE-FB3E-45A2-8DD4-FDE33D87544D}

src/Workleap.OpenApi.MSBuild/GenerateContractProcess.cs

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.Build.Framework;
2+
using Workleap.OpenApi.MSBuild.Spectral;
23

34
namespace Workleap.OpenApi.MSBuild;
45

@@ -11,15 +12,26 @@ namespace Workleap.OpenApi.MSBuild;
1112
internal class GenerateContractProcess
1213
{
1314
private readonly ILoggerWrapper _loggerWrapper;
14-
private readonly SpectralManager _spectralManager;
15+
private readonly SpectralInstaller _spectralInstaller;
16+
private readonly SpectralRulesetManager _spectralRulesetManager;
17+
private readonly SpectralRunner _spectralRunner;
1518
private readonly SwaggerManager _swaggerManager;
1619
private readonly SpecGeneratorManager _specGeneratorManager;
1720
private readonly OasdiffManager _oasdiffManager;
1821

19-
internal GenerateContractProcess(ILoggerWrapper loggerWrapper, SpectralManager spectralManager, SwaggerManager swaggerManager, SpecGeneratorManager specGeneratorManager, OasdiffManager oasdiffManager)
22+
internal GenerateContractProcess(
23+
ILoggerWrapper loggerWrapper,
24+
SpectralInstaller spectralInstaller,
25+
SpectralRulesetManager spectralRulesetManager,
26+
SpectralRunner spectralRunner,
27+
SwaggerManager swaggerManager,
28+
SpecGeneratorManager specGeneratorManager,
29+
OasdiffManager oasdiffManager)
2030
{
2131
this._loggerWrapper = loggerWrapper;
22-
this._spectralManager = spectralManager;
32+
this._spectralInstaller = spectralInstaller;
33+
this._spectralRulesetManager = spectralRulesetManager;
34+
this._spectralRunner = spectralRunner;
2335
this._swaggerManager = swaggerManager;
2436
this._specGeneratorManager = specGeneratorManager;
2537
this._oasdiffManager = oasdiffManager;
@@ -38,7 +50,7 @@ internal async Task Execute(
3850
CancellationToken cancellationToken)
3951
{
4052
this._loggerWrapper.LogMessage("Installing dependencies...");
41-
await this.InstallDependencies(mode, cancellationToken);
53+
var dependenciesResult = await this.InstallDependencies(mode, cancellationToken);
4254

4355
this._loggerWrapper.LogMessage("Running Swagger...");
4456
var generateOpenApiDocsPath = (await this._swaggerManager.RunSwaggerAsync(openApiSwaggerDocumentNames, cancellationToken)).ToList();
@@ -55,15 +67,21 @@ internal async Task Execute(
5567
}
5668

5769
this._loggerWrapper.LogMessage("Running Spectral...");
58-
await this._spectralManager.RunSpectralAsync(generateOpenApiDocsPath, cancellationToken);
70+
await this._spectralRunner.RunSpectralAsync(generateOpenApiDocsPath, dependenciesResult.SpectralExecutablePath, dependenciesResult.SpectralRulesetPath, cancellationToken);
5971
}
6072

61-
private async Task InstallDependencies(
73+
private async Task<DependenciesResult> InstallDependencies(
6274
GenerateContractMode mode,
6375
CancellationToken cancellationToken)
6476
{
6577
var installationTasks = new List<Task>();
66-
installationTasks.Add(this._spectralManager.InstallSpectralAsync(cancellationToken));
78+
79+
var spectralRulesetTask = this._spectralRulesetManager.GetLocalSpectralRulesetFile(cancellationToken);
80+
installationTasks.Add(spectralRulesetTask);
81+
82+
var spectralInstallerTask = this._spectralInstaller.InstallSpectralAsync(cancellationToken);
83+
installationTasks.Add(spectralInstallerTask);
84+
6785
installationTasks.Add(this._swaggerManager.InstallSwaggerCliAsync(cancellationToken));
6886

6987
if (mode == GenerateContractMode.SpecComparison)
@@ -73,5 +91,23 @@ private async Task InstallDependencies(
7391

7492
await Task.WhenAll(installationTasks);
7593
this._loggerWrapper.LogMessage("Finished installing OpenAPI dependencies.", MessageImportance.High);
94+
95+
var spectralRulesetPath = await spectralRulesetTask;
96+
var spectralExecutablePath = await spectralInstallerTask;
97+
98+
return new DependenciesResult(spectralRulesetPath, spectralExecutablePath);
99+
}
100+
101+
private class DependenciesResult
102+
{
103+
public DependenciesResult(string spectralRulesetPath, string spectralExecutablePath)
104+
{
105+
this.SpectralRulesetPath = spectralRulesetPath;
106+
this.SpectralExecutablePath = spectralExecutablePath;
107+
}
108+
109+
public string SpectralRulesetPath { get; }
110+
111+
public string SpectralExecutablePath { get; }
76112
}
77113
}

src/Workleap.OpenApi.MSBuild/ISpectralManager.cs

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/Workleap.OpenApi.MSBuild/SpectralDiffCalculator.cs renamed to src/Workleap.OpenApi.MSBuild/Spectral/DiffCalculator.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
using System.Security.Cryptography;
22

3-
namespace Workleap.OpenApi.MSBuild;
3+
namespace Workleap.OpenApi.MSBuild.Spectral;
44

5-
internal sealed class SpectralDiffCalculator
5+
/// <summary>
6+
/// Class that contains methods to check if some elements has changed since the last execution.
7+
/// </summary>
8+
internal sealed class DiffCalculator
69
{
710
private const string ChecksumExtension = "spectral-checksum";
811
private const string SpectralRulesetChecksumItemName = "spectral-ruleset-checksum";
912

1013
private readonly string _spectralOutputDirectoryPath;
1114

12-
public SpectralDiffCalculator(string spectralChecksumOutputDirectoryPath)
15+
public DiffCalculator(string spectralChecksumOutputDirectoryPath)
1316
{
1417
this._spectralOutputDirectoryPath = spectralChecksumOutputDirectoryPath;
1518
}
1619

17-
public bool HasRulesetChangedSinceLastExecution(string spectralRulset)
20+
public bool HasRulesetChangedSinceLastExecution(string spectralRulsetPath)
1821
{
1922
var preciousRulesetChecksum = this.GetItemChecksum(SpectralRulesetChecksumItemName);
20-
var currentRulesetChecksum = GetFileChecksum(spectralRulset);
23+
var currentRulesetChecksum = GetFileChecksum(spectralRulsetPath);
2124

2225
var hasRulesetChanged = !string.Equals(preciousRulesetChecksum, currentRulesetChecksum, StringComparison.OrdinalIgnoreCase);
2326

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
namespace Workleap.OpenApi.MSBuild.Spectral;
2+
3+
internal class SpectralInstaller
4+
{
5+
private const string SpectralVersion = "6.11.0";
6+
private const string SpectralDownloadUrlFormat = "https://github.com/stoplightio/spectral/releases/download/v{0}/{1}";
7+
8+
private readonly ILoggerWrapper _loggerWrapper;
9+
private readonly IHttpClientWrapper _httpClientWrapper;
10+
private readonly string _spectralDirectory;
11+
12+
public SpectralInstaller(
13+
ILoggerWrapper loggerWrapper,
14+
string openApiToolsDirectoryPath,
15+
IHttpClientWrapper httpClientWrapper)
16+
{
17+
this._loggerWrapper = loggerWrapper;
18+
this._httpClientWrapper = httpClientWrapper;
19+
this._spectralDirectory = Path.Combine(openApiToolsDirectoryPath, "spectral", SpectralVersion);
20+
}
21+
22+
/// <summary>
23+
/// Install spectral tool
24+
/// </summary>
25+
/// <returns>Return executable path</returns>
26+
public async Task<string> InstallSpectralAsync(CancellationToken cancellationToken)
27+
{
28+
this._loggerWrapper.LogMessage("Starting Spectral installation.");
29+
30+
Directory.CreateDirectory(this._spectralDirectory);
31+
32+
var executablePath = GetSpectralFileName();
33+
var url = string.Format(SpectralDownloadUrlFormat, SpectralVersion, executablePath);
34+
var destination = Path.Combine(this._spectralDirectory, executablePath);
35+
36+
await this._httpClientWrapper.DownloadFileToDestinationAsync(url, destination, cancellationToken);
37+
38+
this._loggerWrapper.LogMessage("Spectral installation completed.");
39+
40+
return executablePath;
41+
}
42+
43+
private static string GetSpectralFileName()
44+
{
45+
var osType = RuntimeInformationHelper.GetOperatingSystem();
46+
var architecture = RuntimeInformationHelper.GetArchitecture();
47+
48+
if (osType == "linux")
49+
{
50+
var distro = File.Exists("/etc/os-release") ? File.ReadAllText("/etc/os-release") : string.Empty;
51+
if (distro.Contains("Alpine Linux"))
52+
{
53+
osType = "alpine";
54+
}
55+
}
56+
57+
var fileName = $"spectral-{osType}-{architecture}";
58+
59+
if (osType == "windows")
60+
{
61+
fileName = "spectral.exe";
62+
}
63+
64+
return fileName;
65+
}
66+
}

0 commit comments

Comments
 (0)