diff --git a/docs/recipe/provision/provision.md b/docs/recipe/provision/provision.md index 593864ac..b583a0a3 100644 --- a/docs/recipe/provision/provision.md +++ b/docs/recipe/provision/provision.md @@ -4,7 +4,7 @@ # provision -[Source](/recipe/provision/provision.php) +[Source](/recipe/provision.php) @@ -27,19 +27,19 @@ ## Config ### php_version -[Source](/recipe/provision/provision.php#L8) +[Source](/recipe/provision.php#L8) ### sudo_password -[Source](/recipe/provision/provision.php#L9) +[Source](/recipe/provision.php#L9) ## Tasks ### provision -[Source](/recipe/provision/provision.php#L14) +[Source](/recipe/provision.php#L14) @@ -56,57 +56,57 @@ This task is group task which contains next tasks: ### provision:check -[Source](/recipe/provision/provision.php#L33) +[Source](/recipe/provision.php#L33) ### provision:upgrade -[Source](/recipe/provision/provision.php#L54) +[Source](/recipe/provision.php#L54) ### provision:install -[Source](/recipe/provision/provision.php#L60) +[Source](/recipe/provision.php#L60) ### provision:ssh -[Source](/recipe/provision/provision.php#L83) +[Source](/recipe/provision.php#L83) ### provision:user:deployer -[Source](/recipe/provision/provision.php#L97) +[Source](/recipe/provision.php#L97) ### provision:firewall -[Source](/recipe/provision/provision.php#L132) +[Source](/recipe/provision.php#L132) ### provision:install:php -[Source](/recipe/provision/provision.php#L140) +[Source](/recipe/provision.php#L140) ### provision:install:composer -[Source](/recipe/provision/provision.php#L165) +[Source](/recipe/provision.php#L165) ### provision:config:php:sessions -[Source](/recipe/provision/provision.php#L198) +[Source](/recipe/provision.php#L198) ### provision:nginx:dhparam -[Source](/recipe/provision/provision.php#L204) +[Source](/recipe/provision.php#L204) ### provision:nginx -[Source](/recipe/provision/provision.php#L215) +[Source](/recipe/provision.php#L215) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 023a304f..ec72a3f5 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -15,6 +15,7 @@ + src/Configuration diff --git a/recipe/common.php b/recipe/common.php index 368a55c1..02e755ea 100644 --- a/recipe/common.php +++ b/recipe/common.php @@ -18,8 +18,6 @@ require __DIR__ . '/deploy/update_code.php'; require __DIR__ . '/deploy/vendors.php'; require __DIR__ . '/deploy/writable.php'; -require __DIR__ . '/provision/provision.php'; - use Deployer\Exception\RunException; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\Output; diff --git a/recipe/provision/provision.php b/recipe/provision.php similarity index 100% rename from recipe/provision/provision.php rename to recipe/provision.php diff --git a/src/Command/InitCommand.php b/src/Command/InitCommand.php index c0e67794..37183862 100644 --- a/src/Command/InitCommand.php +++ b/src/Command/InitCommand.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Process\Exception\RuntimeException; use Symfony\Component\Process\Process; +use function Deployer\Support\fork; class InitCommand extends Command { @@ -27,101 +28,186 @@ class InitCommand extends Command $this ->setName('init') ->setDescription('Initialize deployer in your project') - ->addOption('template', 't', InputOption::VALUE_OPTIONAL, 'The template of you project') - ->addOption('filepath', null, InputOption::VALUE_OPTIONAL, 'The file path (default "deploy.php")', 'deploy.php'); + ->addOption('path', 'p', InputOption::VALUE_OPTIONAL, 'Recipe path'); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { - /** @var FormatterHelper $formatter */ - $formatter = $this->getHelper('formatter'); - $initializer = new Initializer(); - $template = $input->getOption('template'); - $filepath = $input->getOption('filepath'); + $io = new SymfonyStyle($input, $output); + $recipePath = $input->getOption('path'); - if (file_exists($filepath)) { - $output->writeln([ - $formatter->formatBlock( - sprintf('The file "%s" already exist.', $filepath), - 'bg=red;fg=white', true - ), - ]); - return 2; - } - - $project = 'my_project'; - $repository = ''; - $hosts = []; - $allow = true; - - if ($template === null) { - $io = new SymfonyStyle($input, $output); - - // Welcome message - $output->writeln(" - _____ _ - | __ \ | | - | | | | ___ _ __ | | ___ _ _ ___ _ __ - | | | |/ _ \ '_ \| |/ _ \| | | |/ _ \ '__| - | |__| | __/ |_) | | (_) | |_| | __/ | - |_____/ \___| .__/|_|\___/ \__, |\___|_| - | | __/ | - |_| |___/ + // Welcome message + $output->write(" + \e[38;2;94;231;223m╔\e[39m\e[38;2;95;230;227m╦\e[39m\e[38;2;96;230;230m╗\e[39m\e[38;2;97;226;230m┌\e[39m\e[38;2;98;221;229m─\e[39m\e[38;2;99;217;228m┐\e[39m\e[38;2;100;213;228m┌\e[39m\e[38;2;101;209;227m─\e[39m\e[38;2;102;205;227m┐\e[39m\e[38;2;103;202;226m┬\e[39m \e[38;2;104;198;226m┌\e[39m\e[38;2;105;194;225m─\e[39m\e[38;2;106;191;225m┐\e[39m\e[38;2;107;187;224m┬\e[39m \e[38;2;108;184;224m┬\e[39m\e[38;2;109;180;223m┌\e[39m\e[38;2;110;177;223m─\e[39m\e[38;2;110;174;222m┐\e[39m\e[38;2;111;171;222m┬\e[39m\e[38;2;112;168;221m─\e[39m\e[38;2;113;165;221m┐\e[39m + \e[38;2;114;162;220m║\e[39m\e[38;2;115;159;220m║\e[39m\e[38;2;116;157;219m├\e[39m\e[38;2;117;154;219m┤\e[39m \e[38;2;118;151;218m├\e[39m\e[38;2;119;149;218m─\e[39m\e[38;2;119;147;217m┘\e[39m\e[38;2;120;144;217m│\e[39m \e[38;2;121;142;216m│\e[39m \e[38;2;122;140;216m│\e[39m\e[38;2;123;138;215m└\e[39m\e[38;2;124;136;215m┬\e[39m\e[38;2;125;134;214m┘\e[39m\e[38;2;125;132;214m├\e[39m\e[38;2;126;130;213m┤\e[39m \e[38;2;127;129;213m├\e[39m\e[38;2;129;128;212m┬\e[39m\e[38;2;132;129;212m┘\e[39m + \e[38;2;135;130;211m═\e[39m\e[38;2;138;130;211m╩\e[39m\e[38;2;141;131;210m╝\e[39m\e[38;2;144;132;210m└\e[39m\e[38;2;147;133;209m─\e[39m\e[38;2;150;134;209m┘\e[39m\e[38;2;152;134;208m┴\e[39m \e[38;2;155;135;208m┴\e[39m\e[38;2;158;136;207m─\e[39m\e[38;2;160;137;207m┘\e[39m\e[38;2;162;137;206m└\e[39m\e[38;2;165;138;206m─\e[39m\e[38;2;167;139;205m┘\e[39m \e[38;2;169;140;205m┴\e[39m \e[38;2;171;140;204m└\e[39m\e[38;2;173;141;204m─\e[39m\e[38;2;175;142;203m┘\e[39m\e[38;2;177;143;203m┴\e[39m\e[38;2;178;143;202m└\e[39m\e[38;2;180;144;202m─\e[39m + + \e[38;2;94;231;223m█\e[39m\e[38;2;95;230;227m█\e[39m\e[38;2;97;228;230m█\e[39m\e[38;2;98;222;229m█\e[39m\e[38;2;99;217;228m█\e[39m\e[38;2;100;212;228m█\e[39m\e[38;2;102;207;227m█\e[39m\e[38;2;103;202;227m█\e[39m\e[38;2;104;197;226m█\e[39m\e[38;2;105;193;225m█\e[39m\e[38;2;106;188;225m█\e[39m\e[38;2;108;184;224m█\e[39m\e[38;2;109;180;223m█\e[39m\e[38;2;110;176;223m█\e[39m\e[38;2;111;172;222m█\e[39m\e[38;2;112;168;222m█\e[39m\e[38;2;113;164;221m█\e[39m\e[38;2;115;161;220m█\e[39m\e[38;2;116;157;220m█\e[39m\e[38;2;117;154;219m█\e[39m\e[38;2;118;151;218m█\e[39m\e[38;2;119;148;218m█\e[39m\e[38;2;120;145;217m█\e[39m\e[38;2;121;142;216m█\e[39m\e[38;2;122;139;216m█\e[39m\e[38;2;123;137;215m█\e[39m\e[38;2;124;134;215m█\e[39m\e[38;2;126;132;214m█\e[39m\e[38;2;127;130;213m█\e[39m\e[38;2;128;128;213m█\e[39m\e[38;2;132;129;212m█\e[39m\e[38;2;136;130;211m█\e[39m\e[38;2;139;131;211m█\e[39m\e[38;2;143;132;210m█\e[39m\e[38;2;147;133;210m█\e[39m\e[38;2;150;134;209m█\e[39m\e[38;2;153;135;208m█\e[39m\e[38;2;157;136;208m█\e[39m\e[38;2;160;137;207m█\e[39m\e[38;2;163;138;206m█\e[39m\e[38;2;166;138;206m█\e[39m\e[38;2;168;139;205m█\e[39m\e[38;2;171;140;205m█\e[39m\e[38;2;173;141;204m█\e[39m\e[38;2;176;142;203m█\e[39m\e[38;2;178;143;203m█\e[39m\e[38;2;180;144;202m█\e[39m "); - $io->text([ - 'Welcome to the Deployer config generator.', - 'This utility will walk you through creating a deploy.php file.', - '', - 'Press ^C at any time to quit.', - ]); + $io->text([ + 'Welcome to the Deployer config generator.', + '', + 'Press ^C at any time to quit.', + ]); - // Yes? - $io->confirm('Continue?'); + // Yes? + $language = $io->choice('Select recipe language', ['php', 'yaml'], 'php'); + if (empty($recipePath)) { + $recipePath = "deploy.$language"; + } - // Template - $recipes = $initializer->getRecipes(); - $template = $io->choice('Select project template', $recipes, 'common'); + // Template + $template = $io->choice('Select project template', $this->recipes(), 'common'); - // Repo - $default = false; - try { - $process = Process::fromShellCommandline('git remote get-url origin'); - $default = $process->mustRun()->getOutput(); - $default = trim($default); - } catch (RuntimeException $e) { - } - $repository = $io->ask('Repository', $default); + // Repo + $default = false; + try { + $process = Process::fromShellCommandline('git remote get-url origin'); + $default = $process->mustRun()->getOutput(); + $default = trim($default); + } catch (RuntimeException $e) { + } + $repository = $io->ask('Repository', $default); - // Project - $default = false; - try { - $process = Process::fromShellCommandline('basename "$PWD"'); - $default = $process->mustRun()->getOutput(); - $default = trim($default); - } catch (RuntimeException $e) { - } - $project = $io->ask('Project name', $default); - - // Hosts - $host = null; - if (preg_match('/github.com:(?[A-Za-z0-9_\.\-]+)\//', $repository, $m)) { + // Guess host + if (preg_match('/github.com:(?[A-Za-z0-9_.\-]+)\//', $repository, $m)) { + $org = $m['org']; + $tempHostFile = tempnam(sys_get_temp_dir(), 'temp-host-file'); + fork(function () use ($org, $tempHostFile) { try { - ['blog' => $blog] = Httpie::get('https://api.github.com/orgs/' . $m['org'])->getJson(); + ['blog' => $blog] = Httpie::get('https://api.github.com/orgs/' . $org)->getJson(); $host = parse_url($blog, PHP_URL_HOST); + file_put_contents($tempHostFile, $host); } catch (\Throwable $e) { // ¯\_(ツ)_/¯ } - } - $hosts = explode(',', $io->ask('Hosts (comma separated)', $host)); + }); } - file_put_contents($filepath, $initializer->getTemplate($template, $project, $repository, $hosts, $allow)); + // Project + $default = false; + try { + $process = Process::fromShellCommandline('basename "$PWD"'); + $default = $process->mustRun()->getOutput(); + $default = trim($default); + } catch (RuntimeException $e) { + } + $project = $io->ask('Project name', $default); + + // Hosts + $host = null; + if (isset($tempHostFile)) { + $host = file_get_contents($tempHostFile); + } + $hosts = explode(',', $io->ask('Hosts (comma separated)', $host)); + + file_put_contents($recipePath, $this->$language($template, $project, $repository, $hosts)); + $this->telemetry(); $output->writeln(sprintf( 'Successfully created %s', - $filepath + $recipePath )); return 0; } + + private function php(string $template, string $project, string $repository, array $hosts): string + { + $h = ""; + foreach ($hosts as $host) { + $h .= "host('{$host}');\n"; + } + + return <<isDot()) { + continue; + } + if ($fileinfo->isDir()) { + continue; + } + + $recipe = pathinfo($fileinfo->getFilename(), PATHINFO_FILENAME); + + if ($recipe === 'README') { + continue; + } + + $recipes[] = $recipe; + } + + sort($recipes); + return $recipes; + } } diff --git a/src/Component/Initializer/Initializer.php b/src/Component/Initializer/Initializer.php deleted file mode 100644 index 38b7595f..00000000 --- a/src/Component/Initializer/Initializer.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Deployer\Component\Initializer; - -use function Deployer\cd; -use function Deployer\run; -use function Deployer\task; - -class Initializer -{ - public function getRecipes() - { - $recipes = []; - $dir = new \DirectoryIterator(__DIR__ . '/../../../recipe'); - foreach ($dir as $fileinfo) { - if ($fileinfo->isDot()) { - continue; - } - if ($fileinfo->isDir()) { - continue; - } - - $recipe = pathinfo($fileinfo->getFilename(), PATHINFO_FILENAME); - - if ($recipe === 'README') { - continue; - } - - $recipes[] = $recipe; - } - - sort($recipes); - return $recipes; - } - - public function getTemplate(string $template, string $project, string $repository, array $hosts, bool $allow): string - { - $h = ""; - foreach ($hosts as $host) { - $h .= "host('{$host}');\n"; - } - - $dontTrack = $allow ? '' : "define('DONT_TRACK', 'ಠ_ಠ');\n"; - - return << $value) { if (!$predicate($value, $key)) { @@ -131,21 +117,14 @@ function array_all(array $array, $predicate) /** * Cleanup CRLF new line endings. - * Issue #2111 - * - * @param $string - * @return string */ -function normalize_line_endings($string) +function normalize_line_endings(string $string): string { return str_replace(["\r\n", "\r"], "\n", $string); } /** * Expand leading tilde (~) symbol in given path. - * - * @param string $path - * @return string */ function parse_home_dir(string $path): string { @@ -163,3 +142,22 @@ function parse_home_dir(string $path): string return $path; } + +function fork(callable $callable) +{ + $pid = null; + // Make sure function is not disabled via php.ini "disable_functions" + if (extension_loaded('pcntl') && function_exists('pcntl_fork')) { + declare(ticks = 1); + $pid = pcntl_fork(); + } + if (is_null($pid) || $pid === -1) { + // Fork fails or there is no `pcntl` extension. + $callable(); + } elseif ($pid === 0) { + // Child process. + posix_setsid(); + $callable(); + exit(0); + } +}