From 7bc8720377bcd05b4f48988e658388c5ce0cc7a3 Mon Sep 17 00:00:00 2001 From: Brock H Caldwell Date: Fri, 16 May 2025 13:15:28 -0500 Subject: [PATCH] fix: provisions DB on container startup --- Dockerfile.prod | 3 + bash/entrypoint.sh | 15 +++++ composer.json | 1 + composer.lock | 58 ++++++++++++++++++- src/Command/ProvisionCommand.php | 58 +++++++++++++++++++ .../Controller/Web/RegistrationController.php | 15 ++++- .../AddPreferencesToDatabase.php | 36 ++++++++++++ .../GettingStarted/GettingStartedInput.php | 16 +++++ .../GettingStarted/MigrateDatabase.php | 31 ++++++++++ 9 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 bash/entrypoint.sh create mode 100644 src/Command/ProvisionCommand.php create mode 100644 src/User/Framework/Pipeline/GettingStarted/AddPreferencesToDatabase.php create mode 100644 src/User/Framework/Pipeline/GettingStarted/GettingStartedInput.php create mode 100644 src/User/Framework/Pipeline/GettingStarted/MigrateDatabase.php diff --git a/Dockerfile.prod b/Dockerfile.prod index 1f906e9..c0c0bf2 100644 --- a/Dockerfile.prod +++ b/Dockerfile.prod @@ -7,5 +7,8 @@ RUN apt-get update && \ docker-php-ext-install ldap COPY --chown=www-data:www-data . /var/www +COPY --chmod=0775 ./bash/entrypoint.sh /usr/local/bin/ COPY ./bash/vhost.conf /etc/apache2/sites-enabled/vhost.conf RUN rm /etc/apache2/sites-enabled/000-default.conf + +ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ] diff --git a/bash/entrypoint.sh b/bash/entrypoint.sh new file mode 100644 index 0000000..14229ec --- /dev/null +++ b/bash/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Sleep for a second to ensure DB is awake and ready +SLEEP_TIME=$(shuf -i 2-5 -n 1) +echo "> Sleeping for ${SLEEP_TIME} seconds to wait for the database" +echo "> If there are errors after the migration runs, it's possible another container (scheduler, worker, etc.) already ran the migrations" +sleep $SLEEP_TIME + +# Provision database +php /var/www/bin/console doctrine:migrations:migrate --no-interaction +php /var/www/bin/console doctrine:fixtures:load --no-interaction + +# Start Apache in the foreground +echo "Starting Apache..." +exec apachectl -D FOREGROUND diff --git a/composer.json b/composer.json index 6d96fe8..cc85ff2 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ "doctrine/doctrine-migrations-bundle": "^3.4", "doctrine/orm": "^3.3", "dragonmantank/cron-expression": "^3.4", + "league/pipeline": "^1.1", "nesbot/carbon": "^3.9", "nihilarr/parse-torrent-name": "^0.0.1", "nyholm/psr7": "*", diff --git a/composer.lock b/composer.lock index 2a0fd52..808fe59 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "06913c92f22c0b45934c395138318bb4", + "content-hash": "33f1579a34e7ada02bb4738a9b39f493", "packages": [ { "name": "1tomany/rich-bundle", @@ -1792,6 +1792,62 @@ ], "time": "2025-01-26T21:29:45+00:00" }, + { + "name": "league/pipeline", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/pipeline.git", + "reference": "9069ddfdbd5582f8a563e00cffdbeffb9a0acd01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/pipeline/zipball/9069ddfdbd5582f8a563e00cffdbeffb9a0acd01", + "reference": "9069ddfdbd5582f8a563e00cffdbeffb9a0acd01", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0 || ^10.0 || ^11.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net", + "role": "Author" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "role": "Maintainer" + } + ], + "description": "A plug and play pipeline implementation.", + "keywords": [ + "composition", + "design pattern", + "pattern", + "pipeline", + "sequential" + ], + "support": { + "issues": "https://github.com/thephpleague/pipeline/issues", + "source": "https://github.com/thephpleague/pipeline/tree/1.1.0" + }, + "time": "2025-02-06T08:48:15+00:00" + }, { "name": "nesbot/carbon", "version": "3.9.1", diff --git a/src/Command/ProvisionCommand.php b/src/Command/ProvisionCommand.php new file mode 100644 index 0000000..c1d9843 --- /dev/null +++ b/src/Command/ProvisionCommand.php @@ -0,0 +1,58 @@ +preferencesRepository = $preferencesRepository; + $this->logger = $logger; + $this->kernel = $kernel; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $pipelineInput = new GettingStartedInput( + kernel: $this->kernel, + preferenceRepository: $this->preferencesRepository, + logger: $this->logger, + ); + + $pipeline = (new Pipeline) + ->pipe(new MigrateDatabase) + ->pipe(new AddPreferencesToDatabase); + + $pipeline->process($pipelineInput); + + $io->success('You have a new command! Now make it your own! Pass --help to see your options.'); + + return Command::SUCCESS; + } +} diff --git a/src/User/Framework/Controller/Web/RegistrationController.php b/src/User/Framework/Controller/Web/RegistrationController.php index 6f4135a..6d1531e 100644 --- a/src/User/Framework/Controller/Web/RegistrationController.php +++ b/src/User/Framework/Controller/Web/RegistrationController.php @@ -6,10 +6,19 @@ use App\User\Action\Command\RegisterUserCommand; use App\User\Action\Handler\RegisterUserHandler; use App\User\Framework\Entity\User; use App\User\Framework\Form\RegistrationFormType; +use App\User\Framework\Pipeline\GettingStarted\AddPreferencesToDatabase; +use App\User\Framework\Pipeline\GettingStarted\GettingStartedInput; +use App\User\Framework\Pipeline\GettingStarted\MigrateDatabase; +use App\User\Framework\Repository\PreferencesRepository; +use App\User\Framework\Repository\UserRepository; +use Doctrine\Common\Collections\ArrayCollection; +use League\Pipeline\Pipeline; +use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Attribute\Route; class RegistrationController extends AbstractController @@ -45,8 +54,12 @@ class RegistrationController extends AbstractController } #[Route(path: '/getting-started', name: 'app_getting_started')] - public function gettingStarted(Request $request, Security $security): Response + public function gettingStarted(Request $request, Security $security, UserRepository $userRepository, PreferencesRepository $preferencesRepository, KernelInterface $kernel, LoggerInterface $logger): Response { + if ((new ArrayCollection($userRepository->findAll()))->count() !== 0) { + return $this->redirectToRoute('app_index'); + } + $form = $this->createForm(RegistrationFormType::class, new User()); $form->handleRequest($request); diff --git a/src/User/Framework/Pipeline/GettingStarted/AddPreferencesToDatabase.php b/src/User/Framework/Pipeline/GettingStarted/AddPreferencesToDatabase.php new file mode 100644 index 0000000..4d2cff4 --- /dev/null +++ b/src/User/Framework/Pipeline/GettingStarted/AddPreferencesToDatabase.php @@ -0,0 +1,36 @@ +preferenceRepository->count() > 0) { + $input->logger->info('[AddPreferencesToDatabase] > Preferences already exist, skipping...'); + return $input; + } + + $app = new Application($input->kernel); + $app->setAutoExit(false); + + $commandInput = new ArrayInput([ + 'command' => 'doctrine:fixtures:load', + '--no-interaction', + ]); + + $output = new BufferedOutput(); + + $app->run($commandInput, $output); + + return $input; + } +} \ No newline at end of file diff --git a/src/User/Framework/Pipeline/GettingStarted/GettingStartedInput.php b/src/User/Framework/Pipeline/GettingStarted/GettingStartedInput.php new file mode 100644 index 0000000..e8cbd7c --- /dev/null +++ b/src/User/Framework/Pipeline/GettingStarted/GettingStartedInput.php @@ -0,0 +1,16 @@ +kernel); + $app->setAutoExit(false); + + $commandInput = new ArrayInput([ + 'command' => 'doctrine:migrations:migrate', + '--no-interaction' => true, + ]); + + $output = new BufferedOutput(); + + $app->run($commandInput, $output); + + $input->logger->info('[MigrateDatabase] > Migrating database...', ['output' => $output->fetch()]); + + return $input; + } +} \ No newline at end of file