From 866d43e15acd80cca2cff9578550cfc570374a29 Mon Sep 17 00:00:00 2001 From: fs Date: Thu, 19 Mar 2026 10:34:35 +0100 Subject: [PATCH] Refactor bin scripts: shared CLI bootstrap, robust module migrate, and runtime locking --- bin/cli-bootstrap.php | 42 +++++ bin/doctor.php | 15 +- bin/module-assets-sync.php | 70 +++----- bin/module-build.php | 66 +++----- bin/module-cli-bootstrap.php | 50 ++++++ bin/module-migrate.php | 292 ++++++++++++++++++++++---------- bin/module-permissions-sync.php | 48 +++--- bin/module-runtime-sync.php | 91 +++++----- bin/scheduler-run.php | 17 +- 9 files changed, 423 insertions(+), 268 deletions(-) create mode 100644 bin/cli-bootstrap.php diff --git a/bin/cli-bootstrap.php b/bin/cli-bootstrap.php new file mode 100644 index 0000000..3b2d336 --- /dev/null +++ b/bin/cli-bootstrap.php @@ -0,0 +1,42 @@ + $channel, + 'method' => 'CLI', + 'path' => $path, + ]); + + if (!$container instanceof AppContainer) { + throw new RuntimeException('CLI app container bootstrap failed.'); + } + + return $container; +} diff --git a/bin/doctor.php b/bin/doctor.php index 3238435..3098d84 100755 --- a/bin/doctor.php +++ b/bin/doctor.php @@ -6,30 +6,19 @@ declare(strict_types=1); use MintyPHP\App\AppContainer; use MintyPHP\App\Bootstrap\EnvValidator; use MintyPHP\DB; -use MintyPHP\Http\RequestContext; use MintyPHP\Service\Access\AuthorizationService; use MintyPHP\Service\Access\PermissionService; use MintyPHP\Service\Access\UiAccessService; use MintyPHP\Service\Audit\SystemAuditService; use MintyPHP\Service\Auth\AuthService; -chdir(__DIR__ . '/..'); - error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED); ini_set('display_errors', '0'); -require 'vendor/autoload.php'; -require 'config/config.php'; -require 'lib/Support/helpers.php'; +require_once __DIR__ . '/cli-bootstrap.php'; /** @var AppContainer $container */ -$container = require 'lib/App/registerContainer.php'; -setAppContainer($container); -RequestContext::start([ - 'channel' => 'cli', - 'method' => 'CLI', - 'path' => 'bin/doctor.php', -]); +$container = cliBootstrapApp('cli', 'bin/doctor.php'); $startedAt = microtime(true); /** @var list $results */ diff --git a/bin/module-assets-sync.php b/bin/module-assets-sync.php index f5a0015..1df425c 100644 --- a/bin/module-assets-sync.php +++ b/bin/module-assets-sync.php @@ -24,55 +24,35 @@ require_once __DIR__ . '/module-cli-bootstrap.php'; function moduleAssetsSyncRun(): int { - $warningsBefore = moduleCliVendorWarningsIgnoredTotal(); - moduleCliBootstrapApp(); - - $exitCode = 0; - $runtimeModulesDir = __DIR__ . '/../web/modules'; - $lockFile = __DIR__ . '/../storage/runtime/.module-assets-sync.lock'; - $mode = (string) getenv('APP_MODULE_ASSET_MODE'); - if (trim($mode) === '') { - $mode = 'symlink'; - } - - try { - $lockDir = dirname($lockFile); - if (!is_dir($lockDir) && !mkdir($lockDir, 0775, true) && !is_dir($lockDir)) { - throw new RuntimeException("Failed to create lock directory: {$lockDir}"); + return moduleCliRunStep('module-assets-sync', static function (): int { + $runtimeModulesDir = __DIR__ . '/../web/modules'; + $lockFile = __DIR__ . '/../storage/runtime/.module-assets-sync.lock'; + $mode = (string) getenv('APP_MODULE_ASSET_MODE'); + if (trim($mode) === '') { + $mode = 'symlink'; } - $lock = fopen($lockFile, 'c'); - if ($lock === false || !flock($lock, LOCK_EX | LOCK_NB)) { - fwrite(STDERR, "module-assets-sync: another sync is in progress, skipping.\n"); - return 0; - } + return moduleCliWithFileLock( + $lockFile, + 'module-assets-sync: another sync is in progress, skipping.', + static function () use ($runtimeModulesDir, $mode): int { + $registry = app(ModuleRegistry::class); + $publisher = new ModuleRuntimeAssetPublisher(); + $result = $publisher->publish($runtimeModulesDir, $registry->getModules(), $mode); - $registry = app(ModuleRegistry::class); - $publisher = new ModuleRuntimeAssetPublisher(); - $result = $publisher->publish($runtimeModulesDir, $registry->getModules(), $mode); + fwrite(STDOUT, sprintf( + "module-assets-sync: mode=%s created=%d updated=%d removed=%d unchanged=%d\n", + $mode, + $result['created'], + $result['updated'], + $result['removed'], + $result['unchanged'] + )); - fwrite(STDOUT, sprintf( - "module-assets-sync: mode=%s created=%d updated=%d removed=%d unchanged=%d\n", - $mode, - $result['created'], - $result['updated'], - $result['removed'], - $result['unchanged'] - )); - } catch (Throwable $exception) { - fwrite(STDERR, sprintf("module-assets-sync: FAILED: %s\n", $exception->getMessage())); - $exitCode = 1; - } finally { - if (isset($lock) && is_resource($lock)) { - flock($lock, LOCK_UN); - fclose($lock); - } - } - - $vendorWarningsIgnored = moduleCliVendorWarningsIgnoredSince($warningsBefore); - fwrite(STDOUT, sprintf("module-assets-sync: vendor_warnings_ignored=%d\n", $vendorWarningsIgnored)); - - return $exitCode; + return 0; + } + ); + }); } if (PHP_SAPI === 'cli' && realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === __FILE__) { diff --git a/bin/module-build.php b/bin/module-build.php index ab0211b..e84011f 100644 --- a/bin/module-build.php +++ b/bin/module-build.php @@ -25,57 +25,41 @@ require_once __DIR__ . '/module-cli-bootstrap.php'; function moduleBuildRun(): int { - $warningsBefore = moduleCliVendorWarningsIgnoredTotal(); - moduleCliBootstrapApp(); + return moduleCliRunStep('module-build', static function (): int { + $runtimeDir = __DIR__ . '/../storage/runtime/pages'; + $lockFile = __DIR__ . '/../storage/runtime/.module-build.lock'; - $exitCode = 0; - $runtimeDir = __DIR__ . '/../storage/runtime/pages'; - $lockFile = __DIR__ . '/../storage/runtime/.module-build.lock'; - - try { // Ensure runtime directory exists $runtimeParent = dirname($runtimeDir); if (!is_dir($runtimeParent) && !mkdir($runtimeParent, 0775, true) && !is_dir($runtimeParent)) { throw new \RuntimeException("Failed to create runtime directory: {$runtimeParent}"); } - // Lock to prevent concurrent builds - $lock = fopen($lockFile, 'c'); - if ($lock === false || !flock($lock, LOCK_EX | LOCK_NB)) { - fwrite(STDERR, "module-build: another build is in progress, skipping.\n"); - return 0; - } + return moduleCliWithFileLock( + $lockFile, + 'module-build: another build is in progress, skipping.', + static function () use ($runtimeDir): int { + $registry = app(ModuleRegistry::class); + $modules = $registry->getModules(); + $builder = new ModuleRuntimePageBuilder(); + $result = $builder->build($runtimeDir, __DIR__ . '/../pages', $modules); - $registry = app(ModuleRegistry::class); - $modules = $registry->getModules(); - $builder = new ModuleRuntimePageBuilder(); - $result = $builder->build($runtimeDir, __DIR__ . '/../pages', $modules); + ModuleRuntimePageBuilder::writeFingerprint($runtimeDir, $modules); - ModuleRuntimePageBuilder::writeFingerprint($runtimeDir, $modules); + if (count($modules) === 0) { + fwrite(STDOUT, "module-build: no modules, runtime -> core pages (symlink).\n"); + } else { + fwrite(STDOUT, sprintf( + "module-build: runtime pages built - %d core entries + %d module entries.\n", + (int) ($result['core_entries'] ?? 0), + (int) ($result['module_entries'] ?? 0) + )); + } - if (count($modules) === 0) { - fwrite(STDOUT, "module-build: no modules, runtime → core pages (symlink).\n"); - } else { - fwrite(STDOUT, sprintf( - "module-build: runtime pages built — %d core entries + %d module entries.\n", - (int) ($result['core_entries'] ?? 0), - (int) ($result['module_entries'] ?? 0) - )); - } - } catch (Throwable $exception) { - fwrite(STDERR, sprintf("module-build: FAILED: %s\n", $exception->getMessage())); - $exitCode = 1; - } finally { - if (isset($lock) && is_resource($lock)) { - flock($lock, LOCK_UN); - fclose($lock); - } - } - - $vendorWarningsIgnored = moduleCliVendorWarningsIgnoredSince($warningsBefore); - fwrite(STDOUT, sprintf("module-build: vendor_warnings_ignored=%d\n", $vendorWarningsIgnored)); - - return $exitCode; + return 0; + } + ); + }); } if (PHP_SAPI === 'cli' && realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === __FILE__) { diff --git a/bin/module-cli-bootstrap.php b/bin/module-cli-bootstrap.php index eb9185a..8ee2026 100644 --- a/bin/module-cli-bootstrap.php +++ b/bin/module-cli-bootstrap.php @@ -114,3 +114,53 @@ function moduleCliBootstrapApp(): void $booted = true; } + +/** + * Runs one module CLI step with shared bootstrap, failure handling and vendor warning summary. + * + * @param callable():int $runner + */ +function moduleCliRunStep(string $stepName, callable $runner): int +{ + $warningsBefore = moduleCliVendorWarningsIgnoredTotal(); + moduleCliBootstrapApp(); + + $exitCode = 0; + try { + $exitCode = $runner(); + } catch (Throwable $exception) { + fwrite(STDERR, sprintf("%s: FAILED: %s\n", $stepName, $exception->getMessage())); + $exitCode = 1; + } + + $vendorWarningsIgnored = moduleCliVendorWarningsIgnoredSince($warningsBefore); + fwrite(STDOUT, sprintf("%s: vendor_warnings_ignored=%d\n", $stepName, $vendorWarningsIgnored)); + + return $exitCode; +} + +/** + * Executes a callable under a non-blocking file lock. + * + * @param callable():int $runner + */ +function moduleCliWithFileLock(string $lockFile, string $busyMessage, callable $runner): int +{ + $lockDir = dirname($lockFile); + if (!is_dir($lockDir) && !mkdir($lockDir, 0775, true) && !is_dir($lockDir)) { + throw new RuntimeException("Failed to create lock directory: {$lockDir}"); + } + + $lock = fopen($lockFile, 'c'); + if ($lock === false || !flock($lock, LOCK_EX | LOCK_NB)) { + fwrite(STDERR, $busyMessage . PHP_EOL); + return 0; + } + + try { + return $runner(); + } finally { + flock($lock, LOCK_UN); + fclose($lock); + } +} diff --git a/bin/module-migrate.php b/bin/module-migrate.php index c434716..c487a12 100644 --- a/bin/module-migrate.php +++ b/bin/module-migrate.php @@ -24,111 +24,225 @@ require_once __DIR__ . '/module-cli-bootstrap.php'; function moduleMigrateRun(): int { - $warningsBefore = moduleCliVendorWarningsIgnoredTotal(); - moduleCliBootstrapApp(); + return moduleCliRunStep('module-migrate', static function (): int { + $lockFile = __DIR__ . '/../storage/runtime/.module-migrate.lock'; - $exitCode = 0; - $totalApplied = 0; + return moduleCliWithFileLock( + $lockFile, + 'module-migrate: another migration run is in progress, skipping.', + static function (): int { + $totalApplied = 0; + $registry = app(ModuleRegistry::class); + $modules = $registry->getModules(); + $hasModules = count($modules) > 0; - try { - $registry = app(ModuleRegistry::class); - $modules = $registry->getModules(); - $hasModules = count($modules) > 0; - - if (!$hasModules) { - fwrite(STDOUT, "module-migrate: no modules enabled, nothing to do.\n"); - } else { - // Ensure tracking table exists (safe if already created by db/updates/ script) - DB::query( - 'CREATE TABLE IF NOT EXISTS `module_migrations` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `module_id` VARCHAR(64) NOT NULL, - `filename` VARCHAR(255) NOT NULL, - `applied_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE KEY `uq_module_migration` (`module_id`, `filename`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' - ); - } - - foreach ($modules as $manifest) { - $migrationsPath = $manifest->migrationsPath; - if ($migrationsPath === null || !is_dir($migrationsPath)) { - continue; - } - - // Discover SQL files - $files = glob($migrationsPath . '/*.sql'); - if ($files === false || count($files) === 0) { - continue; - } - sort($files); // alphabetical order - - // Get already-applied filenames - $applied = []; - $rows = DB::select('SELECT filename FROM module_migrations WHERE module_id = ?', [$manifest->id]); - foreach ($rows as $row) { - $applied[$row['filename']] = true; - } - - foreach ($files as $file) { - $filename = basename($file); - if (isset($applied[$filename])) { - continue; + if (!$hasModules) { + fwrite(STDOUT, "module-migrate: no modules enabled, nothing to do.\n"); + return 0; } - $sql = file_get_contents($file); - if ($sql === false || trim($sql) === '') { - fwrite(STDERR, sprintf("module-migrate: WARNING skipping empty file %s/%s\n", $manifest->id, $filename)); - continue; - } + // Ensure tracking table exists (safe if already created by db/updates/ script) + DB::query( + 'CREATE TABLE IF NOT EXISTS `module_migrations` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `module_id` VARCHAR(64) NOT NULL, + `filename` VARCHAR(255) NOT NULL, + `applied_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uq_module_migration` (`module_id`, `filename`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' + ); - fwrite(STDOUT, sprintf("module-migrate: applying %s/%s ... ", $manifest->id, $filename)); - - // Execute migration inside a transaction so partial failures don't leave the DB inconsistent - DB::query('START TRANSACTION'); - try { - $statements = array_filter(array_map('trim', explode(';', $sql)), static fn (string $s): bool => $s !== ''); - foreach ($statements as $statement) { - DB::query($statement); + foreach ($modules as $manifest) { + $migrationsPath = $manifest->migrationsPath; + if ($migrationsPath === null || !is_dir($migrationsPath)) { + continue; } - // Record as applied - DB::query( - 'INSERT INTO module_migrations (module_id, filename) VALUES (?, ?)', - [$manifest->id, $filename] - ); - DB::query('COMMIT'); - } catch (\Throwable $migrationError) { - DB::query('ROLLBACK'); - throw new \RuntimeException( - sprintf("Migration %s/%s failed: %s", $manifest->id, $filename, $migrationError->getMessage()), - 0, - $migrationError - ); + // Discover SQL files + $files = glob($migrationsPath . '/*.sql'); + if ($files === false || count($files) === 0) { + continue; + } + sort($files); // alphabetical order + + // Get already-applied filenames + $applied = []; + $rows = DB::select('SELECT filename FROM module_migrations WHERE module_id = ?', (string) $manifest->id); + foreach ((array) $rows as $row) { + if (!is_array($row)) { + continue; + } + $filename = trim((string) (($row['module_migrations']['filename'] ?? $row['filename'] ?? ''))); + if ($filename !== '') { + $applied[$filename] = true; + } + } + + foreach ($files as $file) { + $filename = basename($file); + if (isset($applied[$filename])) { + continue; + } + + $sql = file_get_contents($file); + if ($sql === false || trim($sql) === '') { + fwrite(STDERR, sprintf("module-migrate: WARNING skipping empty file %s/%s\n", $manifest->id, $filename)); + continue; + } + + fwrite(STDOUT, sprintf("module-migrate: applying %s/%s ... ", $manifest->id, $filename)); + + // Execute migration inside a transaction so partial failures don't leave the DB inconsistent. + DB::query('START TRANSACTION'); + try { + $statements = moduleMigrateSplitSqlStatements($sql); + foreach ($statements as $statement) { + DB::query($statement); + } + + // Record as applied + DB::query( + 'INSERT INTO module_migrations (module_id, filename) VALUES (?, ?)', + (string) $manifest->id, + $filename + ); + DB::query('COMMIT'); + } catch (\Throwable $migrationError) { + DB::query('ROLLBACK'); + throw new \RuntimeException( + sprintf("Migration %s/%s failed: %s", $manifest->id, $filename, $migrationError->getMessage()), + 0, + $migrationError + ); + } + + fwrite(STDOUT, "OK\n"); + $totalApplied++; + } } - fwrite(STDOUT, "OK\n"); - $totalApplied++; + if ($totalApplied === 0) { + fwrite(STDOUT, "module-migrate: all modules up to date, 0 new migrations.\n"); + } else { + fwrite(STDOUT, sprintf("module-migrate: applied %d migration(s).\n", $totalApplied)); + } + + return 0; + } + ); + }); +} + +/** + * @return list + */ +function moduleMigrateSplitSqlStatements(string $sql): array +{ + if (preg_match('/^\s*DELIMITER\s+/mi', $sql) === 1) { + throw new RuntimeException('DELIMITER directives are not supported in module migration SQL files.'); + } + + $statements = []; + $buffer = ''; + $length = strlen($sql); + $inSingleQuote = false; + $inDoubleQuote = false; + $inBacktick = false; + $inLineComment = false; + $inBlockComment = false; + $escapeNext = false; + + for ($i = 0; $i < $length; $i++) { + $char = $sql[$i]; + $next = $i + 1 < $length ? $sql[$i + 1] : ''; + + if ($inLineComment) { + $buffer .= $char; + if ($char === "\n") { + $inLineComment = false; + } + continue; + } + + if ($inBlockComment) { + $buffer .= $char; + if ($char === '*' && $next === '/') { + $buffer .= $next; + $i++; + $inBlockComment = false; + } + continue; + } + + if (!$inSingleQuote && !$inDoubleQuote && !$inBacktick) { + if ($char === '-' && $next === '-' && ($i + 2 >= $length || ctype_space($sql[$i + 2]))) { + $buffer .= $char . $next; + $i++; + $inLineComment = true; + continue; + } + if ($char === '#') { + $buffer .= $char; + $inLineComment = true; + continue; + } + if ($char === '/' && $next === '*') { + $buffer .= $char . $next; + $i++; + $inBlockComment = true; + continue; } } - if (!$hasModules) { - // Already reported above. - } elseif ($totalApplied === 0) { - fwrite(STDOUT, "module-migrate: all modules up to date, 0 new migrations.\n"); - } else { - fwrite(STDOUT, sprintf("module-migrate: applied %d migration(s).\n", $totalApplied)); + if ($escapeNext) { + $buffer .= $char; + $escapeNext = false; + continue; } - } catch (Throwable $exception) { - fwrite(STDERR, sprintf("module-migrate: FAILED: %s\n", $exception->getMessage())); - $exitCode = 1; + + if (($inSingleQuote || $inDoubleQuote) && $char === '\\') { + $buffer .= $char; + $escapeNext = true; + continue; + } + + if (!$inDoubleQuote && !$inBacktick && $char === '\'') { + $inSingleQuote = !$inSingleQuote; + $buffer .= $char; + continue; + } + + if (!$inSingleQuote && !$inBacktick && $char === '"') { + $inDoubleQuote = !$inDoubleQuote; + $buffer .= $char; + continue; + } + + if (!$inSingleQuote && !$inDoubleQuote && $char === '`') { + $inBacktick = !$inBacktick; + $buffer .= $char; + continue; + } + + if (!$inSingleQuote && !$inDoubleQuote && !$inBacktick && $char === ';') { + $statement = trim($buffer); + if ($statement !== '') { + $statements[] = $statement; + } + $buffer = ''; + continue; + } + + $buffer .= $char; } - $vendorWarningsIgnored = moduleCliVendorWarningsIgnoredSince($warningsBefore); - fwrite(STDOUT, sprintf("module-migrate: vendor_warnings_ignored=%d\n", $vendorWarningsIgnored)); + $tail = trim($buffer); + if ($tail !== '') { + $statements[] = $tail; + } - return $exitCode; + return $statements; } if (PHP_SAPI === 'cli' && realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === __FILE__) { diff --git a/bin/module-permissions-sync.php b/bin/module-permissions-sync.php index 8ae03b8..b9958fe 100644 --- a/bin/module-permissions-sync.php +++ b/bin/module-permissions-sync.php @@ -21,33 +21,31 @@ require_once __DIR__ . '/module-cli-bootstrap.php'; function modulePermissionsSyncRun(): int { - $warningsBefore = moduleCliVendorWarningsIgnoredTotal(); - moduleCliBootstrapApp(); + return moduleCliRunStep('module-permissions-sync', static function (): int { + $lockFile = __DIR__ . '/../storage/runtime/.module-permissions-sync.lock'; - $exitCode = 0; - try { - $synchronizer = new ModulePermissionSynchronizer( - app(ModuleRegistry::class), - app(PermissionRepository::class) + return moduleCliWithFileLock( + $lockFile, + 'module-permissions-sync: another sync is in progress, skipping.', + static function (): int { + $synchronizer = new ModulePermissionSynchronizer( + app(ModuleRegistry::class), + app(PermissionRepository::class) + ); + $result = $synchronizer->sync(); + + fwrite(STDOUT, sprintf( + "module-permissions-sync: created=%d updated=%d unchanged=%d total=%d\n", + $result['created'], + $result['updated'], + $result['unchanged'], + $result['total'] + )); + + return 0; + } ); - $result = $synchronizer->sync(); - - fwrite(STDOUT, sprintf( - "module-permissions-sync: created=%d updated=%d unchanged=%d total=%d\n", - $result['created'], - $result['updated'], - $result['unchanged'], - $result['total'] - )); - } catch (Throwable $exception) { - fwrite(STDERR, sprintf("module-permissions-sync: FAILED: %s\n", $exception->getMessage())); - $exitCode = 1; - } - - $vendorWarningsIgnored = moduleCliVendorWarningsIgnoredSince($warningsBefore); - fwrite(STDOUT, sprintf("module-permissions-sync: vendor_warnings_ignored=%d\n", $vendorWarningsIgnored)); - - return $exitCode; + }); } if (PHP_SAPI === 'cli' && realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === __FILE__) { diff --git a/bin/module-runtime-sync.php b/bin/module-runtime-sync.php index 446e3f7..076e853 100755 --- a/bin/module-runtime-sync.php +++ b/bin/module-runtime-sync.php @@ -12,54 +12,63 @@ require_once __DIR__ . '/module-assets-sync.php'; function moduleRuntimeSyncRun(): int { - moduleCliBootstrapApp(); - $warningsBeforeAll = moduleCliVendorWarningsIgnoredTotal(); + return moduleCliRunStep('module-runtime-sync', static function (): int { + $lockFile = __DIR__ . '/../storage/runtime/.module-runtime-sync.lock'; + return moduleCliWithFileLock( + $lockFile, + 'module-runtime-sync: another runtime sync is in progress, skipping.', + static function (): int { + moduleCliBootstrapApp(); + $warningsBeforeAll = moduleCliVendorWarningsIgnoredTotal(); - $steps = [ - 'migrate' => static fn (): int => moduleMigrateRun(), - 'permissions-sync' => static fn (): int => modulePermissionsSyncRun(), - 'build' => static fn (): int => moduleBuildRun(), - 'assets-sync' => static fn (): int => moduleAssetsSyncRun(), - ]; + $steps = [ + 'migrate' => static fn (): int => moduleMigrateRun(), + 'permissions-sync' => static fn (): int => modulePermissionsSyncRun(), + 'build' => static fn (): int => moduleBuildRun(), + 'assets-sync' => static fn (): int => moduleAssetsSyncRun(), + ]; - $statusByStep = []; - foreach (array_keys($steps) as $stepName) { - $statusByStep[$stepName] = 'pending'; - } + $statusByStep = []; + foreach (array_keys($steps) as $stepName) { + $statusByStep[$stepName] = 'pending'; + } - $finalExitCode = 0; - foreach ($steps as $stepName => $runner) { - $stepWarningsBefore = moduleCliVendorWarningsIgnoredTotal(); - $stepExitCode = $runner(); - $stepWarnings = moduleCliVendorWarningsIgnoredSince($stepWarningsBefore); - $stepStatus = $stepExitCode === 0 ? 'ok' : 'failed'; - $statusByStep[$stepName] = $stepStatus; + $finalExitCode = 0; + foreach ($steps as $stepName => $runner) { + $stepWarningsBefore = moduleCliVendorWarningsIgnoredTotal(); + $stepExitCode = $runner(); + $stepWarnings = moduleCliVendorWarningsIgnoredSince($stepWarningsBefore); + $stepStatus = $stepExitCode === 0 ? 'ok' : 'failed'; + $statusByStep[$stepName] = $stepStatus; - fwrite(STDOUT, sprintf( - "module-runtime-sync: step=%s status=%s exit_code=%d vendor_warnings_ignored=%d\n", - $stepName, - $stepStatus, - $stepExitCode, - $stepWarnings - )); + fwrite(STDOUT, sprintf( + "module-runtime-sync: step=%s status=%s exit_code=%d vendor_warnings_ignored=%d\n", + $stepName, + $stepStatus, + $stepExitCode, + $stepWarnings + )); - if ($stepExitCode !== 0) { - $finalExitCode = $stepExitCode; - break; - } - } + if ($stepExitCode !== 0) { + $finalExitCode = $stepExitCode; + break; + } + } - $totalVendorWarnings = moduleCliVendorWarningsIgnoredSince($warningsBeforeAll); - fwrite(STDOUT, sprintf( - "module-runtime-sync: summary migrate=%s permissions-sync=%s build=%s assets-sync=%s vendor_warnings_ignored=%d\n", - $statusByStep['migrate'], - $statusByStep['permissions-sync'], - $statusByStep['build'], - $statusByStep['assets-sync'], - $totalVendorWarnings - )); + $totalVendorWarnings = moduleCliVendorWarningsIgnoredSince($warningsBeforeAll); + fwrite(STDOUT, sprintf( + "module-runtime-sync: summary migrate=%s permissions-sync=%s build=%s assets-sync=%s vendor_warnings_ignored=%d\n", + $statusByStep['migrate'], + $statusByStep['permissions-sync'], + $statusByStep['build'], + $statusByStep['assets-sync'], + $totalVendorWarnings + )); - return $finalExitCode; + return $finalExitCode; + } + ); + }); } if (PHP_SAPI === 'cli' && realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === __FILE__) { diff --git a/bin/scheduler-run.php b/bin/scheduler-run.php index c5f3a28..a6ffcf8 100755 --- a/bin/scheduler-run.php +++ b/bin/scheduler-run.php @@ -3,27 +3,16 @@ declare(strict_types=1); -chdir(__DIR__ . '/..'); - -require 'vendor/autoload.php'; -require 'config/config.php'; -require 'lib/Support/helpers.php'; -$container = require 'lib/App/registerContainer.php'; -setAppContainer($container); - use MintyPHP\DB; -use MintyPHP\Http\RequestContext; use MintyPHP\Service\Audit\SystemAuditService; use MintyPHP\Service\Scheduler\SchedulerServicesFactory; +require_once __DIR__ . '/cli-bootstrap.php'; + $exitCode = 0; $startedAt = microtime(true); try { - RequestContext::start([ - 'channel' => 'scheduler', - 'method' => 'CLI', - 'path' => 'bin/scheduler-run.php', - ]); + cliBootstrapApp('scheduler', 'bin/scheduler-run.php'); $factory = app(SchedulerServicesFactory::class); $result = $factory->createSchedulerRunService()->runDueJobs(); if (!($result['ok'] ?? false)) {