Skip to content

Commit

Permalink
Implemented spectral report execution on build
Browse files Browse the repository at this point in the history
  • Loading branch information
Rushikesh Vyas committed Nov 2, 2023
1 parent 2a31f92 commit 0c7002f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 21 deletions.
4 changes: 3 additions & 1 deletion src/Workleap.OpenApi.MSBuild/ISpectralManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ namespace Workleap.OpenApi.MSBuild;

public interface ISpectralManager
{
public Task InstallSpectralAsync(CancellationToken cancellationToken);
public Task<string> InstallSpectralAsync(CancellationToken cancellationToken);

public Task RunSpectralAsync(IEnumerable<string> swaggerDocumentPaths, string rulesetUrl, string executableFilename, CancellationToken cancellationToken);
}
4 changes: 2 additions & 2 deletions src/Workleap.OpenApi.MSBuild/ISwaggerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ namespace Workleap.OpenApi.MSBuild;

public interface ISwaggerManager
{
Task RunSwaggerAsync(string[] openApiSwaggerDocumentNames, CancellationToken cancellationToken);
Task<IEnumerable<string>> RunSwaggerAsync(string[] openApiSwaggerDocumentNames, CancellationToken cancellationToken);

Task InstallSwaggerCliAsync(CancellationToken cancellationToken);

Task GenerateOpenApiSpecAsync(string swaggerExePath, string outputOpenApiSpecPath, string documentName, CancellationToken cancellationToken);
Task<string> GenerateOpenApiSpecAsync(string swaggerExePath, string outputOpenApiSpecPath, string documentName, CancellationToken cancellationToken);
}
43 changes: 36 additions & 7 deletions src/Workleap.OpenApi.MSBuild/SpectralManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;

namespace Workleap.OpenApi.MSBuild;

Expand All @@ -9,23 +8,44 @@ internal sealed class SpectralManager : ISpectralManager

private readonly ILoggerWrapper _loggerWrapper;
private readonly IHttpClientWrapper _httpClientWrapper;
private readonly string _toolDirectory;
private readonly string _spectralDirectory;
private readonly string _openApiToolsDirectory;
private readonly IProcessWrapper _processWrapper;

public SpectralManager(LoggerWrapper loggerWrapper, string openApiToolsDirectoryPath, IHttpClientWrapper httpClientWrapper)
public SpectralManager(ILoggerWrapper loggerWrapper, string openApiToolsDirectoryPath, IHttpClientWrapper httpClientWrapper, IProcessWrapper processWrapper)
{
this._loggerWrapper = loggerWrapper;
this._httpClientWrapper = httpClientWrapper;
this._toolDirectory = Path.Combine(openApiToolsDirectoryPath, "spectral", SpectralVersion);
this._openApiToolsDirectory = openApiToolsDirectoryPath;
this._spectralDirectory = Path.Combine(openApiToolsDirectoryPath, "spectral", SpectralVersion);
this._processWrapper = processWrapper;
}

public async Task InstallSpectralAsync(CancellationToken cancellationToken)
public async Task<string> InstallSpectralAsync(CancellationToken cancellationToken)
{
Directory.CreateDirectory(this._toolDirectory);
Directory.CreateDirectory(this._spectralDirectory);

var executableFileName = GetSpectralFileName();
var url = $"https://github.com/stoplightio/spectral/releases/download/v{SpectralVersion}/{executableFileName}";

await this._httpClientWrapper.DownloadFileToDestinationAsync(url, Path.Combine(this._toolDirectory, executableFileName), cancellationToken);
await this._httpClientWrapper.DownloadFileToDestinationAsync(url, Path.Combine(this._spectralDirectory, executableFileName), cancellationToken);
return executableFileName;
}

public async Task RunSpectralAsync(IEnumerable<string> swaggerDocumentPaths, string rulesetUrl, string executableFilename, CancellationToken cancellationToken)
{
this._loggerWrapper.LogMessage("Starting Spectral report generation.");

var spectralExecutePath = Path.Combine(this._spectralDirectory, executableFilename);
var reportsPath = Path.Combine(this._openApiToolsDirectory, "reports");
Directory.CreateDirectory(reportsPath);

foreach (var documentPath in swaggerDocumentPaths)
{
var documentName = Path.GetFileNameWithoutExtension(documentPath);
var outputSpectralReportName = $"spectral-{documentName}.html";
await this.GenerateSpectralReport(documentPath, rulesetUrl, spectralExecutePath, Path.Combine(reportsPath, outputSpectralReportName), cancellationToken);
}
}

private static string GetSpectralFileName()
Expand Down Expand Up @@ -86,4 +106,13 @@ private static string GetArchitecture()

throw new OpenApiTaskFailedException("Unknown processor architecture encountered");
}

private async Task GenerateSpectralReport(string swaggerDocumentPath, string rulesetUrl, string spectralExecutePath, string htmlReportPath, CancellationToken cancellationToken)
{
var exitCode = await this._processWrapper.RunProcessAsync(spectralExecutePath, new[] { "lint", swaggerDocumentPath, "--ruleset", rulesetUrl, "--format", "html", "--output.html", htmlReportPath }, cancellationToken);
if (exitCode != 0)
{
throw new OpenApiTaskFailedException($"Spectral report for {swaggerDocumentPath} could not be created.");
}
}
}
17 changes: 12 additions & 5 deletions src/Workleap.OpenApi.MSBuild/SwaggerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,32 @@ internal sealed class SwaggerManager : ISwaggerManager
private readonly ILoggerWrapper _loggerWrapper;
private readonly string _openApiWebApiAssemblyPath;
private readonly string _swaggerDirectory;
private readonly string _openApiToolsDirectoryPath;

public SwaggerManager(IProcessWrapper processWrapper, ILoggerWrapper loggerWrapper, string openApiToolsDirectoryPath, string openApiWebApiAssemblyPath)
{
this._processWrapper = processWrapper;
this._loggerWrapper = loggerWrapper;
this._openApiWebApiAssemblyPath = openApiWebApiAssemblyPath;
this._openApiToolsDirectoryPath = openApiToolsDirectoryPath;
this._swaggerDirectory = Path.Combine(openApiToolsDirectoryPath, "swagger", SwaggerVersion);
}

public async Task RunSwaggerAsync(string[] openApiSwaggerDocumentNames, CancellationToken cancellationToken)
public async Task<IEnumerable<string>> RunSwaggerAsync(string[] openApiSwaggerDocumentNames, CancellationToken cancellationToken)
{
var swaggerExePath = Path.Combine(this._swaggerDirectory, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "swagger.exe" : "swagger");
var taskList = new List<Task<string>>();

foreach (var documentName in openApiSwaggerDocumentNames)
{
var outputOpenApiSpecName = $"openapi-{documentName.ToLowerInvariant()}.yaml";

var outputOpenApiSpecPath = Path.Combine(this._swaggerDirectory, outputOpenApiSpecName);
var outputOpenApiSpecPath = Path.Combine(this._openApiToolsDirectoryPath, outputOpenApiSpecName);

await this.GenerateOpenApiSpecAsync(swaggerExePath, outputOpenApiSpecPath, documentName, cancellationToken);
taskList.Add(this.GenerateOpenApiSpecAsync(swaggerExePath, outputOpenApiSpecPath, documentName, cancellationToken));
}

return await Task.WhenAll(taskList);
}

public async Task InstallSwaggerCliAsync(CancellationToken cancellationToken)
Expand All @@ -55,13 +60,15 @@ public async Task InstallSwaggerCliAsync(CancellationToken cancellationToken)
}
}

public async Task GenerateOpenApiSpecAsync(string swaggerExePath, string outputOpenApiSpecPath, string documentName, CancellationToken cancellationToken)
public async Task<string> GenerateOpenApiSpecAsync(string swaggerExePath, string outputOpenApiSpecPath, string documentName, CancellationToken cancellationToken)
{
var exitCode = await this._processWrapper.RunProcessAsync(swaggerExePath, new[] { "tofile", "--output", outputOpenApiSpecPath, "--yaml", this._openApiWebApiAssemblyPath, documentName }, cancellationToken);

if (exitCode != 0)
{
throw new OpenApiTaskFailedException("OpenApi file could not be created.");
throw new OpenApiTaskFailedException($"OpenApi file {outputOpenApiSpecPath} could not be created.");
}

return outputOpenApiSpecPath;
}
}
13 changes: 7 additions & 6 deletions src/Workleap.OpenApi.MSBuild/ValidateOpenApiTask.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.Build.Framework;
using Microsoft.Build.Framework;

namespace Workleap.OpenApi.MSBuild;

Expand Down Expand Up @@ -28,10 +28,10 @@ protected override async Task<bool> ExecuteAsync(CancellationToken cancellationT
{
var loggerWrapper = new LoggerWrapper(this.Log);
var processWrapper = new ProcessWrapper(this.OpenApiToolsDirectoryPath);
var swaggerManager = new SwaggerManager(processWrapper, loggerWrapper, this.OpenApiToolsDirectoryPath, this.OpenApiToolsDirectoryPath);
var swaggerManager = new SwaggerManager(processWrapper, loggerWrapper, this.OpenApiToolsDirectoryPath, this.OpenApiWebApiAssemblyPath);
using var httpClientWrapper = new HttpClientWrapper();

var spectralManager = new SpectralManager(loggerWrapper, this.OpenApiToolsDirectoryPath, httpClientWrapper);
var spectralManager = new SpectralManager(loggerWrapper, this.OpenApiToolsDirectoryPath, httpClientWrapper, processWrapper);

this.Log.LogMessage(MessageImportance.Low, "{0} = '{1}'", nameof(this.OpenApiWebApiAssemblyPath), this.OpenApiWebApiAssemblyPath);
this.Log.LogMessage(MessageImportance.Low, "{0} = '{1}'", nameof(this.OpenApiToolsDirectoryPath), this.OpenApiToolsDirectoryPath);
Expand All @@ -51,13 +51,14 @@ protected override async Task<bool> ExecuteAsync(CancellationToken cancellationT
await this.GeneratePublicNugetSource();

await swaggerManager.InstallSwaggerCliAsync(cancellationToken);
await spectralManager.InstallSpectralAsync(cancellationToken);
var spectralExecutableFile = await spectralManager.InstallSpectralAsync(cancellationToken);

// await swaggerManager.RunSwaggerAsync(this.OpenApiSwaggerDocumentNames, cancellationToken);
var swaggerDocPaths = await swaggerManager.RunSwaggerAsync(this.OpenApiSwaggerDocumentNames, cancellationToken);
await spectralManager.RunSpectralAsync(swaggerDocPaths, this.OpenApiSpectralRulesetUrl, spectralExecutableFile, cancellationToken);
}
catch (OpenApiTaskFailedException e)
{
this.Log.LogWarning("An error occured while validating the OpenAPI specification: {0}", e.Message);
this.Log.LogWarning("An error occurred while validating the OpenAPI specification: {0}", e.Message);
}

return true;
Expand Down

0 comments on commit 0c7002f

Please sign in to comment.