chore(deploy): add prod env template, improve ansible deploy, prune old workflows

- Add deployment/ansible/templates/.env.production.j2 used by secrets playbook
- Enhance deploy-update.yml to read registry creds from vault or CI
- Update production-deploy workflow to pass registry credentials to Ansible
- Remove obsolete GitHub-style workflows under .gitea (conflicted naming)

Why: make the production pipeline executable end-to-end with Ansible and
consistent secrets handling; avoid legacy CI configs interfering.
This commit is contained in:
2025-10-30 21:38:28 +01:00
parent d021c49906
commit 2a7b90312f
18 changed files with 577 additions and 30 deletions

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Core\Helper;
final class Str
{
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\Framework\Core\ValueObjects;
use Stringable;
final readonly class DataRate implements Stringable
{
public function __construct(
private Byte $bytes,
private Duration $duration,
) {}
public function __toString()
{
return sprintf('%d B / %d ns', $this->bytes->toBytes(), $this->duration->toNanoseconds());
}
}

View File

@@ -8,12 +8,18 @@ use InvalidArgumentException;
final readonly class Duration
{
private function __construct(
private int $nanoseconds
private int $nanoseconds;
public function __construct(
float|int $value,
TimeUnit $unit = TimeUnit::NANOSECOND,
) {
if ($nanoseconds < 0) {
if ($value < 0) {
throw new InvalidArgumentException('Duration cannot be negative');
}
$seconds = $value * $unit->getMultiplierToSeconds();
$this->nanoseconds = (int) round($seconds * 1_000_000_000);
}
/**
@@ -21,27 +27,18 @@ final readonly class Duration
*/
public static function fromNanoseconds(int $nanoseconds): self
{
return new self($nanoseconds);
return new self($nanoseconds, TimeUnit::NANOSECOND);
}
// Factory Methods
public static function fromSeconds(float $seconds): self
{
if ($seconds < 0) {
throw new InvalidArgumentException('Duration cannot be negative');
}
return new self((int) round($seconds * 1_000_000_000));
return new self($seconds, TimeUnit::SECOND);
}
public static function fromUnit(float $value, TimeUnit $unit): self
{
if ($value < 0) {
throw new InvalidArgumentException('Duration cannot be negative');
}
$seconds = $value * $unit->getMultiplierToSeconds();
return new self((int) round($seconds * 1_000_000_000));
return new self($value, $unit);
}
public static function fromMilliseconds(float $milliseconds): self
@@ -109,24 +106,24 @@ final readonly class Duration
return round($seconds / $unit->getMultiplierToSeconds(), $precision);
}
public function toMilliseconds(): float
public function toMilliseconds(int $precision = 0): float
{
return $this->toUnit(TimeUnit::MILLISECOND, 0);
return $this->toUnit(TimeUnit::MILLISECOND, $precision);
}
public function toMicroseconds(): float
public function toMicroseconds(int $precision = 0): float
{
return $this->toUnit(TimeUnit::MICROSECOND, 0);
return $this->toUnit(TimeUnit::MICROSECOND, $precision);
}
public function toMinutes(): float
public function toMinutes(int $precision = 0): float
{
return $this->toUnit(TimeUnit::MINUTE);
return $this->toUnit(TimeUnit::MINUTE, $precision);
}
public function toHours(): float
public function toHours(int $precision = 0): float
{
return $this->toUnit(TimeUnit::HOUR);
return $this->toUnit(TimeUnit::HOUR, $precision);
}
// Human-readable format
@@ -192,7 +189,7 @@ final readonly class Duration
public function isNotZero(): bool
{
return $this->nanoseconds > 0;
return !$this->isZero();
}
// Framework Integration
@@ -219,7 +216,7 @@ final readonly class Duration
public static function oneSecond(): self
{
return new self(1_000_000_000);
return new self(1, TimeUnit::SECOND);
}
public static function oneMinute(): self

View File

@@ -14,7 +14,7 @@ use App\Framework\Exception\FrameworkException;
final readonly class FileSize
{
public function __construct(
public readonly Byte $bytes
public Byte $bytes
) {
// File size cannot be negative (already validated by Byte)
}

View File

@@ -4,15 +4,25 @@ declare(strict_types=1);
namespace App\Framework\Core\ValueObjects;
use App\Framework\Math\Number;
use InvalidArgumentException;
use Stringable;
final readonly class Percentage
final readonly class Percentage implements Stringable
{
#public Number $value;
public function __construct(
private float $value
private float $value,
public PercentageMode $mode = PercentageMode::Strict,
) {
if ($value < 0.0 || $value > 100.0) {
throw new InvalidArgumentException('Percentage must be between 0 and 100');
if($this->mode === PercentageMode::Strict) {
if ($value < 0.0 || $value > 100.0) {
throw new InvalidArgumentException('Percentage must be between 0 and 100');
}
}
}

View File

@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace App\Framework\Core\ValueObjects;
enum PercentageMode
{
case Strict;
case Extended;
}

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Framework\Core\ValueObjects\PhoneNumber;
enum PhoneNumberFormat
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Math;
final class BcCalculator
{
}

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Framework\Math;
interface Calculator
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Math;
final class Context
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Math;
interface ContextResolver
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Math;
final class DefaultContextResolver
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Math;
final class Number
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace App\Framework\Math;
final class NumberCalculator
{
}

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Framework\Math;
enum RoundingMode
{
}