prvng_core/nulib/lib_provisioning/project/deployment-pipeline.nu

302 lines
8.9 KiB
Plaintext
Raw Permalink Normal View History

# Deployment Pipeline Integration Module
# Integrates detection and completion into infrastructure provisioning workflows
# Run full infrastructure-from-code pipeline
export def run-ifc-pipeline [
project_path: string
--org: string = "default"
--format: string = "json"
--apply: bool = false
--verbose: bool = false
] {
let start_time = (now)
if $verbose {
print $"🚀 Starting Infrastructure-from-Code Pipeline"
print $" Project: ($project_path)"
print $" Organization: ($org)"
print ""
}
# Step 1: Detect technologies
if $verbose {
print "STEP 1: Technology Detection"
print "━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
let detection = (detect-project $project_path --format "json" --debug $verbose)
if ($detection | has "error") {
return {
success: false
error: $detection.error
message: $detection.message
duration_ms: ((now) - $start_time | into int)
}
}
if $verbose {
print $"✓ Detected ($detection.detections | length) technologies"
print ""
}
# Step 2: Load organization rules
if $verbose {
print "STEP 2: Load Inference Rules"
print "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
let rules = (load-inference-rules $org)
if $verbose {
print $"✓ Loaded ($rules.rules | length) inference rules"
print ""
}
# Step 3: Apply inference rules
if $verbose {
print "STEP 3: Apply Inference Rules"
print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
let inference_result = (apply-inference-rules $detection $rules)
if $verbose {
print $"✓ Applied ($inference_result.applied_rules | length) rules"
print $"✓ Inferred ($inference_result.additional_requirements | length) requirements"
print ""
}
# Step 4: Complete declaration
if $verbose {
print "STEP 4: Complete Declaration"
print "━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
let completion = (complete-project $project_path --format "json" --check (not $apply) --debug $verbose)
if ($completion | has "error") {
if $verbose {
print $"⚠️ Completion skipped: ($completion.error)"
print ""
}
} else {
if $verbose {
print $"✓ Completeness: ($completion.completeness | math round -p 1)%"
print $"✓ Gaps identified: ($completion.gaps | length)"
print ""
}
}
# Step 5: Generate report
if $verbose {
print "STEP 5: Generating Report"
print "━━━━━━━━━━━━━━━━━━━━━━━━"
}
let pipeline_result = {
success: true
timestamp: (now | date format '%Y-%m-%dT%H:%M:%SZ')
project_path: $project_path
organization: $org
applied: $apply
duration_ms: ((now) - $start_time | into int)
detection: $detection
inference: $inference_result
completion: (if ($completion | has "error") { null } else { $completion })
summary: {
technologies_detected: ($detection.detections | length)
requirements_inferred: ($inference_result.additional_requirements | length)
gaps_identified: ($completion.gaps | default [] | length)
completeness_percent: ($completion.completeness | default 0 | math round -p 1)
safe_to_apply: ($completion.is_safe | default false)
}
}
if $verbose {
print $"✓ Pipeline completed in ($pipeline_result.duration_ms)ms"
print ""
print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
print "SUMMARY"
print "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
print $pipeline_result.summary
}
$pipeline_result
}
# Validate infrastructure declaration completeness
export def validate-declaration [
project_path: string
--min-completeness: float = 0.90
--strict: bool = false
] {
let completion = (complete-project $project_path --format "json")
if ($completion | has "error") {
return {
valid: false
error: $completion.error
message: $completion.message
}
}
let is_complete = ($completion.completeness >= $min_completeness)
let has_errors = ($completion.error_count > 0)
let is_safe = $completion.is_safe
{
valid: (if $strict { $is_complete and not $has_errors and $is_safe } else { $is_complete })
completeness: $completion.completeness
min_completeness: $min_completeness
errors: $completion.error_count
warnings: $completion.warning_count
safe_to_apply: $is_safe
issues: ($completion.gaps | each {|g| $g.message } | default [])
}
}
# Export pipeline state to file
export def save-pipeline-state [
state: record
output_path: string
] {
try {
$state | to json | save $output_path
{
success: true
message: $"Pipeline state saved to ($output_path)"
path: $output_path
}
} catch {|err|
{
success: false
error: $err.msg
path: $output_path
}
}
}
# Load and resume pipeline from saved state
export def resume-pipeline [
state_path: string
] {
try {
let state = (open $state_path | from json)
{
success: true
state: $state
}
} catch {|err|
{
success: false
error: $err.msg
}
}
}
# Create deployment checklist from pipeline result
export def create-deployment-checklist [
pipeline_result: record
] {
let checks = [
{
title: "Technology Detection"
passed: (($pipeline_result.detection.detections | length) > 0)
details: $"($pipeline_result.detection.detections | length) technologies detected"
}
{
title: "Inference Rules Applied"
passed: (($pipeline_result.inference.applied_rules | length) > 0)
details: $"($pipeline_result.inference.applied_rules | length) rules applied"
}
{
title: "Declaration Completeness"
passed: ($pipeline_result.summary.completeness_percent >= 90)
details: $"($pipeline_result.summary.completeness_percent)% complete"
}
{
title: "No Critical Gaps"
passed: ($pipeline_result.completion.error_count == 0)
details: $"($pipeline_result.completion.error_count) errors, ($pipeline_result.completion.warning_count) warnings"
}
{
title: "Safe to Deploy"
passed: $pipeline_result.completion.is_safe
details: (if $pipeline_result.completion.is_safe { "No breaking changes" } else { "Review breaking changes" })
}
]
{
title: "Infrastructure Deployment Checklist"
timestamp: (now | date format '%Y-%m-%d %H:%M:%S')
all_passed: ($checks | all {|c| $c.passed })
checks: $checks
next_steps: (if ($checks | all {|c| $c.passed }) {
[
"Deploy infrastructure with 'provisioning server create'"
"Apply configuration management"
"Run smoke tests"
"Monitor deployment"
]
} else {
[
"Review failed checks"
"Address critical gaps"
"Revalidate declaration"
]
})
}
}
# Integration with CI/CD pipelines
export def export-for-ci [
pipeline_result: record
ci_system: string = "github"
] {
match $ci_system {
"github" => {
# GitHub Actions output format
{
output_format: "github-actions"
set_output: {
"detection-success": (not ($pipeline_result.detection | has "error"))
"completeness": $pipeline_result.summary.completeness_percent
"safe-to-deploy": $pipeline_result.completion.is_safe
"detected-techs": ($pipeline_result.detection.detections | each {|d| $d.technology } | str join ",")
"inferred-reqs": ($pipeline_result.inference.additional_requirements | each {|r| $r.taskserv } | str join ",")
}
annotations: ($pipeline_result.completion.gaps | map {|g|
{
file: "provisioning/declaration.k"
level: (if $g.severity == "Error" { "error" } else { "warning" })
message: $g.message
title: $g.suggestion
}
} | default [])
}
}
"gitlab" => {
# GitLab CI output format
{
output_format: "gitlab-ci"
variables: {
"DETECTION_SUCCESS": (not ($pipeline_result.detection | has "error"))
"COMPLETENESS_PERCENT": ($pipeline_result.summary.completeness_percent | into string)
"SAFE_TO_DEPLOY": ($pipeline_result.completion.is_safe | into string)
"DETECTED_TECHNOLOGIES": ($pipeline_result.detection.detections | each {|d| $d.technology } | str join ",")
"INFERRED_REQUIREMENTS": ($pipeline_result.inference.additional_requirements | each {|r| $r.taskserv } | str join ",")
}
artifacts: {
reports: {
junit: "pipeline-report.xml"
}
}
}
}
_ => {
# Generic format
$pipeline_result
}
}
}