Add call graph fixtures for various languages and scenarios
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
Lighthouse CI / Lighthouse Audit (push) Has been cancelled
Lighthouse CI / Axe Accessibility Audit (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Reachability Corpus Validation / validate-corpus (push) Has been cancelled
Reachability Corpus Validation / validate-ground-truths (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Reachability Corpus Validation / determinism-check (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
Lighthouse CI / Lighthouse Audit (push) Has been cancelled
Lighthouse CI / Axe Accessibility Audit (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Reachability Corpus Validation / validate-corpus (push) Has been cancelled
Reachability Corpus Validation / validate-ground-truths (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Reachability Corpus Validation / determinism-check (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
- Introduced `all-edge-reasons.json` to test edge resolution reasons in .NET. - Added `all-visibility-levels.json` to validate method visibility levels in .NET. - Created `dotnet-aspnetcore-minimal.json` for a minimal ASP.NET Core application. - Included `go-gin-api.json` for a Go Gin API application structure. - Added `java-spring-boot.json` for the Spring PetClinic application in Java. - Introduced `legacy-no-schema.json` for legacy application structure without schema. - Created `node-express-api.json` for an Express.js API application structure.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -12,4 +13,52 @@ public interface IDeploymentRefsRepository
|
||||
/// Counts distinct deployments referencing a package.
|
||||
/// </summary>
|
||||
Task<int> CountDeploymentsAsync(string purl, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets deployment IDs referencing a package.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<string>> GetDeploymentIdsAsync(string purl, int limit, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Records or updates a deployment reference.
|
||||
/// </summary>
|
||||
Task UpsertAsync(DeploymentRef deployment, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Records multiple deployment references in a batch.
|
||||
/// </summary>
|
||||
Task BulkUpsertAsync(IEnumerable<DeploymentRef> deployments, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets deployment summary for a package.
|
||||
/// </summary>
|
||||
Task<DeploymentSummary?> GetSummaryAsync(string purl, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a deployment reference record.
|
||||
/// </summary>
|
||||
public sealed class DeploymentRef
|
||||
{
|
||||
public required string Purl { get; init; }
|
||||
public string? PurlVersion { get; init; }
|
||||
public required string ImageId { get; init; }
|
||||
public string? ImageDigest { get; init; }
|
||||
public required string Environment { get; init; }
|
||||
public string? Namespace { get; init; }
|
||||
public string? Cluster { get; init; }
|
||||
public string? Region { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of deployments for a package.
|
||||
/// </summary>
|
||||
public sealed class DeploymentSummary
|
||||
{
|
||||
public required string Purl { get; init; }
|
||||
public int ImageCount { get; init; }
|
||||
public int EnvironmentCount { get; init; }
|
||||
public int TotalDeployments { get; init; }
|
||||
public DateTimeOffset? LastDeployment { get; init; }
|
||||
public DateTimeOffset? FirstDeployment { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -15,11 +17,53 @@ public interface IGraphMetricsRepository
|
||||
string symbolId,
|
||||
string callgraphId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Stores computed metrics for a node.
|
||||
/// </summary>
|
||||
Task UpsertAsync(GraphMetrics metrics, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Bulk stores metrics for a call graph.
|
||||
/// </summary>
|
||||
Task BulkUpsertAsync(IEnumerable<GraphMetrics> metrics, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets callgraph IDs that need recomputation (older than threshold).
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<string>> GetStaleCallgraphsAsync(
|
||||
TimeSpan maxAge,
|
||||
int limit,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all metrics for a callgraph.
|
||||
/// </summary>
|
||||
Task DeleteByCallgraphAsync(string callgraphId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Centrality metrics for a symbol.
|
||||
/// </summary>
|
||||
public sealed record GraphMetrics(
|
||||
int Degree,
|
||||
double Betweenness);
|
||||
public sealed class GraphMetrics
|
||||
{
|
||||
public required string NodeId { get; init; }
|
||||
public required string CallgraphId { get; init; }
|
||||
public string NodeType { get; init; } = "symbol";
|
||||
|
||||
public int Degree { get; init; }
|
||||
public int InDegree { get; init; }
|
||||
public int OutDegree { get; init; }
|
||||
public double Betweenness { get; init; }
|
||||
public double? Closeness { get; init; }
|
||||
|
||||
public double? NormalizedBetweenness { get; init; }
|
||||
public double? NormalizedDegree { get; init; }
|
||||
|
||||
public DateTimeOffset ComputedAt { get; init; }
|
||||
public int? ComputationDurationMs { get; init; }
|
||||
public string AlgorithmVersion { get; init; } = "1.0";
|
||||
|
||||
public int? TotalNodes { get; init; }
|
||||
public int? TotalEdges { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -7,6 +10,7 @@ namespace StellaOps.Signals.Persistence;
|
||||
public sealed class InMemoryDeploymentRefsRepository : IDeploymentRefsRepository
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, int> _deploymentsByPurl = new(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, List<DeploymentRef>> _refsByPurl = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public void SetDeployments(string purl, int deployments)
|
||||
{
|
||||
@@ -28,6 +32,82 @@ public sealed class InMemoryDeploymentRefsRepository : IDeploymentRefsRepository
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
return Task.FromResult(_deploymentsByPurl.TryGetValue(purl.Trim(), out var count) ? count : 0);
|
||||
var key = purl.Trim();
|
||||
if (_deploymentsByPurl.TryGetValue(key, out var count))
|
||||
return Task.FromResult(count);
|
||||
|
||||
if (_refsByPurl.TryGetValue(key, out var refs))
|
||||
return Task.FromResult(refs.Count);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> GetDeploymentIdsAsync(string purl, int limit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(purl))
|
||||
return Task.FromResult<IReadOnlyList<string>>(Array.Empty<string>());
|
||||
|
||||
if (_refsByPurl.TryGetValue(purl.Trim(), out var refs))
|
||||
return Task.FromResult<IReadOnlyList<string>>(refs.Take(limit).Select(r => r.ImageId).ToList());
|
||||
|
||||
return Task.FromResult<IReadOnlyList<string>>(Array.Empty<string>());
|
||||
}
|
||||
|
||||
public Task UpsertAsync(DeploymentRef deployment, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ArgumentNullException.ThrowIfNull(deployment);
|
||||
|
||||
var key = deployment.Purl.Trim();
|
||||
_refsByPurl.AddOrUpdate(
|
||||
key,
|
||||
_ => new List<DeploymentRef> { deployment },
|
||||
(_, list) =>
|
||||
{
|
||||
var existing = list.FindIndex(r =>
|
||||
r.ImageId == deployment.ImageId &&
|
||||
r.Environment == deployment.Environment);
|
||||
if (existing >= 0)
|
||||
list[existing] = deployment;
|
||||
else
|
||||
list.Add(deployment);
|
||||
return list;
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task BulkUpsertAsync(IEnumerable<DeploymentRef> deployments, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ArgumentNullException.ThrowIfNull(deployments);
|
||||
|
||||
foreach (var deployment in deployments)
|
||||
{
|
||||
UpsertAsync(deployment, cancellationToken).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<DeploymentSummary?> GetSummaryAsync(string purl, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(purl))
|
||||
return Task.FromResult<DeploymentSummary?>(null);
|
||||
|
||||
if (!_refsByPurl.TryGetValue(purl.Trim(), out var refs) || refs.Count == 0)
|
||||
return Task.FromResult<DeploymentSummary?>(null);
|
||||
|
||||
return Task.FromResult<DeploymentSummary?>(new DeploymentSummary
|
||||
{
|
||||
Purl = purl,
|
||||
ImageCount = refs.Select(r => r.ImageId).Distinct().Count(),
|
||||
EnvironmentCount = refs.Select(r => r.Environment).Distinct().Count(),
|
||||
TotalDeployments = refs.Count
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -30,6 +33,64 @@ public sealed class InMemoryGraphMetricsRepository : IGraphMetricsRepository
|
||||
return Task.FromResult(_metrics.TryGetValue(key, out var metrics) ? metrics : null);
|
||||
}
|
||||
|
||||
public Task UpsertAsync(GraphMetrics metrics, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ArgumentNullException.ThrowIfNull(metrics);
|
||||
|
||||
var key = BuildKey(metrics.NodeId, metrics.CallgraphId);
|
||||
_metrics[key] = metrics;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task BulkUpsertAsync(IEnumerable<GraphMetrics> metrics, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ArgumentNullException.ThrowIfNull(metrics);
|
||||
|
||||
foreach (var m in metrics)
|
||||
{
|
||||
var key = BuildKey(m.NodeId, m.CallgraphId);
|
||||
_metrics[key] = m;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> GetStaleCallgraphsAsync(TimeSpan maxAge, int limit, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var cutoff = DateTimeOffset.UtcNow - maxAge;
|
||||
var staleGraphs = _metrics.Values
|
||||
.Where(m => m.ComputedAt < cutoff)
|
||||
.Select(m => m.CallgraphId)
|
||||
.Distinct()
|
||||
.Take(limit)
|
||||
.ToList();
|
||||
|
||||
return Task.FromResult<IReadOnlyList<string>>(staleGraphs);
|
||||
}
|
||||
|
||||
public Task DeleteByCallgraphAsync(string callgraphId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(callgraphId))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var keysToRemove = _metrics.Keys
|
||||
.Where(k => k.StartsWith(callgraphId.Trim() + "|", StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
foreach (var key in keysToRemove)
|
||||
{
|
||||
_metrics.TryRemove(key, out _);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static string BuildKey(string symbolId, string callgraphId)
|
||||
=> $"{callgraphId.Trim()}|{symbolId.Trim()}";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user