fixes save
This commit is contained in:
@@ -28,6 +28,7 @@ services:
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ./postgres-init:/docker-entrypoint-initdb.d:ro
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
networks:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
-- PostgreSQL initialization for StellaOps air-gap deployment
|
||||
-- ============================================================================
|
||||
-- PostgreSQL initialization for StellaOps
|
||||
-- This script runs automatically on first container start
|
||||
-- ============================================================================
|
||||
|
||||
-- Enable pg_stat_statements extension for query performance analysis
|
||||
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
||||
@@ -9,25 +11,59 @@ CREATE EXTENSION IF NOT EXISTS pg_trgm; -- Fuzzy text search
|
||||
CREATE EXTENSION IF NOT EXISTS btree_gin; -- GIN indexes for scalar types
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- Cryptographic functions
|
||||
|
||||
-- ============================================================================
|
||||
-- Create schemas for all modules
|
||||
-- Migrations will create tables within these schemas
|
||||
CREATE SCHEMA IF NOT EXISTS authority;
|
||||
CREATE SCHEMA IF NOT EXISTS vuln;
|
||||
CREATE SCHEMA IF NOT EXISTS vex;
|
||||
CREATE SCHEMA IF NOT EXISTS scheduler;
|
||||
CREATE SCHEMA IF NOT EXISTS notify;
|
||||
CREATE SCHEMA IF NOT EXISTS policy;
|
||||
CREATE SCHEMA IF NOT EXISTS concelier;
|
||||
CREATE SCHEMA IF NOT EXISTS audit;
|
||||
CREATE SCHEMA IF NOT EXISTS unknowns;
|
||||
-- ============================================================================
|
||||
|
||||
-- Grant usage to application user (assumes POSTGRES_USER is the app user)
|
||||
GRANT USAGE ON SCHEMA authority TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA vuln TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA vex TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA scheduler TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA notify TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA policy TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA concelier TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA audit TO PUBLIC;
|
||||
GRANT USAGE ON SCHEMA unknowns TO PUBLIC;
|
||||
-- Core Platform
|
||||
CREATE SCHEMA IF NOT EXISTS authority; -- Authentication, authorization, OAuth/OIDC
|
||||
|
||||
-- Data Ingestion
|
||||
CREATE SCHEMA IF NOT EXISTS vuln; -- Concelier vulnerability data
|
||||
CREATE SCHEMA IF NOT EXISTS vex; -- Excititor VEX documents
|
||||
|
||||
-- Scanning & Analysis
|
||||
CREATE SCHEMA IF NOT EXISTS scanner; -- Container scanning, SBOM generation
|
||||
|
||||
-- Scheduling & Orchestration
|
||||
CREATE SCHEMA IF NOT EXISTS scheduler; -- Job scheduling
|
||||
CREATE SCHEMA IF NOT EXISTS taskrunner; -- Task execution
|
||||
|
||||
-- Policy & Risk
|
||||
CREATE SCHEMA IF NOT EXISTS policy; -- Policy engine
|
||||
CREATE SCHEMA IF NOT EXISTS unknowns; -- Unknown component tracking
|
||||
|
||||
-- Artifacts & Evidence
|
||||
CREATE SCHEMA IF NOT EXISTS proofchain; -- Attestor proof chains
|
||||
CREATE SCHEMA IF NOT EXISTS attestor; -- Attestor submission queue
|
||||
CREATE SCHEMA IF NOT EXISTS signer; -- Key management
|
||||
|
||||
-- Notifications
|
||||
CREATE SCHEMA IF NOT EXISTS notify; -- Notification delivery
|
||||
|
||||
-- Signals & Observability
|
||||
CREATE SCHEMA IF NOT EXISTS signals; -- Runtime signals
|
||||
|
||||
-- Registry
|
||||
CREATE SCHEMA IF NOT EXISTS packs; -- Task packs registry
|
||||
|
||||
-- Audit
|
||||
CREATE SCHEMA IF NOT EXISTS audit; -- System-wide audit log
|
||||
|
||||
-- ============================================================================
|
||||
-- Grant usage to application user (for single-user mode)
|
||||
-- Per-module users are created in 02-create-users.sql
|
||||
-- ============================================================================
|
||||
DO $$
|
||||
DECLARE
|
||||
schema_name TEXT;
|
||||
BEGIN
|
||||
FOR schema_name IN SELECT unnest(ARRAY[
|
||||
'authority', 'vuln', 'vex', 'scanner', 'scheduler', 'taskrunner',
|
||||
'policy', 'unknowns', 'proofchain', 'attestor', 'signer',
|
||||
'notify', 'signals', 'packs', 'audit'
|
||||
]) LOOP
|
||||
EXECUTE format('GRANT USAGE ON SCHEMA %I TO PUBLIC', schema_name);
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
53
devops/compose/postgres-init/02-create-users.sql
Normal file
53
devops/compose/postgres-init/02-create-users.sql
Normal file
@@ -0,0 +1,53 @@
|
||||
-- ============================================================================
|
||||
-- Per-Module Database Users
|
||||
-- ============================================================================
|
||||
-- Creates isolated database users for each StellaOps module.
|
||||
-- This enables least-privilege access control and audit trail per module.
|
||||
--
|
||||
-- Password format: {module}_dev (for development only)
|
||||
-- In production, use secrets management and rotate credentials.
|
||||
-- ============================================================================
|
||||
|
||||
-- Core Platform
|
||||
CREATE USER authority_user WITH PASSWORD 'authority_dev';
|
||||
|
||||
-- Data Ingestion
|
||||
CREATE USER concelier_user WITH PASSWORD 'concelier_dev';
|
||||
CREATE USER excititor_user WITH PASSWORD 'excititor_dev';
|
||||
|
||||
-- Scanning & Analysis
|
||||
CREATE USER scanner_user WITH PASSWORD 'scanner_dev';
|
||||
|
||||
-- Scheduling & Orchestration
|
||||
CREATE USER scheduler_user WITH PASSWORD 'scheduler_dev';
|
||||
CREATE USER taskrunner_user WITH PASSWORD 'taskrunner_dev';
|
||||
|
||||
-- Policy & Risk
|
||||
CREATE USER policy_user WITH PASSWORD 'policy_dev';
|
||||
CREATE USER unknowns_user WITH PASSWORD 'unknowns_dev';
|
||||
|
||||
-- Artifacts & Evidence
|
||||
CREATE USER attestor_user WITH PASSWORD 'attestor_dev';
|
||||
CREATE USER signer_user WITH PASSWORD 'signer_dev';
|
||||
|
||||
-- Notifications
|
||||
CREATE USER notify_user WITH PASSWORD 'notify_dev';
|
||||
|
||||
-- Signals & Observability
|
||||
CREATE USER signals_user WITH PASSWORD 'signals_dev';
|
||||
|
||||
-- Registry
|
||||
CREATE USER packs_user WITH PASSWORD 'packs_dev';
|
||||
|
||||
-- ============================================================================
|
||||
-- Log created users
|
||||
-- ============================================================================
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'Created per-module database users:';
|
||||
RAISE NOTICE ' - authority_user, concelier_user, excititor_user';
|
||||
RAISE NOTICE ' - scanner_user, scheduler_user, taskrunner_user';
|
||||
RAISE NOTICE ' - policy_user, unknowns_user';
|
||||
RAISE NOTICE ' - attestor_user, signer_user';
|
||||
RAISE NOTICE ' - notify_user, signals_user, packs_user';
|
||||
END $$;
|
||||
153
devops/compose/postgres-init/03-grant-permissions.sql
Normal file
153
devops/compose/postgres-init/03-grant-permissions.sql
Normal file
@@ -0,0 +1,153 @@
|
||||
-- ============================================================================
|
||||
-- Per-Module Schema Permissions
|
||||
-- ============================================================================
|
||||
-- Grants each module user access to their respective schema(s).
|
||||
-- Users can only access tables in their designated schemas.
|
||||
-- ============================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- Authority Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA authority TO authority_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA authority TO authority_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA authority TO authority_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA authority GRANT ALL ON TABLES TO authority_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA authority GRANT ALL ON SEQUENCES TO authority_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Concelier Module (uses 'vuln' schema)
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA vuln TO concelier_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA vuln TO concelier_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA vuln TO concelier_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA vuln GRANT ALL ON TABLES TO concelier_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA vuln GRANT ALL ON SEQUENCES TO concelier_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Excititor Module (uses 'vex' schema)
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA vex TO excititor_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA vex TO excititor_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA vex TO excititor_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA vex GRANT ALL ON TABLES TO excititor_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA vex GRANT ALL ON SEQUENCES TO excititor_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Scanner Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA scanner TO scanner_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA scanner TO scanner_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA scanner TO scanner_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA scanner GRANT ALL ON TABLES TO scanner_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA scanner GRANT ALL ON SEQUENCES TO scanner_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Scheduler Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA scheduler TO scheduler_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA scheduler TO scheduler_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA scheduler TO scheduler_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA scheduler GRANT ALL ON TABLES TO scheduler_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA scheduler GRANT ALL ON SEQUENCES TO scheduler_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- TaskRunner Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA taskrunner TO taskrunner_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA taskrunner TO taskrunner_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA taskrunner TO taskrunner_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA taskrunner GRANT ALL ON TABLES TO taskrunner_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA taskrunner GRANT ALL ON SEQUENCES TO taskrunner_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Policy Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA policy TO policy_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA policy TO policy_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA policy TO policy_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA policy GRANT ALL ON TABLES TO policy_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA policy GRANT ALL ON SEQUENCES TO policy_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Unknowns Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA unknowns TO unknowns_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA unknowns TO unknowns_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA unknowns TO unknowns_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA unknowns GRANT ALL ON TABLES TO unknowns_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA unknowns GRANT ALL ON SEQUENCES TO unknowns_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Attestor Module (uses 'proofchain' and 'attestor' schemas)
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA proofchain TO attestor_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA proofchain TO attestor_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA proofchain TO attestor_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA proofchain GRANT ALL ON TABLES TO attestor_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA proofchain GRANT ALL ON SEQUENCES TO attestor_user;
|
||||
|
||||
GRANT USAGE ON SCHEMA attestor TO attestor_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA attestor TO attestor_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA attestor TO attestor_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA attestor GRANT ALL ON TABLES TO attestor_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA attestor GRANT ALL ON SEQUENCES TO attestor_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Signer Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA signer TO signer_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA signer TO signer_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA signer TO signer_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA signer GRANT ALL ON TABLES TO signer_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA signer GRANT ALL ON SEQUENCES TO signer_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Notify Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA notify TO notify_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA notify TO notify_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA notify TO notify_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA notify GRANT ALL ON TABLES TO notify_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA notify GRANT ALL ON SEQUENCES TO notify_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Signals Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA signals TO signals_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA signals TO signals_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA signals TO signals_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA signals GRANT ALL ON TABLES TO signals_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA signals GRANT ALL ON SEQUENCES TO signals_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Packs Registry Module
|
||||
-- ============================================================================
|
||||
GRANT USAGE ON SCHEMA packs TO packs_user;
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA packs TO packs_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA packs TO packs_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA packs GRANT ALL ON TABLES TO packs_user;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA packs GRANT ALL ON SEQUENCES TO packs_user;
|
||||
|
||||
-- ============================================================================
|
||||
-- Verification
|
||||
-- ============================================================================
|
||||
DO $$
|
||||
DECLARE
|
||||
v_user TEXT;
|
||||
v_schema TEXT;
|
||||
BEGIN
|
||||
RAISE NOTICE 'Per-module permissions granted:';
|
||||
RAISE NOTICE ' authority_user -> authority';
|
||||
RAISE NOTICE ' concelier_user -> vuln';
|
||||
RAISE NOTICE ' excititor_user -> vex';
|
||||
RAISE NOTICE ' scanner_user -> scanner';
|
||||
RAISE NOTICE ' scheduler_user -> scheduler';
|
||||
RAISE NOTICE ' taskrunner_user -> taskrunner';
|
||||
RAISE NOTICE ' policy_user -> policy';
|
||||
RAISE NOTICE ' unknowns_user -> unknowns';
|
||||
RAISE NOTICE ' attestor_user -> proofchain, attestor';
|
||||
RAISE NOTICE ' signer_user -> signer';
|
||||
RAISE NOTICE ' notify_user -> notify';
|
||||
RAISE NOTICE ' signals_user -> signals';
|
||||
RAISE NOTICE ' packs_user -> packs';
|
||||
END $$;
|
||||
93
devops/scripts/efcore/Scaffold-AllModules.ps1
Normal file
93
devops/scripts/efcore/Scaffold-AllModules.ps1
Normal file
@@ -0,0 +1,93 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Scaffolds EF Core DbContext, entities, and compiled models for all StellaOps modules.
|
||||
|
||||
.DESCRIPTION
|
||||
Iterates through all configured modules and runs Scaffold-Module.ps1 for each.
|
||||
Use this after schema changes or for initial setup.
|
||||
|
||||
.PARAMETER SkipMissing
|
||||
Skip modules whose projects don't exist yet (default: true)
|
||||
|
||||
.EXAMPLE
|
||||
.\Scaffold-AllModules.ps1
|
||||
|
||||
.EXAMPLE
|
||||
.\Scaffold-AllModules.ps1 -SkipMissing:$false
|
||||
#>
|
||||
param(
|
||||
[bool]$SkipMissing = $true
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Module definitions: Module name -> Schema name
|
||||
$modules = @(
|
||||
@{ Module = "Unknowns"; Schema = "unknowns" },
|
||||
@{ Module = "PacksRegistry"; Schema = "packs" },
|
||||
@{ Module = "Authority"; Schema = "authority" },
|
||||
@{ Module = "Scanner"; Schema = "scanner" },
|
||||
@{ Module = "Scheduler"; Schema = "scheduler" },
|
||||
@{ Module = "TaskRunner"; Schema = "taskrunner" },
|
||||
@{ Module = "Policy"; Schema = "policy" },
|
||||
@{ Module = "Notify"; Schema = "notify" },
|
||||
@{ Module = "Concelier"; Schema = "vuln" },
|
||||
@{ Module = "Excititor"; Schema = "vex" },
|
||||
@{ Module = "Signals"; Schema = "signals" },
|
||||
@{ Module = "Attestor"; Schema = "proofchain" },
|
||||
@{ Module = "Signer"; Schema = "signer" }
|
||||
)
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$RepoRoot = (Get-Item $ScriptDir).Parent.Parent.Parent.FullName
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================================================" -ForegroundColor Cyan
|
||||
Write-Host " EF Core Scaffolding for All Modules" -ForegroundColor Cyan
|
||||
Write-Host "============================================================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$successCount = 0
|
||||
$skipCount = 0
|
||||
$failCount = 0
|
||||
|
||||
foreach ($m in $modules) {
|
||||
$projectPath = Join-Path $RepoRoot "src" $m.Module "__Libraries" "StellaOps.$($m.Module).Persistence.EfCore"
|
||||
|
||||
if (-not (Test-Path "$projectPath\*.csproj")) {
|
||||
if ($SkipMissing) {
|
||||
Write-Host "SKIP: $($m.Module) - Project not found" -ForegroundColor DarkGray
|
||||
$skipCount++
|
||||
continue
|
||||
} else {
|
||||
Write-Host "FAIL: $($m.Module) - Project not found at: $projectPath" -ForegroundColor Red
|
||||
$failCount++
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host ">>> Scaffolding $($m.Module)..." -ForegroundColor Magenta
|
||||
|
||||
try {
|
||||
& "$ScriptDir\Scaffold-Module.ps1" -Module $m.Module -Schema $m.Schema
|
||||
$successCount++
|
||||
}
|
||||
catch {
|
||||
Write-Host "FAIL: $($m.Module) - $($_.Exception.Message)" -ForegroundColor Red
|
||||
$failCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================================================" -ForegroundColor Cyan
|
||||
Write-Host " Summary" -ForegroundColor Cyan
|
||||
Write-Host "============================================================================" -ForegroundColor Cyan
|
||||
Write-Host " Success: $successCount"
|
||||
Write-Host " Skipped: $skipCount"
|
||||
Write-Host " Failed: $failCount"
|
||||
Write-Host ""
|
||||
|
||||
if ($failCount -gt 0) {
|
||||
exit 1
|
||||
}
|
||||
162
devops/scripts/efcore/Scaffold-Module.ps1
Normal file
162
devops/scripts/efcore/Scaffold-Module.ps1
Normal file
@@ -0,0 +1,162 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Scaffolds EF Core DbContext, entities, and compiled models from PostgreSQL schema.
|
||||
|
||||
.DESCRIPTION
|
||||
This script performs database-first scaffolding for a StellaOps module:
|
||||
1. Cleans existing generated files (Entities, CompiledModels, DbContext)
|
||||
2. Scaffolds DbContext and entities from live PostgreSQL schema
|
||||
3. Generates compiled models for startup performance
|
||||
|
||||
.PARAMETER Module
|
||||
The module name (e.g., Unknowns, PacksRegistry, Authority)
|
||||
|
||||
.PARAMETER Schema
|
||||
The PostgreSQL schema name (defaults to lowercase module name)
|
||||
|
||||
.PARAMETER ConnectionString
|
||||
PostgreSQL connection string. If not provided, uses default dev connection.
|
||||
|
||||
.PARAMETER ProjectPath
|
||||
Optional custom project path. Defaults to src/{Module}/__Libraries/StellaOps.{Module}.Persistence.EfCore
|
||||
|
||||
.EXAMPLE
|
||||
.\Scaffold-Module.ps1 -Module Unknowns
|
||||
|
||||
.EXAMPLE
|
||||
.\Scaffold-Module.ps1 -Module Unknowns -Schema unknowns -ConnectionString "Host=localhost;Database=stellaops_platform;Username=unknowns_user;Password=unknowns_dev"
|
||||
|
||||
.EXAMPLE
|
||||
.\Scaffold-Module.ps1 -Module PacksRegistry -Schema packs
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Module,
|
||||
|
||||
[string]$Schema,
|
||||
|
||||
[string]$ConnectionString,
|
||||
|
||||
[string]$ProjectPath
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Resolve repository root
|
||||
$RepoRoot = (Get-Item $PSScriptRoot).Parent.Parent.Parent.FullName
|
||||
|
||||
# Default schema to lowercase module name
|
||||
if (-not $Schema) {
|
||||
$Schema = $Module.ToLower()
|
||||
}
|
||||
|
||||
# Default connection string
|
||||
if (-not $ConnectionString) {
|
||||
$user = "${Schema}_user"
|
||||
$password = "${Schema}_dev"
|
||||
$ConnectionString = "Host=localhost;Port=5432;Database=stellaops_platform;Username=$user;Password=$password;SearchPath=$Schema"
|
||||
}
|
||||
|
||||
# Default project path
|
||||
if (-not $ProjectPath) {
|
||||
$ProjectPath = Join-Path $RepoRoot "src" $Module "__Libraries" "StellaOps.$Module.Persistence.EfCore"
|
||||
}
|
||||
|
||||
$ContextDir = "Context"
|
||||
$EntitiesDir = "Entities"
|
||||
$CompiledModelsDir = "CompiledModels"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================================================" -ForegroundColor Cyan
|
||||
Write-Host " EF Core Scaffolding for Module: $Module" -ForegroundColor Cyan
|
||||
Write-Host "============================================================================" -ForegroundColor Cyan
|
||||
Write-Host " Schema: $Schema"
|
||||
Write-Host " Project: $ProjectPath"
|
||||
Write-Host " Connection: Host=localhost;Database=stellaops_platform;Username=${Schema}_user;..."
|
||||
Write-Host ""
|
||||
|
||||
# Verify project exists
|
||||
if (-not (Test-Path "$ProjectPath\*.csproj")) {
|
||||
Write-Error "Project not found at: $ProjectPath"
|
||||
Write-Host "Create the project first with: dotnet new classlib -n StellaOps.$Module.Persistence.EfCore"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 1: Clean existing generated files
|
||||
Write-Host "[1/4] Cleaning existing generated files..." -ForegroundColor Yellow
|
||||
$paths = @(
|
||||
(Join-Path $ProjectPath $EntitiesDir),
|
||||
(Join-Path $ProjectPath $CompiledModelsDir),
|
||||
(Join-Path $ProjectPath $ContextDir "${Module}DbContext.cs")
|
||||
)
|
||||
foreach ($path in $paths) {
|
||||
if (Test-Path $path) {
|
||||
Remove-Item -Recurse -Force $path
|
||||
Write-Host " Removed: $path" -ForegroundColor DarkGray
|
||||
}
|
||||
}
|
||||
|
||||
# Recreate directories
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $ProjectPath $EntitiesDir) | Out-Null
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $ProjectPath $CompiledModelsDir) | Out-Null
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $ProjectPath $ContextDir) | Out-Null
|
||||
|
||||
# Step 2: Scaffold DbContext and entities
|
||||
Write-Host "[2/4] Scaffolding DbContext and entities from schema '$Schema'..." -ForegroundColor Yellow
|
||||
$scaffoldArgs = @(
|
||||
"ef", "dbcontext", "scaffold",
|
||||
"`"$ConnectionString`"",
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL",
|
||||
"--project", "`"$ProjectPath`"",
|
||||
"--schema", $Schema,
|
||||
"--context", "${Module}DbContext",
|
||||
"--context-dir", $ContextDir,
|
||||
"--output-dir", $EntitiesDir,
|
||||
"--namespace", "StellaOps.$Module.Persistence.EfCore.Entities",
|
||||
"--context-namespace", "StellaOps.$Module.Persistence.EfCore.Context",
|
||||
"--data-annotations",
|
||||
"--no-onconfiguring",
|
||||
"--force"
|
||||
)
|
||||
|
||||
$process = Start-Process -FilePath "dotnet" -ArgumentList $scaffoldArgs -Wait -PassThru -NoNewWindow
|
||||
if ($process.ExitCode -ne 0) {
|
||||
Write-Error "Scaffold failed with exit code: $($process.ExitCode)"
|
||||
exit 1
|
||||
}
|
||||
Write-Host " Scaffolded entities to: $EntitiesDir" -ForegroundColor DarkGray
|
||||
|
||||
# Step 3: Generate compiled models
|
||||
Write-Host "[3/4] Generating compiled models..." -ForegroundColor Yellow
|
||||
$optimizeArgs = @(
|
||||
"ef", "dbcontext", "optimize",
|
||||
"--project", "`"$ProjectPath`"",
|
||||
"--context", "StellaOps.$Module.Persistence.EfCore.Context.${Module}DbContext",
|
||||
"--output-dir", $CompiledModelsDir,
|
||||
"--namespace", "StellaOps.$Module.Persistence.EfCore.CompiledModels"
|
||||
)
|
||||
|
||||
$process = Start-Process -FilePath "dotnet" -ArgumentList $optimizeArgs -Wait -PassThru -NoNewWindow
|
||||
if ($process.ExitCode -ne 0) {
|
||||
Write-Error "Compiled model generation failed with exit code: $($process.ExitCode)"
|
||||
exit 1
|
||||
}
|
||||
Write-Host " Generated compiled models to: $CompiledModelsDir" -ForegroundColor DarkGray
|
||||
|
||||
# Step 4: Summary
|
||||
Write-Host "[4/4] Scaffolding complete!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Generated files:" -ForegroundColor Cyan
|
||||
$contextFile = Join-Path $ProjectPath $ContextDir "${Module}DbContext.cs"
|
||||
$entityFiles = Get-ChildItem -Path (Join-Path $ProjectPath $EntitiesDir) -Filter "*.cs" -ErrorAction SilentlyContinue
|
||||
$compiledFiles = Get-ChildItem -Path (Join-Path $ProjectPath $CompiledModelsDir) -Filter "*.cs" -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host " Context: $(if (Test-Path $contextFile) { $contextFile } else { 'Not found' })"
|
||||
Write-Host " Entities: $($entityFiles.Count) files"
|
||||
Write-Host " Compiled Models: $($compiledFiles.Count) files"
|
||||
Write-Host ""
|
||||
Write-Host "Next steps:" -ForegroundColor Yellow
|
||||
Write-Host " 1. Review generated entities for any customization needs"
|
||||
Write-Host " 2. Create repository implementations in Repositories/"
|
||||
Write-Host " 3. Add DI registration in Extensions/"
|
||||
Write-Host ""
|
||||
88
devops/scripts/efcore/scaffold-all-modules.sh
Normal file
88
devops/scripts/efcore/scaffold-all-modules.sh
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# ============================================================================
|
||||
# EF Core Scaffolding for All StellaOps Modules
|
||||
# ============================================================================
|
||||
# Iterates through all configured modules and runs scaffold-module.sh for each.
|
||||
# Use this after schema changes or for initial setup.
|
||||
#
|
||||
# Usage: ./scaffold-all-modules.sh [--no-skip-missing]
|
||||
# ============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SKIP_MISSING=true
|
||||
if [ "$1" = "--no-skip-missing" ]; then
|
||||
SKIP_MISSING=false
|
||||
fi
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
|
||||
# Module definitions: "Module:Schema"
|
||||
MODULES=(
|
||||
"Unknowns:unknowns"
|
||||
"PacksRegistry:packs"
|
||||
"Authority:authority"
|
||||
"Scanner:scanner"
|
||||
"Scheduler:scheduler"
|
||||
"TaskRunner:taskrunner"
|
||||
"Policy:policy"
|
||||
"Notify:notify"
|
||||
"Concelier:vuln"
|
||||
"Excititor:vex"
|
||||
"Signals:signals"
|
||||
"Attestor:proofchain"
|
||||
"Signer:signer"
|
||||
)
|
||||
|
||||
echo ""
|
||||
echo "============================================================================"
|
||||
echo " EF Core Scaffolding for All Modules"
|
||||
echo "============================================================================"
|
||||
echo ""
|
||||
|
||||
SUCCESS_COUNT=0
|
||||
SKIP_COUNT=0
|
||||
FAIL_COUNT=0
|
||||
|
||||
for entry in "${MODULES[@]}"; do
|
||||
MODULE="${entry%%:*}"
|
||||
SCHEMA="${entry##*:}"
|
||||
|
||||
PROJECT_PATH="$REPO_ROOT/src/$MODULE/__Libraries/StellaOps.$MODULE.Persistence.EfCore"
|
||||
|
||||
if [ ! -f "$PROJECT_PATH"/*.csproj ]; then
|
||||
if [ "$SKIP_MISSING" = true ]; then
|
||||
echo "SKIP: $MODULE - Project not found"
|
||||
((SKIP_COUNT++))
|
||||
continue
|
||||
else
|
||||
echo "FAIL: $MODULE - Project not found at: $PROJECT_PATH"
|
||||
((FAIL_COUNT++))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo ">>> Scaffolding $MODULE..."
|
||||
|
||||
if "$SCRIPT_DIR/scaffold-module.sh" "$MODULE" "$SCHEMA"; then
|
||||
((SUCCESS_COUNT++))
|
||||
else
|
||||
echo "FAIL: $MODULE - Scaffolding failed"
|
||||
((FAIL_COUNT++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "============================================================================"
|
||||
echo " Summary"
|
||||
echo "============================================================================"
|
||||
echo " Success: $SUCCESS_COUNT"
|
||||
echo " Skipped: $SKIP_COUNT"
|
||||
echo " Failed: $FAIL_COUNT"
|
||||
echo ""
|
||||
|
||||
if [ "$FAIL_COUNT" -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
113
devops/scripts/efcore/scaffold-module.sh
Normal file
113
devops/scripts/efcore/scaffold-module.sh
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
# ============================================================================
|
||||
# EF Core Scaffolding Script for StellaOps Modules
|
||||
# ============================================================================
|
||||
# Usage: ./scaffold-module.sh <Module> [Schema] [ConnectionString]
|
||||
#
|
||||
# Examples:
|
||||
# ./scaffold-module.sh Unknowns
|
||||
# ./scaffold-module.sh Unknowns unknowns
|
||||
# ./scaffold-module.sh PacksRegistry packs "Host=localhost;..."
|
||||
# ============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
MODULE=$1
|
||||
SCHEMA=${2:-$(echo "$MODULE" | tr '[:upper:]' '[:lower:]')}
|
||||
CONNECTION_STRING=$3
|
||||
|
||||
if [ -z "$MODULE" ]; then
|
||||
echo "Usage: $0 <Module> [Schema] [ConnectionString]"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 Unknowns"
|
||||
echo " $0 Unknowns unknowns"
|
||||
echo " $0 PacksRegistry packs \"Host=localhost;Database=stellaops_platform;Username=packs_user;Password=packs_dev\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Resolve repository root
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
|
||||
# Default connection string
|
||||
if [ -z "$CONNECTION_STRING" ]; then
|
||||
USER="${SCHEMA}_user"
|
||||
PASSWORD="${SCHEMA}_dev"
|
||||
CONNECTION_STRING="Host=localhost;Port=5432;Database=stellaops_platform;Username=$USER;Password=$PASSWORD;SearchPath=$SCHEMA"
|
||||
fi
|
||||
|
||||
PROJECT_DIR="$REPO_ROOT/src/$MODULE/__Libraries/StellaOps.$MODULE.Persistence.EfCore"
|
||||
CONTEXT_DIR="Context"
|
||||
ENTITIES_DIR="Entities"
|
||||
COMPILED_DIR="CompiledModels"
|
||||
|
||||
echo ""
|
||||
echo "============================================================================"
|
||||
echo " EF Core Scaffolding for Module: $MODULE"
|
||||
echo "============================================================================"
|
||||
echo " Schema: $SCHEMA"
|
||||
echo " Project: $PROJECT_DIR"
|
||||
echo " Connection: Host=localhost;Database=stellaops_platform;Username=${SCHEMA}_user;..."
|
||||
echo ""
|
||||
|
||||
# Verify project exists
|
||||
if [ ! -f "$PROJECT_DIR"/*.csproj ]; then
|
||||
echo "ERROR: Project not found at: $PROJECT_DIR"
|
||||
echo "Create the project first with: dotnet new classlib -n StellaOps.$MODULE.Persistence.EfCore"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 1: Clean existing generated files
|
||||
echo "[1/4] Cleaning existing generated files..."
|
||||
rm -rf "$PROJECT_DIR/$ENTITIES_DIR"
|
||||
rm -rf "$PROJECT_DIR/$COMPILED_DIR"
|
||||
rm -f "$PROJECT_DIR/$CONTEXT_DIR/${MODULE}DbContext.cs"
|
||||
|
||||
mkdir -p "$PROJECT_DIR/$ENTITIES_DIR"
|
||||
mkdir -p "$PROJECT_DIR/$COMPILED_DIR"
|
||||
mkdir -p "$PROJECT_DIR/$CONTEXT_DIR"
|
||||
|
||||
echo " Cleaned: $ENTITIES_DIR, $COMPILED_DIR, ${MODULE}DbContext.cs"
|
||||
|
||||
# Step 2: Scaffold DbContext and entities
|
||||
echo "[2/4] Scaffolding DbContext and entities from schema '$SCHEMA'..."
|
||||
dotnet ef dbcontext scaffold \
|
||||
"$CONNECTION_STRING" \
|
||||
Npgsql.EntityFrameworkCore.PostgreSQL \
|
||||
--project "$PROJECT_DIR" \
|
||||
--schema "$SCHEMA" \
|
||||
--context "${MODULE}DbContext" \
|
||||
--context-dir "$CONTEXT_DIR" \
|
||||
--output-dir "$ENTITIES_DIR" \
|
||||
--namespace "StellaOps.$MODULE.Persistence.EfCore.Entities" \
|
||||
--context-namespace "StellaOps.$MODULE.Persistence.EfCore.Context" \
|
||||
--data-annotations \
|
||||
--no-onconfiguring \
|
||||
--force
|
||||
|
||||
echo " Scaffolded entities to: $ENTITIES_DIR"
|
||||
|
||||
# Step 3: Generate compiled models
|
||||
echo "[3/4] Generating compiled models..."
|
||||
dotnet ef dbcontext optimize \
|
||||
--project "$PROJECT_DIR" \
|
||||
--context "StellaOps.$MODULE.Persistence.EfCore.Context.${MODULE}DbContext" \
|
||||
--output-dir "$COMPILED_DIR" \
|
||||
--namespace "StellaOps.$MODULE.Persistence.EfCore.CompiledModels"
|
||||
|
||||
echo " Generated compiled models to: $COMPILED_DIR"
|
||||
|
||||
# Step 4: Summary
|
||||
echo "[4/4] Scaffolding complete!"
|
||||
echo ""
|
||||
echo "Generated files:"
|
||||
echo " Context: $PROJECT_DIR/$CONTEXT_DIR/${MODULE}DbContext.cs"
|
||||
echo " Entities: $(ls -1 "$PROJECT_DIR/$ENTITIES_DIR"/*.cs 2>/dev/null | wc -l) files"
|
||||
echo " Compiled Models: $(ls -1 "$PROJECT_DIR/$COMPILED_DIR"/*.cs 2>/dev/null | wc -l) files"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Review generated entities for any customization needs"
|
||||
echo " 2. Create repository implementations in Repositories/"
|
||||
echo " 3. Add DI registration in Extensions/"
|
||||
echo ""
|
||||
100
devops/scripts/fix-duplicate-packages.ps1
Normal file
100
devops/scripts/fix-duplicate-packages.ps1
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# fix-duplicate-packages.ps1 - Remove duplicate PackageReference items from test projects
|
||||
# These are already provided by Directory.Build.props
|
||||
|
||||
param([switch]$DryRun)
|
||||
|
||||
$packagesToRemove = @(
|
||||
"coverlet.collector",
|
||||
"Microsoft.NET.Test.Sdk",
|
||||
"Microsoft.AspNetCore.Mvc.Testing",
|
||||
"xunit",
|
||||
"xunit.runner.visualstudio",
|
||||
"Microsoft.Extensions.TimeProvider.Testing"
|
||||
)
|
||||
|
||||
$sharpCompressPackage = "SharpCompress"
|
||||
|
||||
# Find all test project files
|
||||
$testProjects = Get-ChildItem -Path "src" -Filter "*.Tests.csproj" -Recurse
|
||||
$corpusProjects = Get-ChildItem -Path "src" -Filter "*.Corpus.*.csproj" -Recurse
|
||||
|
||||
Write-Host "=== Fix Duplicate Package References ===" -ForegroundColor Cyan
|
||||
Write-Host "Found $($testProjects.Count) test projects" -ForegroundColor Yellow
|
||||
Write-Host "Found $($corpusProjects.Count) corpus projects (SharpCompress)" -ForegroundColor Yellow
|
||||
|
||||
$fixedCount = 0
|
||||
|
||||
foreach ($proj in $testProjects) {
|
||||
$content = Get-Content $proj.FullName -Raw
|
||||
$modified = $false
|
||||
|
||||
# Skip projects that opt out of common test infrastructure
|
||||
if ($content -match "<UseConcelierTestInfra>\s*false\s*</UseConcelierTestInfra>") {
|
||||
Write-Host " Skipped (UseConcelierTestInfra=false): $($proj.Name)" -ForegroundColor DarkGray
|
||||
continue
|
||||
}
|
||||
|
||||
foreach ($pkg in $packagesToRemove) {
|
||||
# Match PackageReference for this package (various formats)
|
||||
$patterns = @(
|
||||
"(?s)\s*<PackageReference\s+Include=`"$pkg`"\s+Version=`"[^`"]+`"\s*/>\r?\n?",
|
||||
"(?s)\s*<PackageReference\s+Include=`"$pkg`"\s+Version=`"[^`"]+`"\s*>\s*</PackageReference>\r?\n?"
|
||||
)
|
||||
|
||||
foreach ($pattern in $patterns) {
|
||||
if ($content -match $pattern) {
|
||||
$content = $content -replace $pattern, ""
|
||||
$modified = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Clean up empty ItemGroups
|
||||
$content = $content -replace "(?s)\s*<ItemGroup>\s*</ItemGroup>", ""
|
||||
# Clean up ItemGroups with only whitespace/comments
|
||||
$content = $content -replace "(?s)<ItemGroup>\s*<!--[^-]*-->\s*</ItemGroup>", ""
|
||||
|
||||
if ($modified) {
|
||||
$fixedCount++
|
||||
Write-Host " Fixed: $($proj.Name)" -ForegroundColor Green
|
||||
if (-not $DryRun) {
|
||||
$content | Set-Content $proj.FullName -NoNewline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Fix SharpCompress in corpus projects
|
||||
foreach ($proj in $corpusProjects) {
|
||||
$content = Get-Content $proj.FullName -Raw
|
||||
$modified = $false
|
||||
|
||||
$patterns = @(
|
||||
"(?s)\s*<PackageReference\s+Include=`"$sharpCompressPackage`"\s+Version=`"[^`"]+`"\s*/>\r?\n?",
|
||||
"(?s)\s*<PackageReference\s+Include=`"$sharpCompressPackage`"\s+Version=`"[^`"]+`"\s*>\s*</PackageReference>\r?\n?"
|
||||
)
|
||||
|
||||
foreach ($pattern in $patterns) {
|
||||
if ($content -match $pattern) {
|
||||
$content = $content -replace $pattern, ""
|
||||
$modified = $true
|
||||
}
|
||||
}
|
||||
|
||||
# Clean up empty ItemGroups
|
||||
$content = $content -replace "(?s)\s*<ItemGroup>\s*</ItemGroup>", ""
|
||||
|
||||
if ($modified) {
|
||||
$fixedCount++
|
||||
Write-Host " Fixed: $($proj.Name)" -ForegroundColor Green
|
||||
if (-not $DryRun) {
|
||||
$content | Set-Content $proj.FullName -NoNewline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Fixed $fixedCount projects" -ForegroundColor Cyan
|
||||
if ($DryRun) {
|
||||
Write-Host "(Dry run - no changes made)" -ForegroundColor Yellow
|
||||
}
|
||||
55
devops/scripts/fix-duplicate-using-testkit.ps1
Normal file
55
devops/scripts/fix-duplicate-using-testkit.ps1
Normal file
@@ -0,0 +1,55 @@
|
||||
# Fix duplicate "using StellaOps.TestKit;" statements in C# files
|
||||
# The pattern shows files have this statement both at top (correct) and in middle (wrong)
|
||||
# This script removes all occurrences AFTER the first one
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$srcPath = Join-Path $PSScriptRoot "..\..\src"
|
||||
$pattern = "using StellaOps.TestKit;"
|
||||
|
||||
# Find all .cs files containing the pattern
|
||||
$files = Get-ChildItem -Path $srcPath -Recurse -Filter "*.cs" |
|
||||
Where-Object { (Get-Content $_.FullName -Raw) -match [regex]::Escape($pattern) }
|
||||
|
||||
Write-Host "Found $($files.Count) files with 'using StellaOps.TestKit;'" -ForegroundColor Cyan
|
||||
|
||||
$fixedCount = 0
|
||||
$errorCount = 0
|
||||
|
||||
foreach ($file in $files) {
|
||||
try {
|
||||
$lines = Get-Content $file.FullName
|
||||
$newLines = @()
|
||||
$foundFirst = $false
|
||||
$removedAny = $false
|
||||
|
||||
foreach ($line in $lines) {
|
||||
if ($line.Trim() -eq $pattern) {
|
||||
if (-not $foundFirst) {
|
||||
# Keep the first occurrence
|
||||
$newLines += $line
|
||||
$foundFirst = $true
|
||||
} else {
|
||||
# Skip subsequent occurrences
|
||||
$removedAny = $true
|
||||
}
|
||||
} else {
|
||||
$newLines += $line
|
||||
}
|
||||
}
|
||||
|
||||
if ($removedAny) {
|
||||
$newLines | Set-Content -Path $file.FullName -Encoding UTF8
|
||||
Write-Host "Fixed: $($file.Name)" -ForegroundColor Green
|
||||
$fixedCount++
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Error processing $($file.FullName): $_" -ForegroundColor Red
|
||||
$errorCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Summary:" -ForegroundColor Cyan
|
||||
Write-Host " Files fixed: $fixedCount" -ForegroundColor Green
|
||||
Write-Host " Errors: $errorCount" -ForegroundColor $(if ($errorCount -gt 0) { "Red" } else { "Green" })
|
||||
51
devops/scripts/fix-missing-xunit.ps1
Normal file
51
devops/scripts/fix-missing-xunit.ps1
Normal file
@@ -0,0 +1,51 @@
|
||||
# Fix projects with UseConcelierTestInfra=false that don't have xunit
|
||||
# These projects relied on TestKit for xunit, but now need their own reference
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$srcPath = "E:\dev\git.stella-ops.org\src"
|
||||
|
||||
# Find test projects with UseConcelierTestInfra=false
|
||||
$projects = Get-ChildItem -Path $srcPath -Recurse -Filter "*.csproj" |
|
||||
Where-Object {
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
($content -match "<UseConcelierTestInfra>\s*false\s*</UseConcelierTestInfra>") -and
|
||||
(-not ($content -match "xunit\.v3")) -and # Skip xunit.v3 projects
|
||||
(-not ($content -match '<PackageReference\s+Include="xunit"')) # Skip projects that already have xunit
|
||||
}
|
||||
|
||||
Write-Host "Found $($projects.Count) projects needing xunit" -ForegroundColor Cyan
|
||||
|
||||
$xunitPackages = @'
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
'@
|
||||
|
||||
$fixedCount = 0
|
||||
|
||||
foreach ($proj in $projects) {
|
||||
$content = Get-Content $proj.FullName -Raw
|
||||
|
||||
# Check if it has an ItemGroup with PackageReference
|
||||
if ($content -match '(<ItemGroup>[\s\S]*?<PackageReference)') {
|
||||
# Add xunit packages after first PackageReference ItemGroup opening
|
||||
$newContent = $content -replace '(<ItemGroup>\s*\r?\n)(\s*<PackageReference)', "`$1$xunitPackages`n`$2"
|
||||
} else {
|
||||
# No PackageReference ItemGroup, add one before </Project>
|
||||
$itemGroup = @"
|
||||
|
||||
<ItemGroup>
|
||||
$xunitPackages
|
||||
</ItemGroup>
|
||||
"@
|
||||
$newContent = $content -replace '</Project>', "$itemGroup`n</Project>"
|
||||
}
|
||||
|
||||
if ($newContent -ne $content) {
|
||||
Set-Content -Path $proj.FullName -Value $newContent -NoNewline
|
||||
Write-Host "Fixed: $($proj.Name)" -ForegroundColor Green
|
||||
$fixedCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "`nFixed $fixedCount projects" -ForegroundColor Cyan
|
||||
44
devops/scripts/fix-project-references.ps1
Normal file
44
devops/scripts/fix-project-references.ps1
Normal file
@@ -0,0 +1,44 @@
|
||||
# Fix project references in src/__Tests/** that point to wrong relative paths
|
||||
# Pattern: ../../<Module>/... should be ../../../<Module>/...
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$testsPath = "E:\dev\git.stella-ops.org\src\__Tests"
|
||||
|
||||
# Known module prefixes that exist at src/<Module>/
|
||||
$modules = @("Signals", "Scanner", "Concelier", "Scheduler", "Authority", "Attestor",
|
||||
"BinaryIndex", "EvidenceLocker", "Excititor", "ExportCenter", "Gateway",
|
||||
"Graph", "IssuerDirectory", "Notify", "Orchestrator", "Policy", "AirGap",
|
||||
"Provenance", "Replay", "RiskEngine", "SbomService", "Signer", "TaskRunner",
|
||||
"Telemetry", "TimelineIndexer", "Unknowns", "VexHub", "VexLens", "VulnExplorer",
|
||||
"Zastava", "Cli", "Aoc", "Web", "Bench", "Cryptography", "PacksRegistry",
|
||||
"Notifier", "Findings")
|
||||
|
||||
$fixedCount = 0
|
||||
|
||||
Get-ChildItem -Path $testsPath -Recurse -Filter "*.csproj" | ForEach-Object {
|
||||
$proj = $_
|
||||
$content = Get-Content $proj.FullName -Raw
|
||||
$originalContent = $content
|
||||
|
||||
foreach ($module in $modules) {
|
||||
# Fix ../../<Module>/ to ../../../<Module>/
|
||||
# But not ../../../<Module> (already correct)
|
||||
$pattern = "Include=`"../../$module/"
|
||||
$replacement = "Include=`"../../../$module/"
|
||||
|
||||
if ($content -match [regex]::Escape($pattern) -and $content -notmatch [regex]::Escape("Include=`"../../../$module/")) {
|
||||
$content = $content -replace [regex]::Escape($pattern), $replacement
|
||||
}
|
||||
}
|
||||
|
||||
# Fix __Libraries references that are one level short
|
||||
$content = $content -replace 'Include="../../__Libraries/', 'Include="../../../__Libraries/'
|
||||
|
||||
if ($content -ne $originalContent) {
|
||||
Set-Content -Path $proj.FullName -Value $content -NoNewline
|
||||
Write-Host "Fixed: $($proj.Name)" -ForegroundColor Green
|
||||
$fixedCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "`nFixed $fixedCount projects" -ForegroundColor Cyan
|
||||
68
devops/scripts/fix-sln-duplicates.ps1
Normal file
68
devops/scripts/fix-sln-duplicates.ps1
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# fix-sln-duplicates.ps1 - Remove duplicate project entries from solution file
|
||||
|
||||
param(
|
||||
[string]$SlnPath = "src/StellaOps.sln"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
Write-Host "=== Solution Duplicate Cleanup ===" -ForegroundColor Cyan
|
||||
Write-Host "Solution: $SlnPath"
|
||||
|
||||
$content = Get-Content $SlnPath -Raw
|
||||
$lines = $content -split "`r?`n"
|
||||
|
||||
# Track seen project names
|
||||
$seenProjects = @{}
|
||||
$duplicateGuids = @()
|
||||
$newLines = @()
|
||||
$skipNext = $false
|
||||
|
||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||
$line = $lines[$i]
|
||||
|
||||
if ($skipNext) {
|
||||
$skipNext = $false
|
||||
continue
|
||||
}
|
||||
|
||||
# Check for project declaration
|
||||
if ($line -match 'Project\(.+\) = "([^"]+)",.*\{([A-F0-9-]+)\}"?$') {
|
||||
$name = $Matches[1]
|
||||
$guid = $Matches[2]
|
||||
|
||||
if ($seenProjects.ContainsKey($name)) {
|
||||
Write-Host "Removing duplicate: $name ($guid)" -ForegroundColor Yellow
|
||||
$duplicateGuids += $guid
|
||||
# Skip this line and the next EndProject line
|
||||
$skipNext = $true
|
||||
continue
|
||||
} else {
|
||||
$seenProjects[$name] = $true
|
||||
}
|
||||
}
|
||||
|
||||
$newLines += $line
|
||||
}
|
||||
|
||||
# Remove GlobalSection references to duplicate GUIDs
|
||||
$finalLines = @()
|
||||
foreach ($line in $newLines) {
|
||||
$skip = $false
|
||||
foreach ($guid in $duplicateGuids) {
|
||||
if ($line -match $guid) {
|
||||
$skip = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (-not $skip) {
|
||||
$finalLines += $line
|
||||
}
|
||||
}
|
||||
|
||||
# Write back
|
||||
$finalLines -join "`r`n" | Set-Content $SlnPath -Encoding UTF8 -NoNewline
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Removed $($duplicateGuids.Count) duplicate projects" -ForegroundColor Green
|
||||
40
devops/scripts/fix-xunit-using.ps1
Normal file
40
devops/scripts/fix-xunit-using.ps1
Normal file
@@ -0,0 +1,40 @@
|
||||
# Add <Using Include="Xunit" /> to test projects with UseConcelierTestInfra=false
|
||||
# that have xunit but don't have the global using
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$srcPath = "E:\dev\git.stella-ops.org\src"
|
||||
|
||||
# Find test projects with UseConcelierTestInfra=false that have xunit but no Using Include="Xunit"
|
||||
$projects = Get-ChildItem -Path $srcPath -Recurse -Filter "*.csproj" |
|
||||
Where-Object {
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
($content -match "<UseConcelierTestInfra>\s*false\s*</UseConcelierTestInfra>") -and
|
||||
($content -match '<PackageReference\s+Include="xunit"') -and
|
||||
(-not ($content -match '<Using\s+Include="Xunit"'))
|
||||
}
|
||||
|
||||
Write-Host "Found $($projects.Count) projects needing Xunit using" -ForegroundColor Cyan
|
||||
|
||||
$fixedCount = 0
|
||||
|
||||
foreach ($proj in $projects) {
|
||||
$content = Get-Content $proj.FullName -Raw
|
||||
|
||||
# Add Using Include="Xunit" before first ProjectReference ItemGroup or at end
|
||||
if ($content -match '(<ItemGroup>\s*\r?\n\s*<ProjectReference)') {
|
||||
$usingBlock = " <ItemGroup>`n <Using Include=`"Xunit`" />`n </ItemGroup>`n`n"
|
||||
$newContent = $content -replace '(\s*)(<ItemGroup>\s*\r?\n\s*<ProjectReference)', "$usingBlock`$1`$2"
|
||||
} else {
|
||||
# Add before </Project>
|
||||
$usingBlock = "`n <ItemGroup>`n <Using Include=`"Xunit`" />`n </ItemGroup>`n"
|
||||
$newContent = $content -replace '</Project>', "$usingBlock</Project>"
|
||||
}
|
||||
|
||||
if ($newContent -ne $content) {
|
||||
Set-Content -Path $proj.FullName -Value $newContent -NoNewline
|
||||
Write-Host "Fixed: $($proj.Name)" -ForegroundColor Green
|
||||
$fixedCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "`nFixed $fixedCount projects" -ForegroundColor Cyan
|
||||
37
devops/scripts/fix-xunit-v3-conflict.ps1
Normal file
37
devops/scripts/fix-xunit-v3-conflict.ps1
Normal file
@@ -0,0 +1,37 @@
|
||||
# Fix xunit.v3 projects that conflict with Directory.Build.props xunit 2.x
|
||||
# Add UseConcelierTestInfra=false to exclude them from common test infrastructure
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$srcPath = Join-Path $PSScriptRoot "..\..\src"
|
||||
|
||||
# Find all csproj files that reference xunit.v3
|
||||
$xunitV3Projects = Get-ChildItem -Path $srcPath -Recurse -Filter "*.csproj" |
|
||||
Where-Object { (Get-Content $_.FullName -Raw) -match "xunit\.v3" }
|
||||
|
||||
Write-Host "Found $($xunitV3Projects.Count) projects with xunit.v3" -ForegroundColor Cyan
|
||||
|
||||
$fixedCount = 0
|
||||
|
||||
foreach ($proj in $xunitV3Projects) {
|
||||
$content = Get-Content $proj.FullName -Raw
|
||||
|
||||
# Check if already has UseConcelierTestInfra set
|
||||
if ($content -match "<UseConcelierTestInfra>") {
|
||||
Write-Host " Skipped (already configured): $($proj.Name)" -ForegroundColor DarkGray
|
||||
continue
|
||||
}
|
||||
|
||||
# Add UseConcelierTestInfra=false after the first <PropertyGroup>
|
||||
$newContent = $content -replace "(<PropertyGroup>)", "`$1`n <UseConcelierTestInfra>false</UseConcelierTestInfra>"
|
||||
|
||||
# Only write if changed
|
||||
if ($newContent -ne $content) {
|
||||
Set-Content -Path $proj.FullName -Value $newContent -NoNewline
|
||||
Write-Host " Fixed: $($proj.Name)" -ForegroundColor Green
|
||||
$fixedCount++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Fixed $fixedCount projects" -ForegroundColor Cyan
|
||||
244
devops/scripts/migrations-reset-pre-1.0.sql
Normal file
244
devops/scripts/migrations-reset-pre-1.0.sql
Normal file
@@ -0,0 +1,244 @@
|
||||
-- ============================================================================
|
||||
-- StellaOps Migration Reset Script for Pre-1.0 Deployments
|
||||
-- ============================================================================
|
||||
-- This script updates schema_migrations tables to recognize the 1.0.0 compacted
|
||||
-- migrations for deployments that upgraded from pre-1.0 versions.
|
||||
--
|
||||
-- Run via: psql -f migrations-reset-pre-1.0.sql
|
||||
-- Or with connection: psql -h <host> -U <user> -d <db> -f migrations-reset-pre-1.0.sql
|
||||
-- ============================================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- Authority Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 001_initial_schema, 002_mongo_store_equivalents, 003_enable_rls,
|
||||
-- 004_offline_kit_audit, 005_verdict_manifests
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM authority.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'001_initial_schema.sql',
|
||||
'002_mongo_store_equivalents.sql',
|
||||
'003_enable_rls.sql',
|
||||
'004_offline_kit_audit.sql',
|
||||
'005_verdict_manifests.sql'
|
||||
);
|
||||
|
||||
INSERT INTO authority.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Scheduler Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 001_initial_schema, 002_graph_jobs, 003_runs_policy,
|
||||
-- 010_generated_columns_runs, 011_enable_rls, 012_partition_audit,
|
||||
-- 012b_migrate_audit_data
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM scheduler.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'001_initial_schema.sql',
|
||||
'002_graph_jobs.sql',
|
||||
'003_runs_policy.sql',
|
||||
'010_generated_columns_runs.sql',
|
||||
'011_enable_rls.sql',
|
||||
'012_partition_audit.sql',
|
||||
'012b_migrate_audit_data.sql'
|
||||
);
|
||||
|
||||
INSERT INTO scheduler.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Scanner Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 001-034 plus various numbered files (27 total)
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM scanner.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'001_create_tables.sql',
|
||||
'002_proof_spine_tables.sql',
|
||||
'003_classification_history.sql',
|
||||
'004_scan_metrics.sql',
|
||||
'005_smart_diff_tables.sql',
|
||||
'006_score_replay_tables.sql',
|
||||
'007_unknowns_ranking_containment.sql',
|
||||
'008_epss_integration.sql',
|
||||
'0059_scans_table.sql',
|
||||
'0065_unknowns_table.sql',
|
||||
'0075_scan_findings_table.sql',
|
||||
'020_call_graph_tables.sql',
|
||||
'021_smart_diff_tables_search_path.sql',
|
||||
'022_reachability_drift_tables.sql',
|
||||
'023_scanner_api_ingestion.sql',
|
||||
'024_smart_diff_priority_score_widen.sql',
|
||||
'025_epss_raw_layer.sql',
|
||||
'026_epss_signal_layer.sql',
|
||||
'027_witness_storage.sql',
|
||||
'028_epss_triage_columns.sql',
|
||||
'029_vuln_surfaces.sql',
|
||||
'030_vuln_surface_triggers_update.sql',
|
||||
'031_reach_cache.sql',
|
||||
'032_idempotency_keys.sql',
|
||||
'033_binary_evidence.sql',
|
||||
'034_func_proof_tables.sql',
|
||||
'DM001_rename_scanner_migrations.sql'
|
||||
);
|
||||
|
||||
INSERT INTO scanner.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Policy Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 001-013 (14 files, includes duplicate 010 prefix)
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM policy.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'001_initial_schema.sql',
|
||||
'002_cvss_receipts.sql',
|
||||
'003_snapshots_violations.sql',
|
||||
'004_epss_risk_scores.sql',
|
||||
'005_cvss_multiversion.sql',
|
||||
'006_enable_rls.sql',
|
||||
'007_unknowns_registry.sql',
|
||||
'008_exception_objects.sql',
|
||||
'009_exception_applications.sql',
|
||||
'010_recheck_evidence.sql',
|
||||
'010_unknowns_blast_radius_containment.sql',
|
||||
'011_unknowns_reason_codes.sql',
|
||||
'012_budget_ledger.sql',
|
||||
'013_exception_approval.sql'
|
||||
);
|
||||
|
||||
INSERT INTO policy.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Notify Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 001_initial_schema, 010_enable_rls, 011_partition_deliveries,
|
||||
-- 011b_migrate_deliveries_data
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM notify.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'001_initial_schema.sql',
|
||||
'010_enable_rls.sql',
|
||||
'011_partition_deliveries.sql',
|
||||
'011b_migrate_deliveries_data.sql'
|
||||
);
|
||||
|
||||
INSERT INTO notify.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Concelier Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 17 migration files
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM concelier.schema_migrations
|
||||
WHERE migration_name ~ '^[0-9]{3}_.*\.sql$';
|
||||
|
||||
INSERT INTO concelier.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Attestor Module Reset (proofchain + attestor schemas)
|
||||
-- ============================================================================
|
||||
-- Original: 20251214000001_AddProofChainSchema.sql, 20251216_001_create_rekor_submission_queue.sql
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM proofchain.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'20251214000001_AddProofChainSchema.sql',
|
||||
'20251214000002_RollbackProofChainSchema.sql',
|
||||
'20251216_001_create_rekor_submission_queue.sql'
|
||||
);
|
||||
|
||||
INSERT INTO proofchain.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Signer Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: 20251214000001_AddKeyManagementSchema.sql
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM signer.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'20251214000001_AddKeyManagementSchema.sql'
|
||||
);
|
||||
|
||||
INSERT INTO signer.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Signals Module Reset
|
||||
-- ============================================================================
|
||||
-- Original: V0000_001__extensions.sql, V1102_001__unknowns_scoring_schema.sql,
|
||||
-- V1105_001__deploy_refs_graph_metrics.sql, V3102_001__callgraph_relational_tables.sql
|
||||
-- New: 001_initial_schema (compacted)
|
||||
|
||||
DELETE FROM signals.schema_migrations
|
||||
WHERE migration_name IN (
|
||||
'V0000_001__extensions.sql',
|
||||
'V1102_001__unknowns_scoring_schema.sql',
|
||||
'V1105_001__deploy_refs_graph_metrics.sql',
|
||||
'V3102_001__callgraph_relational_tables.sql'
|
||||
);
|
||||
|
||||
INSERT INTO signals.schema_migrations (migration_name, category, checksum, applied_at)
|
||||
VALUES ('001_initial_schema.sql', 'startup', 'compacted_1.0.0', NOW())
|
||||
ON CONFLICT (migration_name) DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- Verification
|
||||
-- ============================================================================
|
||||
-- Display current migration status per module
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
v_module TEXT;
|
||||
v_count INT;
|
||||
BEGIN
|
||||
FOR v_module IN SELECT unnest(ARRAY['authority', 'scheduler', 'scanner', 'policy', 'notify', 'concelier', 'proofchain', 'signer', 'signals']) LOOP
|
||||
EXECUTE format('SELECT COUNT(*) FROM %I.schema_migrations', v_module) INTO v_count;
|
||||
RAISE NOTICE '% module: % migrations registered', v_module, v_count;
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- ============================================================================
|
||||
-- Post-Reset Notes
|
||||
-- ============================================================================
|
||||
-- After running this script:
|
||||
-- 1. All modules should show exactly 1 migration registered
|
||||
-- 2. The schema structure should be identical to a fresh 1.0.0 deployment
|
||||
-- 3. Future migrations (002+) will apply normally
|
||||
--
|
||||
-- To verify manually:
|
||||
-- SELECT * FROM authority.schema_migrations;
|
||||
-- SELECT * FROM scheduler.schema_migrations;
|
||||
-- SELECT * FROM scanner.schema_migrations;
|
||||
-- SELECT * FROM policy.schema_migrations;
|
||||
-- SELECT * FROM notify.schema_migrations;
|
||||
-- SELECT * FROM concelier.schema_migrations;
|
||||
-- SELECT * FROM proofchain.schema_migrations;
|
||||
-- SELECT * FROM signer.schema_migrations;
|
||||
-- SELECT * FROM signals.schema_migrations;
|
||||
-- ============================================================================
|
||||
169
devops/scripts/regenerate-solution.ps1
Normal file
169
devops/scripts/regenerate-solution.ps1
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# regenerate-solution.ps1 - Regenerate StellaOps.sln without duplicate projects
|
||||
#
|
||||
# This script:
|
||||
# 1. Backs up the existing solution
|
||||
# 2. Creates a new solution
|
||||
# 3. Adds all .csproj files, skipping duplicates
|
||||
# 4. Preserves solution folders where possible
|
||||
|
||||
param(
|
||||
[string]$SolutionPath = "src/StellaOps.sln",
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Canonical locations for test projects (in priority order)
|
||||
# Later entries win when there are duplicates
|
||||
$canonicalPatterns = @(
|
||||
# Module-local tests (highest priority)
|
||||
"src/*/__Tests/*/*.csproj",
|
||||
"src/*/__Libraries/__Tests/*/*.csproj",
|
||||
"src/__Libraries/__Tests/*/*.csproj",
|
||||
# Cross-module integration tests
|
||||
"src/__Tests/Integration/*/*.csproj",
|
||||
"src/__Tests/__Libraries/*/*.csproj",
|
||||
# Category-based cross-module tests
|
||||
"src/__Tests/chaos/*/*.csproj",
|
||||
"src/__Tests/security/*/*.csproj",
|
||||
"src/__Tests/interop/*/*.csproj",
|
||||
"src/__Tests/parity/*/*.csproj",
|
||||
"src/__Tests/reachability/*/*.csproj",
|
||||
# Single global tests
|
||||
"src/__Tests/*/*.csproj"
|
||||
)
|
||||
|
||||
Write-Host "=== Solution Regeneration Script ===" -ForegroundColor Cyan
|
||||
Write-Host "Solution: $SolutionPath"
|
||||
Write-Host "Dry Run: $DryRun"
|
||||
Write-Host ""
|
||||
|
||||
# Find all .csproj files
|
||||
Write-Host "Finding all project files..." -ForegroundColor Yellow
|
||||
$allProjects = Get-ChildItem -Path "src" -Filter "*.csproj" -Recurse |
|
||||
Where-Object { $_.FullName -notmatch "\\obj\\" -and $_.FullName -notmatch "\\bin\\" }
|
||||
|
||||
Write-Host "Found $($allProjects.Count) project files"
|
||||
|
||||
# Build a map of project name -> list of paths
|
||||
$projectMap = @{}
|
||||
foreach ($proj in $allProjects) {
|
||||
$name = $proj.BaseName
|
||||
if (-not $projectMap.ContainsKey($name)) {
|
||||
$projectMap[$name] = @()
|
||||
}
|
||||
$projectMap[$name] += $proj.FullName
|
||||
}
|
||||
|
||||
# Find duplicates
|
||||
$duplicates = $projectMap.GetEnumerator() | Where-Object { $_.Value.Count -gt 1 }
|
||||
Write-Host ""
|
||||
Write-Host "Found $($duplicates.Count) projects with duplicate names:" -ForegroundColor Yellow
|
||||
foreach ($dup in $duplicates) {
|
||||
Write-Host " $($dup.Key):" -ForegroundColor Red
|
||||
foreach ($path in $dup.Value) {
|
||||
Write-Host " - $path"
|
||||
}
|
||||
}
|
||||
|
||||
# Select canonical path for each project
|
||||
function Get-CanonicalPath {
|
||||
param([string[]]$Paths)
|
||||
|
||||
# Prefer module-local __Tests over global __Tests
|
||||
$moduleTests = $Paths | Where-Object { $_ -match "src\\[^_][^\\]+\\__Tests\\" }
|
||||
if ($moduleTests.Count -gt 0) { return $moduleTests[0] }
|
||||
|
||||
# Prefer __Libraries/__Tests
|
||||
$libTests = $Paths | Where-Object { $_ -match "__Libraries\\__Tests\\" }
|
||||
if ($libTests.Count -gt 0) { return $libTests[0] }
|
||||
|
||||
# Prefer __Tests over non-__Tests location in same parent
|
||||
$testsPath = $Paths | Where-Object { $_ -match "\\__Tests\\" }
|
||||
if ($testsPath.Count -gt 0) { return $testsPath[0] }
|
||||
|
||||
# Otherwise, take first
|
||||
return $Paths[0]
|
||||
}
|
||||
|
||||
# Build final project list
|
||||
$finalProjects = @()
|
||||
foreach ($entry in $projectMap.GetEnumerator()) {
|
||||
$canonical = Get-CanonicalPath -Paths $entry.Value
|
||||
$finalProjects += $canonical
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Final project count: $($finalProjects.Count)" -ForegroundColor Green
|
||||
|
||||
if ($DryRun) {
|
||||
Write-Host ""
|
||||
Write-Host "=== DRY RUN - No changes made ===" -ForegroundColor Magenta
|
||||
Write-Host "Would add the following projects to solution:"
|
||||
$finalProjects | ForEach-Object { Write-Host " $_" }
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Backup existing solution
|
||||
$backupPath = "$SolutionPath.bak"
|
||||
if (Test-Path $SolutionPath) {
|
||||
Copy-Item $SolutionPath $backupPath -Force
|
||||
Write-Host "Backed up existing solution to $backupPath" -ForegroundColor Gray
|
||||
}
|
||||
|
||||
# Create new solution
|
||||
Write-Host ""
|
||||
Write-Host "Creating new solution..." -ForegroundColor Yellow
|
||||
$slnDir = Split-Path $SolutionPath -Parent
|
||||
$slnName = [System.IO.Path]::GetFileNameWithoutExtension($SolutionPath)
|
||||
|
||||
# Remove old solution
|
||||
if (Test-Path $SolutionPath) {
|
||||
Remove-Item $SolutionPath -Force
|
||||
}
|
||||
|
||||
# Create fresh solution
|
||||
Push-Location $slnDir
|
||||
dotnet new sln -n $slnName --force 2>$null
|
||||
Pop-Location
|
||||
|
||||
# Add projects in batches (dotnet sln add can handle multiple)
|
||||
Write-Host "Adding projects to solution..." -ForegroundColor Yellow
|
||||
$added = 0
|
||||
$failed = 0
|
||||
|
||||
foreach ($proj in $finalProjects) {
|
||||
try {
|
||||
$result = dotnet sln $SolutionPath add $proj 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$added++
|
||||
if ($added % 50 -eq 0) {
|
||||
Write-Host " Added $added projects..." -ForegroundColor Gray
|
||||
}
|
||||
} else {
|
||||
Write-Host " Failed to add: $proj" -ForegroundColor Red
|
||||
$failed++
|
||||
}
|
||||
} catch {
|
||||
Write-Host " Error adding: $proj - $_" -ForegroundColor Red
|
||||
$failed++
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== Summary ===" -ForegroundColor Cyan
|
||||
Write-Host "Projects added: $added" -ForegroundColor Green
|
||||
Write-Host "Projects failed: $failed" -ForegroundColor $(if ($failed -gt 0) { "Red" } else { "Green" })
|
||||
Write-Host ""
|
||||
Write-Host "Solution regenerated at: $SolutionPath"
|
||||
|
||||
# Verify
|
||||
Write-Host ""
|
||||
Write-Host "Verifying solution..." -ForegroundColor Yellow
|
||||
$verifyResult = dotnet build $SolutionPath --no-restore -t:ValidateSolutionConfiguration 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "Solution validation passed!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Solution validation had issues - check manually" -ForegroundColor Yellow
|
||||
}
|
||||
70
devops/scripts/remove-stale-refs.ps1
Normal file
70
devops/scripts/remove-stale-refs.ps1
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# remove-stale-refs.ps1 - Remove stale project references that don't exist
|
||||
|
||||
param([string]$SlnPath = "src/StellaOps.sln")
|
||||
|
||||
$content = Get-Content $SlnPath -Raw
|
||||
$lines = $content -split "`r?`n"
|
||||
|
||||
# Stale project paths (relative from solution location)
|
||||
$staleProjects = @(
|
||||
"__Tests\AirGap\StellaOps.AirGap.Controller.Tests",
|
||||
"__Tests\AirGap\StellaOps.AirGap.Importer.Tests",
|
||||
"__Tests\AirGap\StellaOps.AirGap.Time.Tests",
|
||||
"__Tests\StellaOps.Gateway.WebService.Tests",
|
||||
"__Tests\Graph\StellaOps.Graph.Indexer.Tests",
|
||||
"Scanner\StellaOps.Scanner.Analyzers.Native",
|
||||
"__Libraries\__Tests\StellaOps.Signals.Tests",
|
||||
"__Tests\StellaOps.Audit.ReplayToken.Tests",
|
||||
"__Tests\StellaOps.Router.Gateway.Tests",
|
||||
"__Libraries\StellaOps.Cryptography"
|
||||
)
|
||||
|
||||
$staleGuids = @()
|
||||
$newLines = @()
|
||||
$skipNext = $false
|
||||
|
||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||
$line = $lines[$i]
|
||||
|
||||
if ($skipNext) {
|
||||
$skipNext = $false
|
||||
continue
|
||||
}
|
||||
|
||||
$isStale = $false
|
||||
foreach ($stalePath in $staleProjects) {
|
||||
if ($line -like "*$stalePath*") {
|
||||
# Extract GUID
|
||||
if ($line -match '\{([A-F0-9-]+)\}"?$') {
|
||||
$staleGuids += $Matches[1]
|
||||
}
|
||||
Write-Host "Removing stale: $stalePath"
|
||||
$isStale = $true
|
||||
$skipNext = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $isStale) {
|
||||
$newLines += $line
|
||||
}
|
||||
}
|
||||
|
||||
# Remove GlobalSection references to stale GUIDs
|
||||
$finalLines = @()
|
||||
foreach ($line in $newLines) {
|
||||
$skip = $false
|
||||
foreach ($guid in $staleGuids) {
|
||||
if ($line -match $guid) {
|
||||
$skip = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (-not $skip) {
|
||||
$finalLines += $line
|
||||
}
|
||||
}
|
||||
|
||||
$finalLines -join "`r`n" | Set-Content $SlnPath -Encoding UTF8 -NoNewline
|
||||
Write-Host "Removed $($staleGuids.Count) stale project references"
|
||||
61
devops/scripts/restore-deleted-tests.ps1
Normal file
61
devops/scripts/restore-deleted-tests.ps1
Normal file
@@ -0,0 +1,61 @@
|
||||
# Restore deleted test files from commit parent
|
||||
# Maps old locations to new locations
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$parentCommit = "74c7aa250c401ee9ac332686832b256159efa604^"
|
||||
|
||||
# Mapping: old path -> new path
|
||||
$mappings = @{
|
||||
"src/__Tests/AirGap/StellaOps.AirGap.Importer.Tests" = "src/AirGap/__Tests/StellaOps.AirGap.Importer.Tests"
|
||||
"src/__Tests/AirGap/StellaOps.AirGap.Controller.Tests" = "src/AirGap/__Tests/StellaOps.AirGap.Controller.Tests"
|
||||
"src/__Tests/AirGap/StellaOps.AirGap.Time.Tests" = "src/AirGap/__Tests/StellaOps.AirGap.Time.Tests"
|
||||
"src/__Tests/StellaOps.Gateway.WebService.Tests" = "src/Gateway/__Tests/StellaOps.Gateway.WebService.Tests"
|
||||
"src/__Tests/Replay/StellaOps.Replay.Core.Tests" = "src/Replay/__Tests/StellaOps.Replay.Core.Tests"
|
||||
"src/__Tests/Provenance/StellaOps.Provenance.Attestation.Tests" = "src/Provenance/__Tests/StellaOps.Provenance.Attestation.Tests"
|
||||
"src/__Tests/Policy/StellaOps.Policy.Scoring.Tests" = "src/Policy/__Tests/StellaOps.Policy.Scoring.Tests"
|
||||
}
|
||||
|
||||
Set-Location "E:\dev\git.stella-ops.org"
|
||||
|
||||
foreach ($mapping in $mappings.GetEnumerator()) {
|
||||
$oldPath = $mapping.Key
|
||||
$newPath = $mapping.Value
|
||||
|
||||
Write-Host "`nProcessing: $oldPath -> $newPath" -ForegroundColor Cyan
|
||||
|
||||
# Get list of files from old location in git
|
||||
$files = git ls-tree -r --name-only "$parentCommit" -- $oldPath 2>$null
|
||||
|
||||
if (-not $files) {
|
||||
Write-Host " No files found at old path" -ForegroundColor Yellow
|
||||
continue
|
||||
}
|
||||
|
||||
foreach ($file in $files) {
|
||||
# Calculate relative path and new file path
|
||||
$relativePath = $file.Substring($oldPath.Length + 1)
|
||||
$newFilePath = Join-Path $newPath $relativePath
|
||||
|
||||
# Create directory if needed
|
||||
$newDir = Split-Path $newFilePath -Parent
|
||||
if (-not (Test-Path $newDir)) {
|
||||
New-Item -ItemType Directory -Path $newDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Check if file exists
|
||||
if (Test-Path $newFilePath) {
|
||||
Write-Host " Exists: $relativePath" -ForegroundColor DarkGray
|
||||
continue
|
||||
}
|
||||
|
||||
# Restore file
|
||||
git show "${parentCommit}:${file}" > $newFilePath 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host " Restored: $relativePath" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " Failed: $relativePath" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "`nDone!" -ForegroundColor Cyan
|
||||
Reference in New Issue
Block a user