fix(tools): improve build script discovery and update Verifier to System.CommandLine v8+
Build script: - Add Get-RepoRelativePath() helper for cross-platform path handling - Exclude node_modules and bin/obj from solution discovery Verifier: - Replace deprecated SetHandler with SetAction handler pattern - Use GetRequiredValue/GetValue instead of GetValueForOption - Replace SetDefaultValue with DefaultValueFactory property - Remove CommandLineBuilder wrapper (built into framework now) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,8 +31,29 @@ $ErrorActionPreference = 'Continue'
|
|||||||
$repoRoot = Split-Path -Parent $PSScriptRoot
|
$repoRoot = Split-Path -Parent $PSScriptRoot
|
||||||
$srcDir = Join-Path $repoRoot 'src'
|
$srcDir = Join-Path $repoRoot 'src'
|
||||||
|
|
||||||
|
function Get-RepoRelativePath {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Root,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Path
|
||||||
|
)
|
||||||
|
|
||||||
|
$normalizedRoot = [System.IO.Path]::GetFullPath($Root).TrimEnd('\', '/')
|
||||||
|
$normalizedPath = [System.IO.Path]::GetFullPath($Path)
|
||||||
|
|
||||||
|
if ($normalizedPath.StartsWith($normalizedRoot, [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||||
|
return $normalizedPath.Substring($normalizedRoot.Length).TrimStart('\', '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
return $normalizedPath
|
||||||
|
}
|
||||||
|
|
||||||
$solutions = Get-ChildItem -Path $srcDir -Filter '*.sln' -Recurse |
|
$solutions = Get-ChildItem -Path $srcDir -Filter '*.sln' -Recurse |
|
||||||
Where-Object { $_.Name -ne 'StellaOps.sln' } |
|
Where-Object {
|
||||||
|
$_.Name -ne 'StellaOps.sln' -and
|
||||||
|
$_.FullName -notmatch '[\\/](node_modules|bin|obj)[\\/]'
|
||||||
|
} |
|
||||||
Sort-Object FullName
|
Sort-Object FullName
|
||||||
|
|
||||||
if ($solutions.Count -eq 0) {
|
if ($solutions.Count -eq 0) {
|
||||||
@@ -50,7 +71,7 @@ $testFail = @()
|
|||||||
$testSkipped = @()
|
$testSkipped = @()
|
||||||
|
|
||||||
foreach ($sln in $solutions) {
|
foreach ($sln in $solutions) {
|
||||||
$rel = [System.IO.Path]::GetRelativePath($repoRoot, $sln.FullName)
|
$rel = Get-RepoRelativePath -Root $repoRoot -Path $sln.FullName
|
||||||
Write-Host "--- BUILD: $rel ---" -ForegroundColor Yellow
|
Write-Host "--- BUILD: $rel ---" -ForegroundColor Yellow
|
||||||
|
|
||||||
dotnet build $sln.FullName --configuration $Configuration --nologo -v quiet
|
dotnet build $sln.FullName --configuration $Configuration --nologo -v quiet
|
||||||
|
|||||||
@@ -13,13 +13,11 @@
|
|||||||
|
|
||||||
using StellaOps.Verifier;
|
using StellaOps.Verifier;
|
||||||
using System.CommandLine;
|
using System.CommandLine;
|
||||||
using System.CommandLine.Builder;
|
|
||||||
using System.CommandLine.Parsing;
|
|
||||||
|
|
||||||
var bundleOption = new Option<FileInfo>("--bundle", ["-b"])
|
var bundleOption = new Option<FileInfo>("--bundle", ["-b"])
|
||||||
{
|
{
|
||||||
Description = "Path to the evidence bundle to verify",
|
Description = "Path to the evidence bundle to verify",
|
||||||
IsRequired = true
|
Required = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var trustedKeysOption = new Option<FileInfo?>("--trusted-keys", ["-k"])
|
var trustedKeysOption = new Option<FileInfo?>("--trusted-keys", ["-k"])
|
||||||
@@ -39,33 +37,33 @@ var outputOption = new Option<FileInfo?>("--output", ["-o"])
|
|||||||
|
|
||||||
var formatOption = new Option<ReportFormat>("--format", ["-f"])
|
var formatOption = new Option<ReportFormat>("--format", ["-f"])
|
||||||
{
|
{
|
||||||
Description = "Report output format"
|
Description = "Report output format",
|
||||||
|
DefaultValueFactory = _ => ReportFormat.Markdown
|
||||||
};
|
};
|
||||||
formatOption.SetDefaultValue(ReportFormat.Markdown);
|
|
||||||
|
|
||||||
var verifySignaturesOption = new Option<bool>("--verify-signatures")
|
var verifySignaturesOption = new Option<bool>("--verify-signatures")
|
||||||
{
|
{
|
||||||
Description = "Verify bundle manifest signatures"
|
Description = "Verify bundle manifest signatures",
|
||||||
|
DefaultValueFactory = _ => true
|
||||||
};
|
};
|
||||||
verifySignaturesOption.SetDefaultValue(true);
|
|
||||||
|
|
||||||
var verifyTimestampsOption = new Option<bool>("--verify-timestamps")
|
var verifyTimestampsOption = new Option<bool>("--verify-timestamps")
|
||||||
{
|
{
|
||||||
Description = "Verify RFC 3161 timestamps"
|
Description = "Verify RFC 3161 timestamps",
|
||||||
|
DefaultValueFactory = _ => true
|
||||||
};
|
};
|
||||||
verifyTimestampsOption.SetDefaultValue(true);
|
|
||||||
|
|
||||||
var verifyDigestsOption = new Option<bool>("--verify-digests")
|
var verifyDigestsOption = new Option<bool>("--verify-digests")
|
||||||
{
|
{
|
||||||
Description = "Verify blob digests"
|
Description = "Verify blob digests",
|
||||||
|
DefaultValueFactory = _ => true
|
||||||
};
|
};
|
||||||
verifyDigestsOption.SetDefaultValue(true);
|
|
||||||
|
|
||||||
var verifyPairsOption = new Option<bool>("--verify-pairs")
|
var verifyPairsOption = new Option<bool>("--verify-pairs")
|
||||||
{
|
{
|
||||||
Description = "Verify pair artifacts (SBOM, delta-sig)"
|
Description = "Verify pair artifacts (SBOM, delta-sig)",
|
||||||
|
DefaultValueFactory = _ => true
|
||||||
};
|
};
|
||||||
verifyPairsOption.SetDefaultValue(true);
|
|
||||||
|
|
||||||
var quietOption = new Option<bool>("--quiet", ["-q"])
|
var quietOption = new Option<bool>("--quiet", ["-q"])
|
||||||
{
|
{
|
||||||
@@ -92,19 +90,19 @@ var verifyCommand = new Command("verify", "Verify an evidence bundle")
|
|||||||
verboseOption
|
verboseOption
|
||||||
};
|
};
|
||||||
|
|
||||||
verifyCommand.SetHandler(async (context) =>
|
verifyCommand.SetAction(async (parseResult, ct) =>
|
||||||
{
|
{
|
||||||
var bundle = context.ParseResult.GetValueForOption(bundleOption)!;
|
var bundle = parseResult.GetRequiredValue(bundleOption);
|
||||||
var trustedKeys = context.ParseResult.GetValueForOption(trustedKeysOption);
|
var trustedKeys = parseResult.GetValue(trustedKeysOption);
|
||||||
var trustProfile = context.ParseResult.GetValueForOption(trustProfileOption);
|
var trustProfile = parseResult.GetValue(trustProfileOption);
|
||||||
var output = context.ParseResult.GetValueForOption(outputOption);
|
var output = parseResult.GetValue(outputOption);
|
||||||
var format = context.ParseResult.GetValueForOption(formatOption);
|
var format = parseResult.GetValue(formatOption);
|
||||||
var verifySignatures = context.ParseResult.GetValueForOption(verifySignaturesOption);
|
var verifySignatures = parseResult.GetValue(verifySignaturesOption);
|
||||||
var verifyTimestamps = context.ParseResult.GetValueForOption(verifyTimestampsOption);
|
var verifyTimestamps = parseResult.GetValue(verifyTimestampsOption);
|
||||||
var verifyDigests = context.ParseResult.GetValueForOption(verifyDigestsOption);
|
var verifyDigests = parseResult.GetValue(verifyDigestsOption);
|
||||||
var verifyPairs = context.ParseResult.GetValueForOption(verifyPairsOption);
|
var verifyPairs = parseResult.GetValue(verifyPairsOption);
|
||||||
var quiet = context.ParseResult.GetValueForOption(quietOption);
|
var quiet = parseResult.GetValue(quietOption);
|
||||||
var verbose = context.ParseResult.GetValueForOption(verboseOption);
|
var verbose = parseResult.GetValue(verboseOption);
|
||||||
|
|
||||||
var options = new VerifierOptions
|
var options = new VerifierOptions
|
||||||
{
|
{
|
||||||
@@ -122,8 +120,7 @@ verifyCommand.SetHandler(async (context) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
var verifier = new BundleVerifier();
|
var verifier = new BundleVerifier();
|
||||||
var exitCode = await verifier.VerifyAsync(options, context.GetCancellationToken());
|
return await verifier.VerifyAsync(options, ct);
|
||||||
context.ExitCode = exitCode;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var infoCommand = new Command("info", "Display bundle information without verification")
|
var infoCommand = new Command("info", "Display bundle information without verification")
|
||||||
@@ -133,19 +130,18 @@ var infoCommand = new Command("info", "Display bundle information without verifi
|
|||||||
quietOption
|
quietOption
|
||||||
};
|
};
|
||||||
|
|
||||||
infoCommand.SetHandler(async (context) =>
|
infoCommand.SetAction(async (parseResult, ct) =>
|
||||||
{
|
{
|
||||||
var bundle = context.ParseResult.GetValueForOption(bundleOption)!;
|
var bundle = parseResult.GetRequiredValue(bundleOption);
|
||||||
var format = context.ParseResult.GetValueForOption(formatOption);
|
var format = parseResult.GetValue(formatOption);
|
||||||
var quiet = context.ParseResult.GetValueForOption(quietOption);
|
var quiet = parseResult.GetValue(quietOption);
|
||||||
|
|
||||||
var verifier = new BundleVerifier();
|
var verifier = new BundleVerifier();
|
||||||
var exitCode = await verifier.ShowInfoAsync(
|
return await verifier.ShowInfoAsync(
|
||||||
bundle.FullName,
|
bundle.FullName,
|
||||||
format,
|
format,
|
||||||
quiet,
|
quiet,
|
||||||
context.GetCancellationToken());
|
ct);
|
||||||
context.ExitCode = exitCode;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootCommand = new RootCommand("Stella Ops Bundle Verifier - Offline evidence bundle verification")
|
var rootCommand = new RootCommand("Stella Ops Bundle Verifier - Offline evidence bundle verification")
|
||||||
@@ -154,16 +150,17 @@ var rootCommand = new RootCommand("Stella Ops Bundle Verifier - Offline evidence
|
|||||||
infoCommand
|
infoCommand
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add version option
|
try
|
||||||
rootCommand.AddOption(new Option<bool>("--version", "Show version information"));
|
{
|
||||||
|
return await rootCommand.Parse(args).InvokeAsync();
|
||||||
var parser = new CommandLineBuilder(rootCommand)
|
}
|
||||||
.UseDefaults()
|
catch (OperationCanceledException)
|
||||||
.UseExceptionHandler((ex, context) =>
|
{
|
||||||
{
|
Console.Error.WriteLine("Verification cancelled.");
|
||||||
Console.Error.WriteLine($"Error: {ex.Message}");
|
return 2;
|
||||||
context.ExitCode = 2;
|
}
|
||||||
})
|
catch (Exception ex)
|
||||||
.Build();
|
{
|
||||||
|
Console.Error.WriteLine($"Error: {ex.Message}");
|
||||||
return await parser.InvokeAsync(args);
|
return 2;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,14 +20,6 @@
|
|||||||
<Product>Stella Ops Bundle Verifier</Product>
|
<Product>Stella Ops Bundle Verifier</Product>
|
||||||
<Description>Standalone verifier for Stella Ops evidence bundles</Description>
|
<Description>Standalone verifier for Stella Ops evidence bundles</Description>
|
||||||
|
|
||||||
<!-- Single-file and self-contained publishing -->
|
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
|
||||||
<SelfContained>true</SelfContained>
|
|
||||||
<PublishTrimmed>true</PublishTrimmed>
|
|
||||||
<TrimMode>partial</TrimMode>
|
|
||||||
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
|
|
||||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
|
||||||
|
|
||||||
<!-- Optimize for size -->
|
<!-- Optimize for size -->
|
||||||
<InvariantGlobalization>true</InvariantGlobalization>
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<DebuggerSupport>false</DebuggerSupport>
|
<DebuggerSupport>false</DebuggerSupport>
|
||||||
@@ -37,6 +29,14 @@
|
|||||||
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
|
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(PublishSingleFile)' == 'true'">
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishTrimmed>true</PublishTrimmed>
|
||||||
|
<TrimMode>partial</TrimMode>
|
||||||
|
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
|
||||||
|
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Runtime identifiers for cross-platform builds -->
|
<!-- Runtime identifiers for cross-platform builds -->
|
||||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == ''">
|
<PropertyGroup Condition="'$(RuntimeIdentifier)' == ''">
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;linux-musl-x64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;linux-musl-x64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
@@ -46,6 +46,12 @@
|
|||||||
<PackageReference Include="System.CommandLine" />
|
<PackageReference Include="System.CommandLine" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="__Tests\**\*.cs" />
|
||||||
|
<EmbeddedResource Remove="__Tests\**\*" />
|
||||||
|
<None Remove="__Tests\**\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Minimal dependencies for standalone operation -->
|
<!-- Minimal dependencies for standalone operation -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- No database, network, or heavy framework dependencies -->
|
<!-- No database, network, or heavy framework dependencies -->
|
||||||
|
|||||||
@@ -13,16 +13,12 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<UseConcelierTestInfra>false</UseConcelierTestInfra>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" />
|
<PackageReference Include="FluentAssertions" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
<PackageReference Include="xunit" />
|
|
||||||
<PackageReference Include="xunit.runner.visualstudio">
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="coverlet.collector">
|
<PackageReference Include="coverlet.collector">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
|||||||
Reference in New Issue
Block a user