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

@@ -83,17 +83,21 @@ final readonly class ArgumentParser
// Handle --option=value
if (str_contains($optionPart, '=')) {
[$name, $value] = explode('=', $optionPart, 2);
$parsed['options'][$name] = $this->parseValue($name, $value);
$camelCaseName = $this->kebabToCamelCase($name);
$parsed['options'][$camelCaseName] = $this->parseValue($camelCaseName, $value);
return $index + 1;
}
// Convert kebab-case to camelCase for definition lookup
$camelCaseName = $this->kebabToCamelCase($optionPart);
// Handle --option value or --flag
$definition = $this->findDefinitionByName($optionPart);
$definition = $this->findDefinitionByName($camelCaseName);
if ($definition && $definition->type === ArgumentType::BOOLEAN) {
// Boolean flag
$parsed['flags'][$optionPart] = true;
// Boolean flag - use camelCase name
$parsed['flags'][$camelCaseName] = true;
return $index + 1;
}
@@ -104,16 +108,25 @@ final readonly class ArgumentParser
throw new \InvalidArgumentException("Option '--{$optionPart}' requires a value");
}
// Optional option without value - treat as flag
$parsed['flags'][$optionPart] = true;
$parsed['flags'][$camelCaseName] = true;
return $index + 1;
}
$parsed['options'][$optionPart] = $this->parseValue($optionPart, $arguments[$index + 1]);
$parsed['options'][$camelCaseName] = $this->parseValue($camelCaseName, $arguments[$index + 1]);
return $index + 2;
}
/**
* Convert kebab-case to camelCase
* Example: dry-run -> dryRun
*/
private function kebabToCamelCase(string $kebab): string
{
return lcfirst(str_replace('-', '', ucwords($kebab, '-')));
}
/**
* Parse short option (-o or -o value or -abc)
*/
@@ -325,54 +338,3 @@ final readonly class ArgumentParser
return new ArgumentParserBuilder();
}
}
/**
* Fluent builder for ArgumentParser
*/
final class ArgumentParserBuilder
{
/** @var ArgumentDefinition[] */
private array $definitions = [];
public function addArgument(ArgumentDefinition $definition): self
{
$this->definitions[$definition->name] = $definition;
return $this;
}
public function requiredString(string $name, string $description = ''): self
{
return $this->addArgument(ArgumentDefinition::required($name, $description));
}
public function optionalString(string $name, string $default = '', string $description = ''): self
{
return $this->addArgument(ArgumentDefinition::optional($name, $default, $description));
}
public function flag(string $name, ?string $shortName = null, string $description = ''): self
{
return $this->addArgument(ArgumentDefinition::flag($name, $shortName, $description));
}
public function email(string $name, bool $required = true, string $description = ''): self
{
return $this->addArgument(ArgumentDefinition::email($name, $required, $description));
}
public function integer(string $name, bool $required = false, ?int $default = null, string $description = ''): self
{
return $this->addArgument(ArgumentDefinition::integer($name, $required, $default, $description));
}
public function choice(string $name, array $choices, bool $required = false, ?string $default = null, string $description = ''): self
{
return $this->addArgument(ArgumentDefinition::choice($name, $choices, $required, $default, $description));
}
public function build(): ArgumentParser
{
return new ArgumentParser($this->definitions);
}
}