feat(Deployment): Integrate Ansible deployment via PHP deployment pipeline

- Create AnsibleDeployStage using framework's Process module for secure command execution
- Integrate AnsibleDeployStage into DeploymentPipelineCommands for production deployments
- Add force_deploy flag support in Ansible playbook to override stale locks
- Use PHP deployment module as orchestrator (php console.php deploy:production)
- Fix ErrorAggregationInitializer to use Environment class instead of $_ENV superglobal

Architecture:
- BuildStage → AnsibleDeployStage → HealthCheckStage for production
- Process module provides timeout, error handling, and output capture
- Ansible playbook supports rollback via rollback-git-based.yml
- Zero-downtime deployments with health checks
This commit is contained in:
2025-10-26 14:08:07 +01:00
parent a90263d3be
commit 3b623e7afb
170 changed files with 19888 additions and 575 deletions

View File

@@ -0,0 +1,253 @@
<layout name="admin" />
<x-breadcrumbs items='[
{"label": "Admin", "url": "/admin"},
{"label": "ML Dashboard", "url": "/admin/ml/dashboard"}
]' />
<div class="admin-page">
<div class="admin-page__header">
<div class="admin-page__header-content">
<h1 class="admin-page__title">{{ $page_title }}</h1>
<p class="admin-page__subtitle">Monitor machine learning model performance and health metrics</p>
</div>
<div class="admin-page__actions">
<a href="{{ $api_dashboard_url }}" class="admin-button admin-button--secondary" target="_blank">
<svg class="admin-icon" width="16" height="16" fill="currentColor">
<path d="M8 2a6 6 0 100 12A6 6 0 008 2zm0 10a4 4 0 110-8 4 4 0 010 8z"/>
</svg>
View API
</a>
</div>
</div>
<!-- Summary Cards -->
<div class="admin-grid admin-grid--3-col">
<!-- System Health Card -->
<div class="admin-card">
<div class="admin-card__header">
<h3 class="admin-card__title">System Health</h3>
</div>
<div class="admin-card__content">
<div class="admin-stat-list">
<div class="admin-stat-item">
<span class="admin-stat-item__label">Overall Status</span>
<span class="admin-stat-item__value">
<span class="admin-badge admin-badge--{{ $overall_badge }}">{{ $overall_status }}</span>
</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Health Percentage</span>
<span class="admin-stat-item__value">{{ $health_percentage }}%</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Average Accuracy</span>
<span class="admin-stat-item__value">{{ $average_accuracy }}%</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Time Window</span>
<span class="admin-stat-item__value">{{ $time_window_hours }} hours</span>
</div>
</div>
</div>
</div>
<!-- Model Statistics Card -->
<div class="admin-card">
<div class="admin-card__header">
<h3 class="admin-card__title">Model Statistics</h3>
</div>
<div class="admin-card__content">
<div class="admin-stat-list">
<div class="admin-stat-item">
<span class="admin-stat-item__label">Total Models</span>
<span class="admin-stat-item__value">{{ $total_models }}</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Healthy</span>
<span class="admin-stat-item__value">
<span class="admin-badge admin-badge--success">{{ $healthy_models }}</span>
</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Degraded</span>
<span class="admin-stat-item__value">
<span class="admin-badge admin-badge--warning">{{ $degraded_models }}</span>
</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Critical</span>
<span class="admin-stat-item__value">
<span class="admin-badge admin-badge--danger">{{ $critical_models }}</span>
</span>
</div>
</div>
</div>
</div>
<!-- Performance Metrics Card -->
<div class="admin-card">
<div class="admin-card__header">
<h3 class="admin-card__title">Performance Metrics</h3>
</div>
<div class="admin-card__content">
<div class="admin-stat-list">
<div class="admin-stat-item">
<span class="admin-stat-item__label">Total Predictions</span>
<span class="admin-stat-item__value">{{ $total_predictions }}</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Supervised Models</span>
<span class="admin-stat-item__value">{{ $supervised_count }}</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Unsupervised Models</span>
<span class="admin-stat-item__value">{{ $unsupervised_count }}</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Reinforcement Models</span>
<span class="admin-stat-item__value">{{ $reinforcement_count }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- Degradation Alerts Section -->
<div class="admin-card" if="{{ $has_alerts }}">
<div class="admin-card__header">
<h3 class="admin-card__title">
Degradation Alerts
<span class="admin-badge admin-badge--danger">{{ $alert_count }}</span>
</h3>
</div>
<div class="admin-card__content">
<div class="admin-table-container">
<table class="admin-table">
<thead>
<tr>
<th>Model</th>
<th>Version</th>
<th>Current Accuracy</th>
<th>Threshold</th>
<th>Severity</th>
<th>Recommendation</th>
</tr>
</thead>
<tbody>
<tr foreach="$alerts as $alert">
<td>
<strong>{{ $alert['model_name'] }}</strong>
</td>
<td>
<code>{{ $alert['version'] }}</code>
</td>
<td>
<span class="admin-badge admin-badge--{{ $alert['severity_badge'] }}">
{{ $alert['current_accuracy'] }}%
</span>
</td>
<td>{{ $alert['threshold'] }}%</td>
<td>
<span class="admin-badge admin-badge--{{ $alert['severity_badge'] }}">
{{ $alert['severity'] }}
</span>
</td>
<td>{{ $alert['recommendation'] }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Models Overview Section -->
<div class="admin-card">
<div class="admin-card__header">
<h3 class="admin-card__title">Models Overview</h3>
</div>
<div class="admin-card__content">
<div class="admin-table-container">
<table class="admin-table">
<thead>
<tr>
<th>Model Name</th>
<th>Version</th>
<th>Type</th>
<th>Accuracy</th>
<th>Precision</th>
<th>Recall</th>
<th>F1 Score</th>
<th>Predictions</th>
<th>Avg Confidence</th>
<th>Threshold</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr foreach="$models as $model">
<td>
<strong>{{ $model['model_name'] }}</strong>
</td>
<td>
<code>{{ $model['version'] }}</code>
</td>
<td>
<span class="admin-badge admin-badge--info">
{{ $model['type'] }}
</span>
</td>
<td>{{ $model['accuracy'] }}%</td>
<td>
<span if="!{{ $model['precision'] }}">-</span>
<span if="{{ $model['precision'] }}">{{ $model['precision'] }}%</span>
</td>
<td>
<span if="!{{ $model['recall'] }}">-</span>
<span if="{{ $model['recall'] }}">{{ $model['recall'] }}%</span>
</td>
<td>
<span if="!{{ $model['f1_score'] }}">-</span>
<span if="{{ $model['f1_score'] }}">{{ $model['f1_score'] }}%</span>
</td>
<td>{{ $model['total_predictions'] }}</td>
<td>
<span if="!{{ $model['average_confidence'] }}">-</span>
<span if="{{ $model['average_confidence'] }}">{{ $model['average_confidence'] }}%</span>
</td>
<td>{{ $model['threshold'] }}</td>
<td>
<span class="admin-badge admin-badge--{{ $model['status_badge'] }}">
{{ $model['status'] }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- API Information Card -->
<div class="admin-card">
<div class="admin-card__header">
<h3 class="admin-card__title">API Endpoints</h3>
</div>
<div class="admin-card__content">
<div class="admin-stat-list">
<div class="admin-stat-item">
<span class="admin-stat-item__label">Dashboard Data</span>
<span class="admin-stat-item__value">
<code>GET {{ $api_dashboard_url }}</code>
</span>
</div>
<div class="admin-stat-item">
<span class="admin-stat-item__label">Health Check</span>
<span class="admin-stat-item__value">
<code>GET {{ $api_health_url }}</code>
</span>
</div>
</div>
</div>
</div>
</div>