feat(Production): Complete production deployment infrastructure

- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -0,0 +1,157 @@
<?php
declare(strict_types=1);
use App\Framework\Deployment\Pipeline\ValueObjects\DeploymentEnvironment;
use App\Framework\Deployment\Pipeline\ValueObjects\PipelineConfig;
use App\Framework\Deployment\Pipeline\ValueObjects\PipelineStage;
use App\Framework\Deployment\Pipeline\ValueObjects\StageConfig;
describe('PipelineConfig', function () {
it('creates pipeline configuration with default values', function () {
$stages = [
StageConfig::forStage(PipelineStage::BUILD),
StageConfig::forStage(PipelineStage::TEST),
];
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: $stages
);
expect($config->name)->toBe('Test Pipeline');
expect($config->environment)->toBe(DeploymentEnvironment::DEVELOPMENT);
expect($config->stopOnFailure)->toBeTrue();
expect($config->enableRollback)->toBeFalse();
expect($config->globalParameters)->toBeEmpty();
});
it('creates pipeline configuration with custom values', function () {
$stages = [StageConfig::forStage(PipelineStage::BUILD)];
$config = new PipelineConfig(
name: 'Custom Pipeline',
environment: DeploymentEnvironment::PRODUCTION,
stages: $stages,
stopOnFailure: false,
enableRollback: true,
globalParameters: ['key' => 'value']
);
expect($config->stopOnFailure)->toBeFalse();
expect($config->enableRollback)->toBeTrue();
expect($config->globalParameters)->toHaveKey('key');
});
it('returns all stages', function () {
$stages = [
StageConfig::forStage(PipelineStage::BUILD),
StageConfig::forStage(PipelineStage::TEST),
StageConfig::forStage(PipelineStage::DEPLOY),
];
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: $stages
);
expect($config->getStages())->toHaveCount(3);
});
it('returns only enabled stages', function () {
$stages = [
new StageConfig(stage: PipelineStage::BUILD, enabled: true),
new StageConfig(stage: PipelineStage::TEST, enabled: false),
new StageConfig(stage: PipelineStage::DEPLOY, enabled: true),
];
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: $stages
);
$enabledStages = $config->getEnabledStages();
expect($enabledStages)->toHaveCount(2);
expect($enabledStages[0]->stage)->toBe(PipelineStage::BUILD);
expect($enabledStages[1]->stage)->toBe(PipelineStage::DEPLOY);
});
it('finds stage by type', function () {
$stages = [
StageConfig::forStage(PipelineStage::BUILD),
StageConfig::forStage(PipelineStage::TEST),
];
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: $stages
);
$buildStage = $config->findStage(PipelineStage::BUILD);
expect($buildStage)->not->toBeNull();
expect($buildStage->stage)->toBe(PipelineStage::BUILD);
});
it('returns null for non-existent stage', function () {
$stages = [StageConfig::forStage(PipelineStage::BUILD)];
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: $stages
);
$deployStage = $config->findStage(PipelineStage::DEPLOY);
expect($deployStage)->toBeNull();
});
it('checks if stage is enabled', function () {
$stages = [
new StageConfig(stage: PipelineStage::BUILD, enabled: true),
new StageConfig(stage: PipelineStage::TEST, enabled: false),
];
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: $stages
);
expect($config->isStageEnabled(PipelineStage::BUILD))->toBeTrue();
expect($config->isStageEnabled(PipelineStage::TEST))->toBeFalse();
expect($config->isStageEnabled(PipelineStage::DEPLOY))->toBeFalse(); // Not in config
});
it('gets global parameter with default', function () {
$config = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: [],
globalParameters: ['timeout' => 300]
);
expect($config->getGlobalParameter('timeout'))->toBe(300);
expect($config->getGlobalParameter('missing', 'default'))->toBe('default');
});
it('creates config for different environment', function () {
$original = new PipelineConfig(
name: 'Test Pipeline',
environment: DeploymentEnvironment::DEVELOPMENT,
stages: [StageConfig::forStage(PipelineStage::BUILD)]
);
$production = $original->forEnvironment(DeploymentEnvironment::PRODUCTION);
expect($production->environment)->toBe(DeploymentEnvironment::PRODUCTION);
expect($production->name)->toBe($original->name);
expect($production->stages)->toBe($original->stages);
});
});

View File

@@ -0,0 +1,161 @@
<?php
declare(strict_types=1);
use App\Framework\Deployment\Pipeline\ValueObjects\DeploymentEnvironment;
use App\Framework\Deployment\Pipeline\ValueObjects\PipelineStage;
use App\Framework\Deployment\Pipeline\ValueObjects\StageConfig;
describe('StageConfig', function () {
it('creates stage config with default values', function () {
$config = new StageConfig(stage: PipelineStage::BUILD);
expect($config->stage)->toBe(PipelineStage::BUILD);
expect($config->enabled)->toBeTrue();
expect($config->timeoutSeconds)->toBe(0);
expect($config->retries)->toBe(0);
expect($config->continueOnFailure)->toBeFalse();
expect($config->parameters)->toBeEmpty();
expect($config->skipEnvironments)->toBeEmpty();
});
it('creates stage config with custom values', function () {
$config = new StageConfig(
stage: PipelineStage::BUILD,
enabled: false,
timeoutSeconds: 300,
retries: 3,
continueOnFailure: true,
parameters: ['key' => 'value'],
skipEnvironments: [DeploymentEnvironment::DEVELOPMENT]
);
expect($config->enabled)->toBeFalse();
expect($config->timeoutSeconds)->toBe(300);
expect($config->retries)->toBe(3);
expect($config->continueOnFailure)->toBeTrue();
expect($config->parameters)->toHaveKey('key');
expect($config->skipEnvironments)->toContain(DeploymentEnvironment::DEVELOPMENT);
});
it('determines if should skip for environment', function () {
$config = new StageConfig(
stage: PipelineStage::BACKUP,
skipEnvironments: [
DeploymentEnvironment::DEVELOPMENT,
DeploymentEnvironment::STAGING
]
);
expect($config->shouldSkipForEnvironment(DeploymentEnvironment::DEVELOPMENT))->toBeTrue();
expect($config->shouldSkipForEnvironment(DeploymentEnvironment::STAGING))->toBeTrue();
expect($config->shouldSkipForEnvironment(DeploymentEnvironment::PRODUCTION))->toBeFalse();
});
it('gets parameter with default value', function () {
$config = new StageConfig(
stage: PipelineStage::BUILD,
parameters: ['timeout' => 300]
);
expect($config->getParameter('timeout'))->toBe(300);
expect($config->getParameter('missing', 'default'))->toBe('default');
});
it('checks if has timeout', function () {
$noTimeout = new StageConfig(
stage: PipelineStage::BUILD,
timeoutSeconds: 0
);
$withTimeout = new StageConfig(
stage: PipelineStage::BUILD,
timeoutSeconds: 300
);
expect($noTimeout->hasTimeout())->toBeFalse();
expect($withTimeout->hasTimeout())->toBeTrue();
});
it('checks if has retries', function () {
$noRetries = new StageConfig(
stage: PipelineStage::BUILD,
retries: 0
);
$withRetries = new StageConfig(
stage: PipelineStage::BUILD,
retries: 3
);
expect($noRetries->hasRetries())->toBeFalse();
expect($withRetries->hasRetries())->toBeTrue();
});
it('creates default config for build stage', function () {
$config = StageConfig::forStage(PipelineStage::BUILD);
expect($config->stage)->toBe(PipelineStage::BUILD);
expect($config->enabled)->toBeTrue();
expect($config->timeoutSeconds)->toBe(600); // 10 minutes
expect($config->retries)->toBe(1);
});
it('creates default config for test stage', function () {
$config = StageConfig::forStage(PipelineStage::TEST);
expect($config->stage)->toBe(PipelineStage::TEST);
expect($config->timeoutSeconds)->toBe(300); // 5 minutes
expect($config->retries)->toBe(0);
expect($config->skipEnvironments)->toContain(DeploymentEnvironment::PRODUCTION);
});
it('creates default config for security check stage', function () {
$config = StageConfig::forStage(PipelineStage::SECURITY_CHECK);
expect($config->stage)->toBe(PipelineStage::SECURITY_CHECK);
expect($config->timeoutSeconds)->toBe(120); // 2 minutes
expect($config->skipEnvironments)->toContain(DeploymentEnvironment::DEVELOPMENT);
});
it('creates default config for backup stage', function () {
$config = StageConfig::forStage(PipelineStage::BACKUP);
expect($config->stage)->toBe(PipelineStage::BACKUP);
expect($config->timeoutSeconds)->toBe(300); // 5 minutes
expect($config->retries)->toBe(1);
expect($config->skipEnvironments)->toContain(DeploymentEnvironment::DEVELOPMENT);
});
it('creates default config for deploy stage', function () {
$config = StageConfig::forStage(PipelineStage::DEPLOY);
expect($config->stage)->toBe(PipelineStage::DEPLOY);
expect($config->timeoutSeconds)->toBe(600); // 10 minutes
expect($config->retries)->toBe(0);
});
it('creates default config for health check stage', function () {
$config = StageConfig::forStage(PipelineStage::HEALTH_CHECK);
expect($config->stage)->toBe(PipelineStage::HEALTH_CHECK);
expect($config->timeoutSeconds)->toBe(60); // 1 minute
expect($config->retries)->toBe(2);
});
it('creates default config for cleanup stage', function () {
$config = StageConfig::forStage(PipelineStage::CLEANUP);
expect($config->stage)->toBe(PipelineStage::CLEANUP);
expect($config->timeoutSeconds)->toBe(180); // 3 minutes
expect($config->continueOnFailure)->toBeTrue();
});
it('creates default config for rollback stage', function () {
$config = StageConfig::forStage(PipelineStage::ROLLBACK);
expect($config->stage)->toBe(PipelineStage::ROLLBACK);
expect($config->timeoutSeconds)->toBe(300); // 5 minutes
expect($config->retries)->toBe(0);
});
});