From 055c721ab2e11fe17d98a4b278635c0cece02465 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 7 Mar 2022 11:27:55 +0100 Subject: [PATCH] Breaking: Start working on deployer v7 --- Installer/Distribution/Defaults/deploy.php | 5 - Installer/Distribution/Defaults/deploy.yaml | 31 +++- Task/Git.php | 178 ++++++++++++++++++ Task/Server.php | 165 +++++++++++++++++ Task/Slack.php | 84 +++++++++ Utility/Hostname.php | 50 +++++ Utility/Input.php | 192 ++++++++++++++++++++ Utility/Output.php | 126 +++++++++++++ Utility/Runner.php | 44 +++++ Utility/StringHelper.php | 48 +++++ config.php | 163 +++++++---------- config.yaml | 66 +++++++ template/Neos/Settings.yaml | 2 +- template/Redis/conf | 2 +- 14 files changed, 1040 insertions(+), 116 deletions(-) delete mode 100644 Installer/Distribution/Defaults/deploy.php create mode 100644 Task/Git.php create mode 100644 Task/Server.php create mode 100644 Task/Slack.php create mode 100644 Utility/Hostname.php create mode 100644 Utility/Input.php create mode 100644 Utility/Output.php create mode 100644 Utility/Runner.php create mode 100644 Utility/StringHelper.php create mode 100644 config.yaml diff --git a/Installer/Distribution/Defaults/deploy.php b/Installer/Distribution/Defaults/deploy.php deleted file mode 100644 index 93c2b1e..0000000 --- a/Installer/Distribution/Defaults/deploy.php +++ /dev/null @@ -1,5 +0,0 @@ - $pwd])) { + writeln(''); + if (!askConfirmationInput('There are no files staged. Do you want to add all files?')) { + exit(1); + } + runLocally('git add .'); + } + + $crop = 100; + writebox( + "Line 1 will be cropped at $crop characters.
All other lines will be wrapped after $crop characters.", + null + ); + // Cropping is index based, so we need to add 2 + $crop = $crop + 2; + + $type = askChoiceln( + 'Select the type of change that you\'re committing', + $types, + array_key_first($types) + ); + writeCleanLine(); + $type .= ':'; + $short = askln('Write a short, imperative tense description of the change:', true, null, false, $type); + $long = askln('Provide a longer description of the change: (press enter to skip)'); + + $breaking = null; + if ($type !== 'Breaking:') { + $breaking = askConfirmationInput('Are there any breaking changes?', 'Describe the breaking changes:'); + } + $issues = askConfirmationInput('Does this change affect any open issues?', 'Add issue references (e.g. "fix #123", "re #123".):'); + + $output = substr("$type $short", 0, $crop); + if (is_string($long)) { + $output .= "\n\n" . wordwrap($long, $crop); + } + if (is_string($breaking)) { + $output .= "\n\n" . wordwrap("BREAKING CHANGE: $breaking", $crop); + } + if (is_string($issues)) { + $output .= "\n\n" . wordwrap($issues, $crop); + } + $output = str_replace('"', '\"', $output); + runLocally("git commit -m \"$output\"", ['cwd' => $pwd]); + + writeCleanLine(); +})->once(); + +desc('Create release tag on git'); +task('git:tag', static function (): void { + $latest = 'git describe --tags $(git rev-list --tags --max-count=1)'; + if (!testLocally($latest . '>/dev/null 2>&1')) { + $tag = askln('Please enter a tag name', true); + } else { + $latest = runLocally($latest); + $type = askChoiceln("Latest tag is $latest. Choose type of release", [ + "Patch", + "Minor", + "Major" + ]); + $prefix = ''; + // Check if $latest starts with an "v" + if (strpos($latest, 'v') === 0) { + $prefix = 'v'; + $latest = substr($latest, 1); + } + + $split = explode('.', $latest); + $patch = (int) array_pop($split); + $minor = (int) array_pop($split); + $major = (int) array_pop($split); + + switch ($type) { + case 'Patch': + $patch++; + break; + case 'Minor': + $patch = 0; + $minor++; + break; + case 'Major': + $patch = 0; + $minor = 0; + $major++; + break; + } + $tag = sprintf('%s%d.%d.%d', $prefix, $major, $minor, $patch); + } + + $gh = get('local/gh'); + + $date = (new DateTime('now', new DateTimeZone('UTC')))->format(DateTime::RFC850); + $description = askln( + 'Add a description for the tag', + false, + "Deployment on $date" + ); + runLocally("git tag -a -m '$description' '$tag'"); + runLocally('git push origin --tags'); + if ($gh) { + runLocally("$gh release create $tag --generate-notes"); + } +})->once(); + +desc('Set the know host for the SSH_KNOWN_HOSTS secret'); +task('git:ssh:know_hosts', static function (): void { + $gh = get('local/gh'); + secretFeedback('SSH_KNOWN_HOSTS', (bool)$gh); + $keys = ''; + foreach (getAllHostnames() as $hostname) { + $key = trim(runLocally("ssh-keyscan $hostname")); + $keys .= $key; + writeCleanLine("$key"); + } + var_dump(timestamp()); + + if ($gh) { + // runLocally("$gh secret set SSH_KNOWN_HOSTS --body '$keys'"); + } +})->once(); + +desc('Set the private key for SSH_PRIVATE_KEY secret and upload public key to host'); +task('git:ssh:key', static function (): void { + $gh = get('local/gh'); + runLocally('ssh-keygen -q -t rsa -b 4096 -N "" -C "Github Actions" -f __temp_ssh_key'); + $private = runLocally('cat __temp_ssh_key'); + $public = runLocally('cat __temp_ssh_key.pub'); + secretFeedback('SSH_PRIVATE_KEY', (bool)$gh); + if ($gh) { + runLocally("$gh secret set SSH_PRIVATE_KEY --body '$private'"); + } + writeln("$private"); + on(Deployer::get()->hosts, function () use ($public) { + $file = run("cat ~/.ssh/authorized_keys"); + if (strpos($file, $public) === false) { + run("echo '$public' >> ~/.ssh/authorized_keys"); + writebox('The public key was added to authorized_keys on the host {{alias}}'); + } + }); + runLocally('rm -f __temp_ssh_key __temp_ssh_key.pub'); +})->once(); + +/** + * @param string $key + * @param boolean $hasGithubCLI + * @return void + */ +function secretFeedback(string $key, bool $hasGithubCLI): void +{ + if ($hasGithubCLI) { + writebox("Follow entry was made as $key secret on github:"); + return; + } + writebox("Put this value as $key secret on github:"); +} diff --git a/Task/Server.php b/Task/Server.php new file mode 100644 index 0000000..5c074a3 --- /dev/null +++ b/Task/Server.php @@ -0,0 +1,165 @@ +Set PHP version on uberspace

Current version:
$currentVersion"); + + $availableVersions = run('uberspace tools version list php'); + $versionsList = explode(\PHP_EOL, str_replace('- ', '', $availableVersions)); + $version = askChoiceln('Please choose the desired version', $versionsList); + + if ($version !== $currentVersionShort) { + $output = run("uberspace tools version use php $version"); + writebox($output, 'bgSuccess'); + return; + } + writebox("As PHP is already set to $version,
no configuration was changed"); +}); + +desc('Add a domain to uberspace'); +task('server:domain:add', static function (): void { + writebox('Get list of domains, please wait...', null); + $currentEntry = run('uberspace web domain list'); + $alias = parse('alias'); + writebox("Add a domain to uberspace +If you have multiple domains, you will be asked +after every entry if you wand to add another domain. + +Current entry: +$currentEntry + +To cancel enter exit as answer"); + // Check if the alias seems to have a subdomain + $wwwDomain = 'www.' . $alias; + $defaultDomain = substr_count($alias, '.') > 1 ? $alias : $wwwDomain; + $suggestions = [$alias, $wwwDomain]; + $firstDomain = askDomain('Please enter the domain', $defaultDomain, $suggestions); + if ($firstDomain === 'exit') { + return; + } + $domains = [ + $firstDomain + ]; + writeln(''); + while ($domain = askDomain('Please enter another domain or press enter to continue', null, $suggestions)) { + if ($domain === 'exit') { + return; + } + if ($domain) { + $domains[] = $domain; + } + writeln(''); + } + $outputDomains = implode("\n", $domains); + $ip = ''; + writebox('Adding domains, please wait...'); + foreach ($domains as $domain) { + $ip = run("uberspace web domain add $domain"); + } + writebox("Following entries are added:

$outputDomains

$ip", 'green'); +}); + +desc('Remove a domain from uberspace'); +task('server:domain:remove', static function (): void { + writebox('Get list of domains, please wait...', null); + $currentEntry = run('uberspace web domain list'); + + if ($currentEntry == parse('{{remote_user}}.uber.space')) { + writebox('No domains to remove'); + return; + } + + writebox("Remove a domain from uberspace +If you have multiple domains, you will be asked +after every entry if you wand to remove another domain. + +Current entry: +$currentEntry + +To finish the setup, press enter or choose the last entry"); + + $currentEntriesArray = explode(\PHP_EOL, $currentEntry); + $currentEntriesArray[] = 'Finish setup'; + $domains = []; + + while ($domain = askChoiceln('Please choose the domain you want to remove', $currentEntriesArray, sizeof($currentEntriesArray) - 1)) { + if ($domain === 'Finish setup') { + break; + } + $currentEntriesArray = array_values(array_diff($currentEntriesArray, [$domain])); + $domains[] = $domain; + } + if (sizeof($domains)) { + $outputDomains = implode("\n", $domains); + writebox('Removing domains, please wait...'); + foreach ($domains as $domain) { + run("uberspace web domain del $domain"); + } + writebox('Following entries are removed:

' . $outputDomains, 'bgSuccess'); + } else { + writebox('No Domains where removed', 'error'); + } +}); + +desc('List all domains and subdomains'); +task('server:domain:list', static function (): void { + writebox('Get list of domains, please wait...', null); + $currentEntry = run('uberspace web domain list'); + writebox("Registered domains on the uberspace account \"{{remote_user}}\" + +$currentEntry"); +}); + +desc('Create and/or read the deployment key'); +task('server:ssh_key', static function (): void { + if (!test('[ -f ~/.ssh/{{ssh_key}}.pub ]')) { + // -q Silence key generation + // -t Set algorithm + // -b Specifies the number of bits in the key + // -N Set the passphrase + // -C Comment for the key + // -f Specifies name of the file in which to store the created key + run('cat /dev/zero | ssh-keygen -q -t rsa -b 4096 -N "" -C "$(hostname -f)" -f ~/.ssh/{{ssh_key}}'); + } + + // We dont use `ssh-keygen -y` because we also want to output the comment + writebox('The public key ({{ssh_key}}.pub) from {{alias}} is:'); + writeln('' . run('cat ~/.ssh/{{ssh_key}}.pub') . ''); + writeln(''); + + $sshKnowHostsFile = '~/.ssh/known_hosts'; + $repoHost = get('repository_url_parts')['host']; + + if (!test("grep -q '$repoHost' $sshKnowHostsFile")) { + run("ssh-keyscan $repoHost >> $sshKnowHostsFile"); + } +}); diff --git a/Task/Slack.php b/Task/Slack.php new file mode 100644 index 0000000..87fc04c --- /dev/null +++ b/Task/Slack.php @@ -0,0 +1,84 @@ + get('slack_title'), + 'text' => get('slack_text'), + 'color' => get('slack_color'), + 'mrkdwn_in' => ['text'], + ]; + + foreach (array_unique($slackWebhook) as $hook) { + Httpie::post($hook)->body(['attachments' => [$attachment]])->send(); + } +})->once()->hidden(); + +desc('Notifying Slack about deploy finish'); +task('slack:notify:success', static function (): void { + $slackWebhook = get('slack_webhook', false); + if (!$slackWebhook) { + return; + } + if (!is_array($slackWebhook)) { + $slackWebhook = [$slackWebhook]; + } + + $attachment = [ + 'title' => get('slack_title'), + 'text' => get('slack_success_text'), + 'color' => get('slack_success_color'), + 'mrkdwn_in' => ['text'], + ]; + + foreach (array_unique($slackWebhook) as $hook) { + Httpie::post($hook)->body(['attachments' => [$attachment]])->send(); + } +})->once()->hidden(); + + +desc('Notifying Slack about deploy failure'); +task('slack:notify:failure', static function (): void { + $slackWebhook = get('slack_webhook', false); + if (!$slackWebhook) { + return; + } + if (!is_array($slackWebhook)) { + $slackWebhook = [$slackWebhook]; + } + + $attachment = [ + 'title' => get('slack_title'), + 'text' => get('slack_failure_text'), + 'color' => get('slack_failure_color'), + 'mrkdwn_in' => ['text'], + ]; + + foreach (array_unique($slackWebhook) as $hook) { + Httpie::post($hook)->body(['attachments' => [$attachment]])->send(); + } +})->once()->hidden(); + +after('deploy:failed', 'slack:notify:failure'); diff --git a/Utility/Hostname.php b/Utility/Hostname.php new file mode 100644 index 0000000..14d3589 --- /dev/null +++ b/Utility/Hostname.php @@ -0,0 +1,50 @@ + 1 ? $alias : 'www.' . $alias; +} + +/** + * Returns all domains + * + * @return array + */ +function getAllDomains(): array +{ + $hostnames = []; + on(Deployer::get()->hosts, function () use (&$hostnames) { + $hostnames[] = get('alias'); + }); + return array_unique($hostnames); +} + +/** + * Returns all hostnames + * + * @return array + */ +function getAllHostnames(): array +{ + $hostnames = []; + on(Deployer::get()->hosts, function ($host) use (&$hostnames) { + $hostnames[] = $host->get('hostname'); + }); + return array_unique($hostnames); +} diff --git a/Utility/Input.php b/Utility/Input.php new file mode 100644 index 0000000..8a905b9 --- /dev/null +++ b/Utility/Input.php @@ -0,0 +1,192 @@ + 1 ? $realDomain : $wwwDomain; + $suggestions = [$realDomain, $wwwDomain, $previewDomain]; + return askDomain($question, $defaultDomain, $suggestions); +} + +/** + * Ask the user for confirmation, if true ask second question + * + * @param string $question + * @param string|null $questionIfTrue + * @param boolean $default + * @param boolean $required + * @return bool|string + */ +function askConfirmationInput(string $question, ?string $questionIfTrue = null, bool $default = false, bool $required = false) +{ + $question = parse($question); + if (isset($questionIfTrue)) { + $questionIfTrue = parse($questionIfTrue); + } + $q1Length = getLength($question) + 6; + $q2Length = getLength($questionIfTrue); + $placeholderQ1 = $q1Length < $q2Length ? $q2Length - $q1Length : 0; + $placeholderQ2 = $q1Length > $q2Length ? $q1Length - $q2Length : 0; + + $answer = askConfirmation(" $question " . str_repeat(' ', $placeholderQ1), $default); + if ($answer === false) { + writeCleanLine(" No \n"); + return false; + } + if (!isset($questionIfTrue)) { + writeCleanLine(" Yes \n"); + return true; + } + return askln($questionIfTrue . str_repeat(' ', $placeholderQ2), $required); +} + +/** + * Ask the user for input + * + * @param string $question + * @param boolean $required + * @param string|null $default + * @param boolean $hidden + * @return string|null + */ +function askln(string $question, bool $required = false, ?string $default = null, bool $hidden = false, string $prefix = ''): ?string +{ + if (is_string($default)) { + $default = parse($default); + } + + if (strlen($prefix)) { + $prefix = " $prefix "; + } + + if ($required === true) { + $answer = null; + while ($answer === null) { + writeCleanLine(" $question "); + $answer = $hidden ? askHiddenResponse($prefix) : _ask($prefix, $default); + } + writeCleanLine(); + return $answer; + } + writeCleanLine(" $question "); + $answer = $hidden ? askHiddenResponse($prefix) : _ask($prefix, $default); + writeCleanLine(); + return $answer; +} + +/** + * @param string $message + * @param string[] $availableChoices + * @param string|int|null $default + * @param bool|false $multiselect + * @return string|string[] + * @codeCoverageIgnore + */ +function askChoiceln(string $message, array $availableChoices, $default = null, bool $multiselect = false) +{ + Context::required(__FUNCTION__); + $message = parse($message); + if (empty($availableChoices)) { + throw new InvalidArgumentException('Available choices should not be empty'); + } + + if ($default !== null && !array_key_exists($default, $availableChoices)) { + throw new InvalidArgumentException('Default choice is not available'); + } + + if (output()->isQuiet()) { + if ($default === null) { + $default = key($availableChoices); + } + return [$default => $availableChoices[$default]]; + } + + if (Deployer::isWorker()) { + return Deployer::proxyCallToMaster(currentHost(), __FUNCTION__, ...func_get_args()); + } + + /** @var QuestionHelper */ + $helper = Deployer::get()->getHelper('question'); + $message = " $message" . (($default === null) ? "" : " ($default)") . " "; + $length = getLength($message); + $placeholder = '' . str_repeat(' ', $length) . ''; + + writeCleanLine($placeholder); + writeCleanLine($message); + $question = new ChoiceQuestion($placeholder, $availableChoices, $default); + $question->setMultiselect($multiselect); + + return $helper->ask(input(), output(), $question); +} + + +function _ask(string $message, ?string $default = null, ?array $autocomplete = null): ?string +{ + // if (defined('DEPLOYER_NO_ASK')) { + // throw new WillAskUser($message); + // } + // Context::required(__FUNCTION__); + + if (output()->isQuiet()) { + return $default; + } + + if (Deployer::isWorker()) { + return Deployer::proxyCallToMaster(currentHost(), __FUNCTION__, ...func_get_args()); + } + + /** @var QuestionHelper */ + $helper = Deployer::get()->getHelper('question'); + + $tag = currentHost()->getTag(); + $message = parse($message); + $message = "$message " . (($default === null) ? "" : "(default: $default) "); + + $question = new Question($message, $default); + if (!empty($autocomplete)) { + $question->setAutocompleterValues($autocomplete); + } + + return $helper->ask(input(), output(), $question); +} diff --git a/Utility/Output.php b/Utility/Output.php new file mode 100644 index 0000000..20849d0 --- /dev/null +++ b/Utility/Output.php @@ -0,0 +1,126 @@ + gets printed bold,
/
create a linebreak + * @param string|null The type of the box. + * @return void + */ +function writebox(string $content, ?string $type = 'bgInfo'): void +{ + $background = null; + $color = null; + + switch (strtolower($type)) { + case 'info': + $color = 'blue'; + break; + case 'success': + $color = 'green'; + break; + case 'warning': + $color = 'yellow'; + break; + case 'error': + $color = 'red'; + break; + case 'bginfo': + $background = 'blue'; + $color = 'white'; + break; + case 'bgsuccess': + $background = 'green'; + $color = 'black'; + break; + case 'bgwarning': + $background = 'yellow'; + $color = 'black'; + break; + case 'bgerror': + $background = 'red'; + $color = 'white'; + break; + } + + // Parse content + $content = parse($content); + + // Replace strong with bold notation + if (isset($background)) { + $content = str_replace( + ['', ''], + ["", ''], + $content + ); + } elseif (isset($color)) { + $content = str_replace( + ['', ''], + ["", ''], + $content + ); + } else { + $content = str_replace( + ['', ''], + ["", ''], + $content + ); + } + + // Replace br tags with a linebreak + $contentArray = preg_split('/(]*>|\n)/i', $content); + $contents = []; + $maxLength = 0; + foreach ($contentArray as $key => $string) { + $length = getLength($string); + $contents[$key] = compact('length', 'string'); + if ($length > $maxLength) { + $maxLength = $length; + } + } + $placeholder = str_repeat(' ', $maxLength); + + writeCleanLine(); + writeCleanLine($placeholder, $color, $background); + foreach ($contents as $array) { + $space = str_repeat(' ', $maxLength - $array['length']); + writeCleanLine($array['string'] . $space, $color, $background); + } + writeCleanLine($placeholder, $color, $background); + writeCleanLine(); +} + + +/** + * Write line with optional colors + * + * @param string|null $content + * @param string|null $background + * @param string|null $color + * @return void + */ +function writeCleanLine( + ?string $content = null, + ?string $color = null, + ?string $background = null +): void { + if (!$content) { + $content = ' '; + } + + $content = " $content "; + + if (isset($background)) { + $content = "$content"; + } elseif (isset($color)) { + $content = "$content"; + } + output()->writeln($content); +} diff --git a/Utility/Runner.php b/Utility/Runner.php new file mode 100644 index 0000000..676408b --- /dev/null +++ b/Utility/Runner.php @@ -0,0 +1,44 @@ +/dev/null 2>&1')) { + return trim(runLocally($command)); + } + + return null; +} + +/** + * Run a interactive shell on the server + * + * @param string $command + * @return void + */ +function ttyRun(string $command): void +{ + $command = parse("VISUAL={{editor}} $command"); + $host = currentHost(); + $connectionString = $host->getConnectionString(); + $ssh = ['ssh', '-A', '-tt', $connectionString, $command]; + $process = new Process($ssh); + $process->setTimeout(null)->setIdleTimeout(null)->setTty(true); + $process->run(); +} diff --git a/Utility/StringHelper.php b/Utility/StringHelper.php new file mode 100644 index 0000000..ed892a1 --- /dev/null +++ b/Utility/StringHelper.php @@ -0,0 +1,48 @@ + $database) { - $array[$database] = $start + $index; - } - } - return $array; +set('local_pwd', static function (): string { + return runLocally('echo $PWD'); }); -// Composer specific -set('composer_options', '{{composer_action}} --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader'); +set('local/gh', static function (): ?string { + return whichLocally('gh'); +}); -// Git specifc values set('bin/git', static function (): string { - return 'GIT_SSH_COMMAND="ssh -i ~/.ssh/' . get('ssh_key') . '" ' . locateBinaryPath('git'); + return 'GIT_SSH_COMMAND="ssh -i ~/.ssh/' . get('ssh_key') . '" ' . which('git'); }); set('repository_url_parts', static function (): array { @@ -88,54 +49,63 @@ return 'https://' . get('repository_url_parts')['host'] . '/' . get('repository_url_parts')['path']; }); -set('deploy_user', static function (): string { - $user = getenv('GIT_AUTHOR_NAME'); - if ($user === false) { - $user = getenv('GIT_COMMITTER_NAME'); - if ($user === false) { - $getUserCommand = 'git config --get user.name'; - if (!testLocally("$getUserCommand 2>/dev/null || true")) { - $user = runLocally($getUserCommand); - } else { - $user = get('user'); - } - } +set('stage', static function (): ?string { + $labels = get('labels'); + if (isset($labels) && $labels['stage']) { + return $labels['stage']; } - return $user; + return null; }); -set('git_commit_types', [ - 'Fix' => 'A bug fix', - 'Update' => 'A backwards-compatible enhancement', - 'Breaking' => 'A backwards-incompatible enhancement', - 'Docs' => 'Documentation change', - 'Build' => 'Build process update', - 'New' => 'A new feature implementation', - 'Upgrade' => 'Dependency upgrade', - 'Chore' => 'Other changes (e.g.: refactoring)', -]); - -// Connection specifc values -set('port', 22); -set('forwardAgent', false); -set('multiplexing', true); -set('ssh_key', get('repository_short_name')); - -// Server specifc values -set('editor', 'nano'); -set('html_path', '/var/www/virtual/{{user}}'); -set('deploy_path', '{{html_path}}/{{deploy_folder}}'); -set('db_backup_folder', '{{deploy_path}}/.dep/databases/dumps'); -set('db_backup_keep_dumps', 5); - set('deploy_folder', static function (): string { $suffix = ''; - if (has('stage')) { - $suffix = "/" . ucfirst(get('stage')); + $stage = get('stage'); + if (isset($stage)) { + $suffix = "/" . ucfirst($stage); } return get('repository_short_name') . $suffix; }); +set('deploy_user', static function (): string { + $user = getenv('GIT_AUTHOR_NAME') || getenv('GIT_COMMITTER_NAME'); + if ($user !== false) { + return $user; + } + + $getUserCommand = 'git config --get user.name'; + if (!testLocally("$getUserCommand 2>/dev/null || true")) { + $user = runLocally($getUserCommand); + if ($user !== 'DDEV-Local User') { + return $user; + } + } + return get('remote_user'); +}); + +set('db_name', static function (): string { + try { + $yaml = run('{{flow_command}} configuration:show --type Settings --path Neos.Flow.persistence.backendOptions'); + return Yaml::parse($yaml)['dbname']; + } catch (RuntimeException $e) { + $stage = get('stage'); + $name = has('database') ? '{{database}}' : camelCaseToSnakeCase(get('repository_short_name')) . '_neos'; + $suffix = !has('database') && $stage ? '_' . camelCaseToSnakeCase($stage) : ''; + return parse('{{remote_user}}_' . $name . $suffix); + } +}); + +set('redis_databases_with_numbers', static function (): array { + $start = get('redis_start_db_number', 2); + $databases = get('redis_databases', false); + $array = []; + if (is_array($databases)) { + foreach ($databases as $index => $database) { + $array[$database] = $start + $index; + } + } + return $array; +}); + set('db_password', static function (): string { return run('my_print_defaults client | grep -Po "password=\K(\S)*"'); }); @@ -144,15 +114,6 @@ return run('date +"%Y-%m-%d__%H-%M-%S"'); }); -// Slack specifc values set('slack_application', static function (): string { - return get('application', getRealHostname()); + return get('application', '{{alias}}'); }); -set('slack_title', '{{slack_application}} (Neos)'); -set('slack_text', '_{{deploy_user}}_ deploying *{{repository_short_name}}* on `{{branch}}` to *{{target}}*'); -set('slack_success_text', 'Deploy from *{{repository_short_name}}* to *{{target}}* successful'); -set('slack_failure_text', 'Deploy from *{{repository_short_name}}* to *{{target}}* failed'); - -set('slack_color', '#4d91f7'); -set('slack_success_color', '#00c100'); -set('slack_failure_color', '#ff0909'); diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..52596ce --- /dev/null +++ b/config.yaml @@ -0,0 +1,66 @@ +import: + - recipe/common.php + - Build/Uberspace.Deployer/config.php + +config: + # Server specifc values + editor: 'vim' + html_path: '/var/www/virtual/{{remote_user}}' + deploy_path: '{{html_path}}/{{deploy_folder}}' + db_backup_folder: '{{deploy_path}}/.dep/databases/dumps' + db_backup_keep_dumps: 5 + http_user: '{{remote_user}}' + http_group: '{{remote_user}}' + + # Connection specifc values + port: 22 + forwardAgent: false + multiplexing: true + ssh_key: '{{repository_short_name}}' + + # Flow specifc values + flow_context: Production/Live + flow_command: 'FLOW_CONTEXT={{flow_context}} {{bin/php}} -d memory_limit=8G {{release_or_current_path}}/flow' + shared_dirs: + - 'Data/Persistent' + - 'Data/Logs' + - 'Configuration' + + # To disable the upload you can set this to false: upload_assets_folder: false; + # Mostly used for rendered CSS & JS files, who you don't want in your repository + upload_assets_folder: + - 'DistributionPackages/*/Resources/Private/Templates/InlineAssets' + - 'DistributionPackages/*/Resources/Public/Scripts' + - 'DistributionPackages/*/Resources/Public/Styles' + + # Redis specfic values + redis_start_db_number: 2 + redis_defaultLifetime: 0 + redis_databases: + - Flow_Mvc_Routing_Route + - Flow_Mvc_Routing_Resolve + - Neos_Fusion_Content + - Flow_Session_MetaData + - Flow_Session_Storage + - Neos_Media_ImageSize + - Flow_Security_Cryptography_HashService + + # git specfic values + git_commit_types: + Fix: 'A bug fix' + Update: 'A backwards-compatible enhancement' + Breaking: 'A backwards-incompatible enhancement' + Docs: 'Documentation change' + Build: 'Build process update' + New: 'A new feature implementation' + Upgrade: 'Dependency upgrade' + Chore: 'Other changes (e.g.: refactoring)' + + # Slack notification + slack_title: '{{slack_application}} (Neos)' + slack_text: '_{{deploy_user}}_ deploying *{{repository_short_name}}* on `{{branch}}` to *{{target}}*' + slack_success_text: 'Deploy from *{{repository_short_name}}* to *{{target}}* successful' + slack_failure_text: 'Deploy from *{{repository_short_name}}* to *{{target}}* failed' + slack_color: '#4d91f7' + slack_success_color: '#00c100' + slack_failure_color: '#ff0909' diff --git a/template/Neos/Settings.yaml b/template/Neos/Settings.yaml index 5db40ab..9e2e542 100644 --- a/template/Neos/Settings.yaml +++ b/template/Neos/Settings.yaml @@ -10,6 +10,6 @@ Neos: backendOptions: driver: pdo_mysql dbname: '{{db_name}}' - user: '{{user}}' + user: '{{remote_user}}' password: '{{db_password}}' host: localhost diff --git a/template/Redis/conf b/template/Redis/conf index 370a583..8b8b27a 100644 --- a/template/Redis/conf +++ b/template/Redis/conf @@ -1,4 +1,4 @@ -unixsocket /home/{{user}}/.redis/sock +unixsocket /home/{{remote_user}}/.redis/sock daemonize no port 0 save "" \ No newline at end of file