up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
sdk-generator-smoke / sdk-smoke (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
sdk-generator-smoke / sdk-smoke (push) Has been cancelled
This commit is contained in:
@@ -7,12 +7,13 @@ namespace StellaOps.Scanner.Worker.Determinism;
|
||||
/// </summary>
|
||||
public sealed class DeterminismContext
|
||||
{
|
||||
public DeterminismContext(bool fixedClock, DateTimeOffset fixedInstantUtc, int? rngSeed, bool filterLogs)
|
||||
public DeterminismContext(bool fixedClock, DateTimeOffset fixedInstantUtc, int? rngSeed, bool filterLogs, int? concurrencyLimit)
|
||||
{
|
||||
FixedClock = fixedClock;
|
||||
FixedInstantUtc = fixedInstantUtc.ToUniversalTime();
|
||||
RngSeed = rngSeed;
|
||||
FilterLogs = filterLogs;
|
||||
ConcurrencyLimit = concurrencyLimit;
|
||||
}
|
||||
|
||||
public bool FixedClock { get; }
|
||||
@@ -22,4 +23,6 @@ public sealed class DeterminismContext
|
||||
public int? RngSeed { get; }
|
||||
|
||||
public bool FilterLogs { get; }
|
||||
|
||||
public int? ConcurrencyLimit { get; }
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ internal sealed class SurfaceManifestStageExecutor : IScanStageExecutor
|
||||
private readonly ILogger<SurfaceManifestStageExecutor> _logger;
|
||||
private readonly ICryptoHash _hash;
|
||||
private readonly IRubyPackageInventoryStore _rubyPackageStore;
|
||||
private readonly Determinism.DeterminismContext _determinism;
|
||||
private readonly string _componentVersion;
|
||||
|
||||
public SurfaceManifestStageExecutor(
|
||||
@@ -51,7 +52,8 @@ internal sealed class SurfaceManifestStageExecutor : IScanStageExecutor
|
||||
ScannerWorkerMetrics metrics,
|
||||
ILogger<SurfaceManifestStageExecutor> logger,
|
||||
ICryptoHash hash,
|
||||
IRubyPackageInventoryStore rubyPackageStore)
|
||||
IRubyPackageInventoryStore rubyPackageStore,
|
||||
Determinism.DeterminismContext determinism)
|
||||
{
|
||||
_publisher = publisher ?? throw new ArgumentNullException(nameof(publisher));
|
||||
_surfaceCache = surfaceCache ?? throw new ArgumentNullException(nameof(surfaceCache));
|
||||
@@ -60,6 +62,7 @@ internal sealed class SurfaceManifestStageExecutor : IScanStageExecutor
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_hash = hash ?? throw new ArgumentNullException(nameof(hash));
|
||||
_rubyPackageStore = rubyPackageStore ?? throw new ArgumentNullException(nameof(rubyPackageStore));
|
||||
_determinism = determinism ?? throw new ArgumentNullException(nameof(determinism));
|
||||
_componentVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown";
|
||||
}
|
||||
|
||||
@@ -221,9 +224,56 @@ internal sealed class SurfaceManifestStageExecutor : IScanStageExecutor
|
||||
}));
|
||||
}
|
||||
|
||||
var determinismPayload = BuildDeterminismPayload(context, payloads);
|
||||
if (determinismPayload is not null)
|
||||
{
|
||||
payloads.Add(determinismPayload);
|
||||
}
|
||||
|
||||
return payloads;
|
||||
}
|
||||
|
||||
private SurfaceManifestPayload? BuildDeterminismPayload(ScanJobContext context, IEnumerable<SurfaceManifestPayload> payloads)
|
||||
{
|
||||
var pins = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
if (context.Lease.Metadata.TryGetValue("determinism.feed", out var feed) && !string.IsNullOrWhiteSpace(feed))
|
||||
{
|
||||
pins["feed"] = feed;
|
||||
}
|
||||
|
||||
if (context.Lease.Metadata.TryGetValue("determinism.policy", out var policy) && !string.IsNullOrWhiteSpace(policy))
|
||||
{
|
||||
pins["policy"] = policy;
|
||||
}
|
||||
|
||||
var artifactHashes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var payload in payloads)
|
||||
{
|
||||
var digest = ComputeDigest(payload.Content.Span);
|
||||
artifactHashes[payload.Kind] = digest;
|
||||
}
|
||||
|
||||
var report = new
|
||||
{
|
||||
fixedClock = _determinism.FixedClock,
|
||||
fixedInstantUtc = _determinism.FixedInstantUtc,
|
||||
rngSeed = _determinism.RngSeed,
|
||||
filterLogs = _determinism.FilterLogs,
|
||||
concurrencyLimit = _determinism.ConcurrencyLimit,
|
||||
pins = pins,
|
||||
artifacts = artifactHashes
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(report, JsonOptions);
|
||||
return new SurfaceManifestPayload(
|
||||
ArtifactDocumentType.SurfaceObservation,
|
||||
ArtifactDocumentFormat.ObservationJson,
|
||||
Kind: "determinism.json",
|
||||
MediaType: "application/json",
|
||||
Content: Encoding.UTF8.GetBytes(json),
|
||||
View: "replay");
|
||||
}
|
||||
|
||||
private async Task PersistRubyPackagesAsync(ScanJobContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!context.Analysis.TryGet<ReadOnlyDictionary<string, LanguageAnalyzerResult>>(ScanAnalysisKeys.LanguageAnalyzerResults, out var results))
|
||||
|
||||
@@ -58,7 +58,8 @@ builder.Services.AddSingleton(new DeterminismContext(
|
||||
workerOptions.Determinism.FixedClock,
|
||||
workerOptions.Determinism.FixedInstantUtc,
|
||||
workerOptions.Determinism.RngSeed,
|
||||
workerOptions.Determinism.FilterLogs));
|
||||
workerOptions.Determinism.FilterLogs,
|
||||
workerOptions.Determinism.ConcurrencyLimit));
|
||||
builder.Services.AddSingleton<IDeterministicRandomProvider>(_ => new DeterministicRandomProvider(workerOptions.Determinism.RngSeed));
|
||||
builder.Services.AddScannerCache(builder.Configuration);
|
||||
builder.Services.AddSurfaceEnvironment(options =>
|
||||
|
||||
Reference in New Issue
Block a user