Skip to content
87 changes: 86 additions & 1 deletion src/Smartstore.Build/Smartstore.Build/Build.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Nuke.Common;
using Nuke.Common.CI;
using Nuke.Common.Git;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.GitVersion;
using Serilog;
Expand Down Expand Up @@ -45,6 +47,10 @@ class Build : NukeBuild
AbsolutePath SourceDirectory => RootDirectory / "src";
AbsolutePath TestsDirectory => RootDirectory / "test";
AbsolutePath ArtifactsDirectory => RootDirectory / "build" / "artifacts";
AbsolutePath ToolsDirectory => RootDirectory / "build" / ".tools";
AbsolutePath SbomToolPath => ToolsDirectory / (EnvironmentInfo.Platform == PlatformFamily.Windows ? "sbom-tool.exe" : "sbom-tool");
const string SbomToolPackage = "Microsoft.Sbom.DotNetTool";
const string SbomToolVersion = "4.1.4";

string GetPublishName()
{
Expand Down Expand Up @@ -97,7 +103,7 @@ string GetPublishName()

Target Deploy => _ => _
.DependsOn(Compile)
.Triggers(Zip)
.Triggers(Zip, GenerateSbom)
.Executes(() =>
{
var publishName = GetPublishName();
Expand All @@ -123,6 +129,72 @@ string GetPublishName()
.SetOutput(outputDir));
});

Target GenerateSbom => _ => _
.DependsOn(Deploy)
.Executes(() =>
{
EnsureSbomTool();

var publishName = GetPublishName();
AbsolutePath publishDirectory = ArtifactsDirectory / publishName;
AbsolutePath buildComponentDirectory = SourceDirectory;

if (!publishDirectory.DirectoryExists())
{
throw new Exception($"Published output for {publishName} not found in {ArtifactsDirectory}.");
}

AbsolutePath manifestRootDirectory = publishDirectory;
AbsolutePath manifestDirectory = manifestRootDirectory / "_manifest";
AbsolutePath generatedManifestDirectory = manifestDirectory / "spdx_2.2";
AbsolutePath generatedManifest = generatedManifestDirectory / "manifest.spdx.json";
AbsolutePath sbomDirectory = publishDirectory / "sbom";
AbsolutePath sbomFile = sbomDirectory / "manifest.spdx.json";

Log.Information($"Generating SBOM for {publishName} using Microsoft SBOM Tool...");

manifestDirectory.CreateOrCleanDirectory();

var exclusions = string.Join(';', new string[]
{
"*.cshtml",
"*.scss",
"*.css",
"*.png",
"*.gif",
"*.jpg"
});

var arguments = string.Join(" ", new string[]
{
"generate",
"-b", publishDirectory,
"-bc", buildComponentDirectory,
"-ps", "Smartstore",
"-nsb", "https://smartstore.com",
"-pn", "Smartstore",
"-pv", Version,
"-m", manifestRootDirectory,
"-e", exclusions
}.Select(x => $"\"{x}\""));

ProcessTasks.StartProcess(SbomToolPath, arguments)
.AssertZeroExitCode();

if (!File.Exists(generatedManifest))
{
throw new Exception($"SBOM manifest not found at {generatedManifest}.");
}

sbomDirectory.CreateOrCleanDirectory();
File.Copy(generatedManifest, sbomFile, overwrite: true);

if (Directory.Exists(generatedManifestDirectory))
{
Directory.Delete(generatedManifestDirectory, recursive: true);
}
});

Target Zip => _ => _
.Executes(() =>
{
Expand Down Expand Up @@ -152,4 +224,17 @@ string GetPublishName()
.SetConfiguration(Configuration));
});

void EnsureSbomTool()
{
ToolsDirectory.CreateDirectory();

if (File.Exists(SbomToolPath))
{
return;
}

Log.Information("Installing Microsoft SBOM Tool dotnet tool...");
DotNet($"tool install --tool-path \"{ToolsDirectory}\" {SbomToolPackage} --version {SbomToolVersion}");
}

}