Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eeb2c016f7 | |||
|
|
5151b22dc2 | ||
|
|
dc3c80a2a9 |
@ -13,7 +13,7 @@ insert_final_newline = true
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
# TS/JS-Files
|
# TS/JS-Files
|
||||||
[*.{ts,js,es6}]
|
[*.{ts,js}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
# JSON-Files
|
# JSON-Files
|
||||||
@ -21,14 +21,23 @@ indent_size = 2
|
|||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
# ReST-Files
|
# ReST-Files
|
||||||
[*.rst]
|
[*.{rst,rst.txt}]
|
||||||
indent_size = 3
|
indent_size = 4
|
||||||
|
max_line_length = 80
|
||||||
|
|
||||||
|
# Markdown-Files
|
||||||
|
[*.md]
|
||||||
max_line_length = 80
|
max_line_length = 80
|
||||||
|
|
||||||
# YAML-Files
|
# YAML-Files
|
||||||
[*.{yaml,yml}]
|
[*.{yaml,yml}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
# NEON-Files
|
||||||
|
[*.neon]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
# package.json
|
# package.json
|
||||||
[package.json]
|
[package.json]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|||||||
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Evoweb\DeployerConfig\Config;
|
namespace Evoweb\DeployerConfig\Config;
|
||||||
|
|
||||||
use Deployer\Deployer;
|
|
||||||
use Deployer\Exception\Exception;
|
use Deployer\Exception\Exception;
|
||||||
use Evoweb\DeployerConfig\Tasks\Deploy;
|
use Evoweb\DeployerConfig\Tasks\Deploy;
|
||||||
use Evoweb\DeployerConfig\Tasks\Local;
|
use Evoweb\DeployerConfig\Tasks\Local;
|
||||||
@ -17,38 +16,37 @@ use function Deployer\import;
|
|||||||
use function Deployer\parse;
|
use function Deployer\parse;
|
||||||
use function Deployer\runLocally;
|
use function Deployer\runLocally;
|
||||||
use function Deployer\set;
|
use function Deployer\set;
|
||||||
use function Deployer\Support\str_contains;
|
|
||||||
use function Deployer\testLocally;
|
use function Deployer\testLocally;
|
||||||
use function Deployer\warning;
|
use function Deployer\warning;
|
||||||
|
|
||||||
class Deployment
|
class Deployment
|
||||||
{
|
{
|
||||||
|
protected array $environmentVariables = [
|
||||||
|
'CI_PROJECT_DIR',
|
||||||
|
'CI_HOST',
|
||||||
|
'ENVIRONMENT',
|
||||||
|
'INSTANCE_ID'
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->loadDeployerCommon();
|
$this->loadDeployerCommon();
|
||||||
$this->setDefaultConfiguration();
|
$this->setDefaultConfiguration();
|
||||||
$this->loadHostConfiguration();
|
$this->loadHostConfiguration();
|
||||||
$this->registerTasks();
|
$this->registerTasks();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadDeployerCommon(): void
|
protected function loadDeployerCommon(): void
|
||||||
{
|
{
|
||||||
foreach (['/../../', '/../../../', '/../../../../'] as $path) {
|
$file = realpath(__DIR__ . '/../../../../deployer/deployer/recipe/common.php');
|
||||||
$file = realpath(__DIR__ . $path . 'vendor/deployer/deployer/recipe/common.php');
|
|
||||||
if ($file && file_exists($file)) {
|
if ($file && file_exists($file)) {
|
||||||
require $file;
|
require $file;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setDefaultConfiguration(): void
|
protected function setDefaultConfiguration(): void
|
||||||
{
|
{
|
||||||
$this->set('CI_PROJECT_DIR', getEnv('CI_PROJECT_DIR'));
|
array_walk($this->environmentVariables, fn ($variable) => $this->set($variable, getEnv($variable)));
|
||||||
$this->set('CI_HOST', getEnv('CI_HOST'));
|
|
||||||
$this->set('ENVIRONMENT_NAME', getEnv('ENVIRONMENT_NAME'));
|
|
||||||
$this->set('INSTANCE_ID', getEnv('INSTANCE_ID'));
|
|
||||||
|
|
||||||
$this->set('app_container_path', '');
|
$this->set('app_container_path', '');
|
||||||
|
|
||||||
@ -195,12 +193,9 @@ class Deployment
|
|||||||
protected function loadHostConfiguration(): void
|
protected function loadHostConfiguration(): void
|
||||||
{
|
{
|
||||||
// read configuration
|
// read configuration
|
||||||
foreach (['/../../../../', '/../../../../../'] as $path) {
|
$file = realpath(__DIR__ . '/../../../../../hosts.yaml');
|
||||||
$file = realpath(__DIR__ . $path . $_ENV['ENVIRONMENT_NAME'] . '.yaml');
|
if ($file && file_exists($file)) {
|
||||||
if (file_exists($file)) {
|
|
||||||
import($file);
|
import($file);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,6 @@ use ReflectionMethod;
|
|||||||
use function Deployer\get;
|
use function Deployer\get;
|
||||||
use function Deployer\has;
|
use function Deployer\has;
|
||||||
use function Deployer\set;
|
use function Deployer\set;
|
||||||
use function Deployer\test;
|
|
||||||
use function Deployer\testLocally;
|
use function Deployer\testLocally;
|
||||||
|
|
||||||
abstract class AbstractTasks
|
abstract class AbstractTasks
|
||||||
@ -102,26 +101,4 @@ abstract class AbstractTasks
|
|||||||
{
|
{
|
||||||
return $this->has($name) && is_array($this->get($name));
|
return $this->has($name) && is_array($this->get($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getApplicationContext(): string
|
|
||||||
{
|
|
||||||
return $this->has('application_context') ?
|
|
||||||
'TYPO3_CONTEXT="' . $this->get('application_context') . '" ' :
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getSudo(): string
|
|
||||||
{
|
|
||||||
return $this->get('clear_use_sudo') ? 'sudo ' : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getTYPO3Bin(string $path, string $testPath): string
|
|
||||||
{
|
|
||||||
if (test('[ -f ' . $testPath . '/releases/{{release_name}}/vendor/bin/typo3cms ]')) {
|
|
||||||
$bin = $path . '/releases/{{release_name}}/vendor/bin/typo3cms';
|
|
||||||
} else {
|
|
||||||
$bin = $path . '/releases/{{release_name}}/vendor/bin/typo3';
|
|
||||||
}
|
|
||||||
return $bin;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,6 @@ class Deploy extends AbstractTasks
|
|||||||
'local:shared',
|
'local:shared',
|
||||||
'local:writable',
|
'local:writable',
|
||||||
'local:write_release',
|
'local:write_release',
|
||||||
'local:create_folder',
|
|
||||||
'local:vendors',
|
'local:vendors',
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -41,17 +40,21 @@ class Deploy extends AbstractTasks
|
|||||||
'local:unlock',
|
'local:unlock',
|
||||||
'deploy:success',
|
'deploy:success',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'deploy' => [
|
||||||
|
'deploy:prepare',
|
||||||
|
'deploy:publish',
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct()
|
protected function initializeTasks(): void
|
||||||
{
|
{
|
||||||
parent::__construct();
|
array_walk($this->tasks, [$this, 'registerTask']);
|
||||||
$this->registerAfterTask();
|
$this->registerAfterTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function registerAfterTask(): void
|
protected function registerAfterTask(): void
|
||||||
{
|
{
|
||||||
// [Optional] if deploy fails automatically unlock.
|
|
||||||
after('deploy:failed', 'local:unlock');
|
after('deploy:failed', 'local:unlock');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,6 @@ class Local extends AbstractTasks
|
|||||||
'local:shared',
|
'local:shared',
|
||||||
'local:writable',
|
'local:writable',
|
||||||
'local:write_release',
|
'local:write_release',
|
||||||
'local:create_folder',
|
|
||||||
'local:vendors',
|
'local:vendors',
|
||||||
'local:clear_paths',
|
'local:clear_paths',
|
||||||
'local:symlink',
|
'local:symlink',
|
||||||
@ -88,15 +87,6 @@ class Local extends AbstractTasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlocks deploy
|
|
||||||
*/
|
|
||||||
public function unlock(): void
|
|
||||||
{
|
|
||||||
// always success
|
|
||||||
runLocally("rm -f {{deploy_path}}/.dep/deploy.lock");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares release
|
* Prepares release
|
||||||
*/
|
*/
|
||||||
@ -173,43 +163,11 @@ class Local extends AbstractTasks
|
|||||||
throw new ConfigurationException("Missing 'repository' configuration.");
|
throw new ConfigurationException("Missing 'repository' configuration.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$targetWithDir = $target;
|
|
||||||
if (!empty(get('sub_directory'))) {
|
|
||||||
$targetWithDir .= ':{{sub_directory}}';
|
|
||||||
}
|
|
||||||
|
|
||||||
$bare = parse('{{deploy_path}}/.dep/repo');
|
|
||||||
$env = [
|
|
||||||
'GIT_TERMINAL_PROMPT' => '0',
|
|
||||||
'GIT_SSH_COMMAND' => get('git_ssh_command'),
|
|
||||||
];
|
|
||||||
|
|
||||||
start:
|
|
||||||
// Clone the repository to a bare repo.
|
|
||||||
runLocally("[ -d $bare ] || mkdir -p $bare");
|
|
||||||
runLocally("[ -f $bare/HEAD ] || $git clone --mirror $repository $bare 2>&1", ['env' => $env]);
|
|
||||||
|
|
||||||
// If remote url changed, drop `.dep/repo` and reinstall.
|
|
||||||
if (runLocally("cd $bare; $git config --get remote.origin.url") !== $repository) {
|
|
||||||
runLocally("rm -rf {{deploy_path}}$bare");
|
|
||||||
goto start;
|
|
||||||
}
|
|
||||||
|
|
||||||
runLocally("$git remote update 2>&1", ['env' => $env]);
|
|
||||||
|
|
||||||
// Copy to release_path.
|
// Copy to release_path.
|
||||||
if (get('update_code_strategy') === 'archive') {
|
runLocally("cd {{release_path}}; $git clone --branch $target $repository .");
|
||||||
runLocally("cd $bare; $git archive $targetWithDir | tar -x -f - -C {{release_path}} 2>&1");
|
|
||||||
} elseif (get('update_code_strategy') === 'clone') {
|
|
||||||
runLocally("cd {{release_path}}; $git clone -l $bare .");
|
|
||||||
runLocally("cd {{release_path}}; $git remote set-url origin $repository", ['env' => $env]);
|
|
||||||
runLocally("cd {{release_path}}; $git checkout --force $target");
|
|
||||||
} else {
|
|
||||||
throw new ConfigurationException(parse("Unknown `update_code_strategy` option: {{update_code_strategy}}."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save git revision in REVISION file.
|
// Save git revision in REVISION file.
|
||||||
$rev = escapeshellarg(runLocally("cd $bare; $git rev-list $target -1"));
|
$rev = escapeshellarg(runLocally("cd {{release_path}}; $git rev-list $target -1"));
|
||||||
runLocally("echo $rev > {{release_path}}/REVISION");
|
runLocally("echo $rev > {{release_path}}/REVISION");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,21 +271,23 @@ class Local extends AbstractTasks
|
|||||||
throw new \RuntimeException('Absolute path not allowed in config parameter `writable_dirs`.');
|
throw new \RuntimeException('Absolute path not allowed in config parameter `writable_dirs`.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$options = ['cwd' => $this->get('release_or_current_path')];
|
||||||
|
|
||||||
// Create directories if they don't exist
|
// Create directories if they don't exist
|
||||||
runLocally("cd {{release_or_current_path}}; mkdir -p $dirs");
|
runLocally("mkdir -p $dirs", $options);
|
||||||
|
|
||||||
if ($mode === 'chown') {
|
if ($mode === 'chown') {
|
||||||
$httpUser = get('http_user');
|
$httpUser = get('http_user');
|
||||||
// Change owner.
|
// Change owner.
|
||||||
// -L traverse every symbolic link to a directory encountered
|
// -L traverse every symbolic link to a directory encountered
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo chown -L $recursive $httpUser $dirs");
|
runLocally("$sudo chown -L $recursive $httpUser $dirs", $options);
|
||||||
} elseif ($mode === 'chgrp') {
|
} elseif ($mode === 'chgrp') {
|
||||||
// Change group ownership.
|
// Change group ownership.
|
||||||
// -L traverse every symbolic link to a directory encountered
|
// -L traverse every symbolic link to a directory encountered
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo chgrp -L $recursive {{http_group}} $dirs");
|
runLocally("$sudo chgrp -L $recursive {{http_group}} $dirs", $options);
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo chmod $recursive g+rwx $dirs");
|
runLocally("$sudo chmod $recursive g+rwx $dirs", $options);
|
||||||
} elseif ($mode === 'chmod') {
|
} elseif ($mode === 'chmod') {
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo chmod $recursive {{writable_chmod_mode}} $dirs");
|
runLocally("$sudo chmod $recursive {{writable_chmod_mode}} $dirs", $options);
|
||||||
} elseif ($mode === 'acl') {
|
} elseif ($mode === 'acl') {
|
||||||
$remoteUser = get('remote_user', false);
|
$remoteUser = get('remote_user', false);
|
||||||
if (empty($remoteUser)) {
|
if (empty($remoteUser)) {
|
||||||
@ -337,7 +297,7 @@ class Local extends AbstractTasks
|
|||||||
if (strlen(runLocally("chmod --help | grep ugoa; true")) > 0) {
|
if (strlen(runLocally("chmod --help | grep ugoa; true")) > 0) {
|
||||||
// Try OS-X specific setting of access-rights
|
// Try OS-X specific setting of access-rights
|
||||||
|
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo chmod g+w $dirs");
|
runLocally("$sudo chmod g+w $dirs", $options);
|
||||||
} elseif ($this->commandExist('setfacl')) {
|
} elseif ($this->commandExist('setfacl')) {
|
||||||
$setFaclUsers = "-m u:\"$httpUser\":rwX";
|
$setFaclUsers = "-m u:\"$httpUser\":rwX";
|
||||||
// Check if remote user exists, before adding it to setfacl
|
// Check if remote user exists, before adding it to setfacl
|
||||||
@ -353,16 +313,16 @@ class Local extends AbstractTasks
|
|||||||
$writeableDirs = get('writable_dirs');
|
$writeableDirs = get('writable_dirs');
|
||||||
foreach ($writeableDirs as $dir) {
|
foreach ($writeableDirs as $dir) {
|
||||||
// Check if ACL has been set or not
|
// Check if ACL has been set or not
|
||||||
$hasfacl = runLocally("cd {{release_or_current_path}}; getfacl -p $dir | grep \"^user:$httpUser:.*w\" | wc -l");
|
$hasfacl = runLocally("getfacl -p $dir | grep \"^user:$httpUser:.*w\" | wc -l", $options);
|
||||||
// Set ACL for directory if it has not been set before
|
// Set ACL for directory if it has not been set before
|
||||||
if (!$hasfacl) {
|
if (!$hasfacl) {
|
||||||
runLocally("cd {{release_or_current_path}}; setfacl -L $recursive $setFaclUsers $dir");
|
runLocally("setfacl -L $recursive $setFaclUsers $dir", $options);
|
||||||
runLocally("cd {{release_or_current_path}}; setfacl -dL $recursive $setFaclUsers $dir");
|
runLocally("setfacl -dL $recursive $setFaclUsers $dir", $options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo setfacl -L $recursive $setFaclUsers $dirs");
|
runLocally("$sudo setfacl -L $recursive $setFaclUsers $dirs", $options);
|
||||||
runLocally("cd {{release_or_current_path}}; $sudo setfacl -dL $recursive $setFaclUsers $dirs");
|
runLocally("$sudo setfacl -dL $recursive $setFaclUsers $dirs", $options);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$alias = currentHost()->getAlias();
|
$alias = currentHost()->getAlias();
|
||||||
@ -371,12 +331,12 @@ class Local extends AbstractTasks
|
|||||||
} elseif ($mode === 'sticky') {
|
} elseif ($mode === 'sticky') {
|
||||||
// Changes the group of the files, sets sticky bit to the directories
|
// Changes the group of the files, sets sticky bit to the directories
|
||||||
// and add the writable bit for all files
|
// and add the writable bit for all files
|
||||||
runLocally("cd {{release_or_current_path}}; for dir in $dirs;" .
|
runLocally("for dir in $dirs;" .
|
||||||
'do ' .
|
'do ' .
|
||||||
'chgrp -L -R {{http_group}} ${dir}; ' .
|
'chgrp -L -R {{http_group}} ${dir}; ' .
|
||||||
'find ${dir} -type d -exec chmod g+rwxs \{\} \;;' .
|
'find ${dir} -type d -exec chmod g+rwxs \{\} \;;' .
|
||||||
'find ${dir} -type f -exec chmod g+rw \{\} \;;' .
|
'find ${dir} -type f -exec chmod g+rw \{\} \;;' .
|
||||||
'done');
|
'done', $options);
|
||||||
} elseif ($mode === 'skip') {
|
} elseif ($mode === 'skip') {
|
||||||
// Does nothing, saves time if no changes are required for some environments
|
// Does nothing, saves time if no changes are required for some environments
|
||||||
return;
|
return;
|
||||||
@ -390,24 +350,6 @@ class Local extends AbstractTasks
|
|||||||
runLocally('echo {{target}} > {{release_path}}/release');
|
runLocally('echo {{target}} > {{release_path}}/release');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creating necessary folders
|
|
||||||
*/
|
|
||||||
public function createFolder(): void
|
|
||||||
{
|
|
||||||
$sudo = $this->getSudo();
|
|
||||||
|
|
||||||
if (testLocally('[ ! -d {{release_path}}/var/cache ]')) {
|
|
||||||
runLocally('mkdir -p {{release_path}}/var/cache');
|
|
||||||
}
|
|
||||||
runLocally($sudo . ' chmod -R 775 {{release_path}}/var/cache');
|
|
||||||
|
|
||||||
if (testLocally('[ ! -d {{release_path}}/var/log ]')) {
|
|
||||||
runLocally('mkdir -p {{release_path}}/var/log');
|
|
||||||
}
|
|
||||||
runLocally($sudo . ' chmod -R 775 {{release_path}}/var/log');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installing vendors
|
* Installing vendors
|
||||||
*/
|
*/
|
||||||
@ -483,4 +425,13 @@ class Local extends AbstractTasks
|
|||||||
{
|
{
|
||||||
info('Folder of this release is: {{release_path}}');
|
info('Folder of this release is: {{release_path}}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlocks deploy
|
||||||
|
*/
|
||||||
|
public function unlock(): void
|
||||||
|
{
|
||||||
|
// always success
|
||||||
|
runLocally("rm -f {{deploy_path}}/.dep/deploy.lock");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Evoweb\DeployerConfig\Tasks;
|
namespace Evoweb\DeployerConfig\Tasks;
|
||||||
|
|
||||||
|
use function Deployer\currentHost;
|
||||||
use function Deployer\get;
|
use function Deployer\get;
|
||||||
use function Deployer\parse;
|
use function Deployer\parse;
|
||||||
use function Deployer\run;
|
use function Deployer\run;
|
||||||
@ -158,8 +159,29 @@ class Remote extends AbstractTasks
|
|||||||
*/
|
*/
|
||||||
public function clearOpcache(): void
|
public function clearOpcache(): void
|
||||||
{
|
{
|
||||||
$webDomain = rtrim($this->get('web_domain'), '/');
|
|
||||||
$htaccess = $this->has('htaccess') ? '--user ' . $this->get('htaccess') : '';
|
$htaccess = $this->has('htaccess') ? '--user ' . $this->get('htaccess') : '';
|
||||||
run('curl ' . $htaccess . ' -sk ' . $webDomain . '/cache.php');
|
run('curl ' . $htaccess . ' -sk https://' . currentHost()->getAlias() . '/cache.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getSudo(): string
|
||||||
|
{
|
||||||
|
return $this->get('clear_use_sudo') ? 'sudo ' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getApplicationContext(): string
|
||||||
|
{
|
||||||
|
return $this->has('application_context') ?
|
||||||
|
'TYPO3_CONTEXT="' . $this->get('application_context') . '" ' :
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTYPO3Bin(string $path, string $testPath): string
|
||||||
|
{
|
||||||
|
if (test('[ -f ' . $testPath . '/releases/{{release_name}}/vendor/bin/typo3cms ]')) {
|
||||||
|
$bin = $path . '/releases/{{release_name}}/vendor/bin/typo3cms';
|
||||||
|
} else {
|
||||||
|
$bin = $path . '/releases/{{release_name}}/vendor/bin/typo3';
|
||||||
|
}
|
||||||
|
return $bin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,8 +55,6 @@ class Rsync extends AbstractTasks
|
|||||||
|
|
||||||
$this->set('rsync_default', $this->defaultConfig);
|
$this->set('rsync_default', $this->defaultConfig);
|
||||||
|
|
||||||
$this->set('rsync_src', '{{deploy_path}}');
|
|
||||||
|
|
||||||
$this->set('rsync_dest', '{{user}}@{{hostname}}:\'{{remote_path}}/\'');
|
$this->set('rsync_dest', '{{user}}@{{hostname}}:\'{{remote_path}}/\'');
|
||||||
|
|
||||||
$this->set('rsync_config', $this->rsyncConfig(...));
|
$this->set('rsync_config', $this->rsyncConfig(...));
|
||||||
@ -87,10 +85,12 @@ class Rsync extends AbstractTasks
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (testLocally('[ -d "{{deploy_path}}" ]')) {
|
if (testLocally('[ -d "{{deploy_path}}" ]')) {
|
||||||
|
$config = $this->get('rsync_config');
|
||||||
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
|
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
|
||||||
runLocally(
|
runLocally(
|
||||||
'rsync \
|
'
|
||||||
-e \'ssh -p {{port}}' . $identityFile . '\' \
|
rsync \
|
||||||
|
-e "ssh -p {{port}}' . $identityFile . '" \
|
||||||
{{rsync_flags}} \
|
{{rsync_flags}} \
|
||||||
{{rsync_options}} \
|
{{rsync_options}} \
|
||||||
{{rsync_timeout}} \
|
{{rsync_timeout}} \
|
||||||
@ -98,7 +98,9 @@ class Rsync extends AbstractTasks
|
|||||||
{{rsync_excludes_download}} \
|
{{rsync_excludes_download}} \
|
||||||
{{rsync_includes}} \
|
{{rsync_includes}} \
|
||||||
{{rsync_filter}} \
|
{{rsync_filter}} \
|
||||||
{{rsync_dest}} {{deploy_path}}'
|
{{rsync_dest}} {{deploy_path}}
|
||||||
|
',
|
||||||
|
$config
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
warning('<comment>No destination folder found.</comment>');
|
warning('<comment>No destination folder found.</comment>');
|
||||||
@ -110,12 +112,13 @@ class Rsync extends AbstractTasks
|
|||||||
*/
|
*/
|
||||||
public function remote(): void
|
public function remote(): void
|
||||||
{
|
{
|
||||||
|
if (test('[ -d "{{remote_path}}" ]')) {
|
||||||
$config = $this->get('rsync_config');
|
$config = $this->get('rsync_config');
|
||||||
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
|
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
|
||||||
if (test('[ -d "{{remote_path}}" ]')) {
|
|
||||||
runLocally(
|
runLocally(
|
||||||
'rsync \
|
'
|
||||||
-e \'ssh -p {{port}}' . $identityFile . '\' \
|
rsync \
|
||||||
|
-e "ssh -p {{port}}' . $identityFile . '" \
|
||||||
{{rsync_flags}} \
|
{{rsync_flags}} \
|
||||||
{{rsync_options}} \
|
{{rsync_options}} \
|
||||||
{{rsync_timeout}} \
|
{{rsync_timeout}} \
|
||||||
@ -123,7 +126,8 @@ class Rsync extends AbstractTasks
|
|||||||
--exclude=' . escapeshellarg('shared/') . ' \
|
--exclude=' . escapeshellarg('shared/') . ' \
|
||||||
{{rsync_excludes_upload}} \
|
{{rsync_excludes_upload}} \
|
||||||
{{rsync_filter}} \
|
{{rsync_filter}} \
|
||||||
\'{{rsync_src}}/\' {{user}}@{{hostname}}:\'{{remote_path}}/\'',
|
{{deploy_path}}/ {{rsync_dest}}
|
||||||
|
',
|
||||||
$config
|
$config
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -139,11 +143,13 @@ class Rsync extends AbstractTasks
|
|||||||
$config = $this->get('rsync_config');
|
$config = $this->get('rsync_config');
|
||||||
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
|
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
|
||||||
runLocally(
|
runLocally(
|
||||||
'rsync \
|
'
|
||||||
-e \'ssh -p {{port}}' . $identityFile . '\' \
|
rsync \
|
||||||
|
-e "ssh -p {{port}}' . $identityFile . '" \
|
||||||
{{rsync_flags}} \
|
{{rsync_flags}} \
|
||||||
{{rsync_options}} \
|
{{rsync_options}} \
|
||||||
\'{{rsync_src}}/current\' {{user}}@{{hostname}}:\'{{remote_path}}/\'',
|
{{deploy_path}}/current {{rsync_dest}}
|
||||||
|
',
|
||||||
$config
|
$config
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
212
README.md
212
README.md
@ -1,85 +1,197 @@
|
|||||||
## To install add Build/composer.json to the project
|
## To install add Build/composer.json to the project
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "cp/build",
|
"name": "ew/build",
|
||||||
"description": "Project deployment with support for deployphp",
|
"description": "Project deployment with utilization of deployphp",
|
||||||
"repositories": [
|
"repositories": {
|
||||||
{
|
"gitea": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitlab.cp-compartner.de/cpcompartner/build-config.git"
|
"url": "https://gitea.fischer.im/evoWeb/ew_deployer_config.git"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"cp/build-config": "^1.7.3"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"require": {
|
||||||
"staging": "dep -vv --file=vendor/cp/build-config/deploy.php deploy staging --branch",
|
"evoweb/deployer-config": "dev-develop"
|
||||||
"production": "dep --file=vendor/cp/build-config/deploy.php deploy production --tag",
|
|
||||||
|
|
||||||
"phpcs-fixer": "php-cs-fixer fix --config=vendor/cp/build-config/php_cs.php",
|
|
||||||
"phpstan": "phpstan analyse --configuration=vendor/cp/build-config/phpstan.neon",
|
|
||||||
"rector": "rector process --config=vendor/cp/build-config/rector.php",
|
|
||||||
"php72-lint": "find ../packages ../private/typo3conf -name '*.php' -exec php7.2 -l {} 1> /dev/null \\;",
|
|
||||||
"php74-lint": "find ../packages ../private/typo3conf -name '*.php' -exec php7.4 -l {} 1> /dev/null \\;"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage per composer
|
## Add to Build/alias.sh with
|
||||||
|
```shell
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
Install it with:
|
function composer() {
|
||||||
```bash
|
mkdir -p "${HOME}/.config/composer"
|
||||||
./composer update
|
mkdir -p "${HOME}/.cache/composer"
|
||||||
|
docker run -t \
|
||||||
|
--user $(id -u):33 \
|
||||||
|
--env COMPOSER_CACHE_DIR=/cache \
|
||||||
|
--env SSH_AUTH_SOCK=/ssh-agent \
|
||||||
|
--env CI_HOST \
|
||||||
|
--env CI_PROJECT_DIR \
|
||||||
|
--env ENVIRONMENT \
|
||||||
|
--env INSTANCE_ID \
|
||||||
|
--env ADDITIONAL_CONFIG_FILE \
|
||||||
|
--env TYPO3_CONTEXT \
|
||||||
|
--env STAGE \
|
||||||
|
--network db \
|
||||||
|
--volume "$(readlink -f ${SSH_AUTH_SOCK})":/ssh-agent \
|
||||||
|
--volume /etc/passwd:/etc/passwd:ro \
|
||||||
|
--volume "${HOME}":"${HOME}" \
|
||||||
|
--volume "${HOME}/.ssh/known_hosts":/home/.ssh-agent/known_hosts \
|
||||||
|
--volume "${HOME}/.config/composer":/tmp \
|
||||||
|
--volume "${HOME}/.cache/composer":/cache \
|
||||||
|
--volume "${CI_PROJECT_DIR}":"${CI_PROJECT_DIR}" \
|
||||||
|
--volume "${PWD%}":/app \
|
||||||
|
evoweb/php:composer $@
|
||||||
|
}
|
||||||
|
alias composer=composer
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Add .env to project root
|
||||||
|
```apacheconf
|
||||||
|
ALIAS_SCRIPT=Build/alias.sh
|
||||||
|
DEPLOY_CONFIG=Build/vendor/evoweb/deployer-config/deploy.php
|
||||||
|
|
||||||
|
DOMAIN=www.evoweb.de
|
||||||
|
CI_HOST=10.10.0.25
|
||||||
|
INSTANCE_ID=website-evoweb
|
||||||
|
HOST=sebastian@10.10.0.25
|
||||||
|
PORT=22
|
||||||
|
|
||||||
|
SHARED=/mnt/Docker/website-evoweb/shared
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add Makefile to project root
|
||||||
|
```makefile
|
||||||
|
MAKEFLAGS += --warn-undefined-variables
|
||||||
|
SHELL := /bin/bash
|
||||||
|
.EXPORT_ALL_VARIABLES:
|
||||||
|
.ONESHELL:
|
||||||
|
.SHELLFLAGS := -eu -o pipefail -c
|
||||||
|
.SILENT:
|
||||||
|
|
||||||
|
# use the rest as arguments for "run"
|
||||||
|
_ARGS := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
|
||||||
|
# ...and turn them into do-nothing targets
|
||||||
|
$(eval $(_ARGS):;@:)
|
||||||
|
|
||||||
|
production-%: ENVIRONMENT=production
|
||||||
|
production-%: TYPO3_CONTEXT=Production
|
||||||
|
staging-%: ENVIRONMENT=staging
|
||||||
|
staging-%: TYPO3_CONTEXT=Production/Staging
|
||||||
|
|
||||||
|
MKFILE_PATH := $(realpath $(firstword $(MAKEFILE_LIST)))
|
||||||
|
CI_PROJECT_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))
|
||||||
|
|
||||||
|
include $(CI_PROJECT_DIR)/.env
|
||||||
|
|
||||||
|
TAG := $(shell git -C $(CI_PROJECT_DIR) describe --abbrev=0)
|
||||||
|
BUILD_DIR := $(CI_PROJECT_DIR)/Build/
|
||||||
|
ALIAS_FILE := $(CI_PROJECT_DIR)/$(ALIAS_SCRIPT)
|
||||||
|
DEPLOY_FILE := $(CI_PROJECT_DIR)/$(DEPLOY_CONFIG)
|
||||||
|
|
||||||
|
.PHONY: latest-tag
|
||||||
|
latest-tag:
|
||||||
|
echo "Latest tag is: $(shell git -C $(CI_PROJECT_DIR) describe --abbrev=0)"
|
||||||
|
|
||||||
|
.PHONY: --build-install
|
||||||
|
--build-install:
|
||||||
|
echo "Installed build tools started"
|
||||||
|
source $(ALIAS_FILE); \
|
||||||
|
composer --working-dir=$(BUILD_DIR) install
|
||||||
|
echo "Installed build tools finished"
|
||||||
|
|
||||||
|
.PHONY: --release
|
||||||
|
--release:
|
||||||
|
echo "Release for $(ENVIRONMENT) with '$(TASK)' started"
|
||||||
|
source $(ALIAS_FILE); \
|
||||||
|
ENVIRONMENT="$(ENVIRONMENT)" \
|
||||||
|
composer --working-dir=$(BUILD_DIR) exec dep -- $(VERBOSE) --file=$(DEPLOY_FILE) $(TASK) environment=$(ENVIRONMENT)
|
||||||
|
echo "Release for $(ENVIRONMENT) with '$(TASK)' finished"
|
||||||
|
|
||||||
|
##@
|
||||||
|
##@ Commands to release tag or branch
|
||||||
|
##@
|
||||||
|
|
||||||
|
.PHONY: production-release
|
||||||
|
production-release: ##@ Release latest tag to production
|
||||||
|
production-release: TASK=deploy --tag $(TAG)
|
||||||
|
production-release: VERBOSE=
|
||||||
|
production-release: --build-install --release
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: staging-release
|
||||||
|
staging-release: ##@ Release develop to staging
|
||||||
|
staging-release: TASK=deploy --branch develop
|
||||||
|
staging-release: VERBOSE=-vv
|
||||||
|
staging-release: --build-install --release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage per make
|
||||||
|
|
||||||
Deploy branch develop to staging
|
Deploy branch develop to staging
|
||||||
```bash
|
```bash
|
||||||
./composer staging develop
|
make staging-release
|
||||||
```
|
```
|
||||||
|
|
||||||
Deploy tag 1.0.0 to production
|
Deploy tag 1.0.0 to production
|
||||||
```bash
|
```bash
|
||||||
./composer production 1.0.0
|
make production-release 1.0.0
|
||||||
```
|
|
||||||
|
|
||||||
PHPCS fixer usage:
|
|
||||||
```bash
|
|
||||||
./composer phpcs-fixer ../package/cp_sitepackage
|
|
||||||
```
|
|
||||||
|
|
||||||
PHPStan usage:
|
|
||||||
```bash
|
|
||||||
./composer phpstan ../package/cp_sitepackage
|
|
||||||
```
|
|
||||||
|
|
||||||
TYPO3 Rector usage:
|
|
||||||
```bash
|
|
||||||
./composer rector ../package/cp_sitepackage
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Overriding default values per host in hosts.yaml
|
## Overriding default values per host in hosts.yaml
|
||||||
```yaml
|
```yaml
|
||||||
.base: &base
|
# for more settings, look in https://github.com/deployphp/deployer/recipe/common.php
|
||||||
local: true
|
config:
|
||||||
alias: '{{CI_HOST}}'
|
bin/php: 'docker exec -e TYPO3_CONTEXT="{{application_context}}" $(docker ps -q -f name={{INSTANCE_ID}}-php-fpm-1) php'
|
||||||
deploy_path: '{{CI_PROJECT_DIR}}/cache/{{ENVIRONMENT_NAME}}'
|
http_user: sebastian
|
||||||
|
http_group: www-data
|
||||||
|
keep_releases: 5
|
||||||
|
|
||||||
|
remote_user: sebastian
|
||||||
|
identity_file: ~/.ssh/rsync_id_ed25519
|
||||||
|
deploy_path: '{{CI_PROJECT_DIR}}/Build/cache/{{ENVIRONMENT}}'
|
||||||
|
|
||||||
|
repository: git@gitea.fischer.im:evoWeb/website_evoweb_de.git
|
||||||
composer_options: '{{composer_action}} --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader --no-suggest --ignore-platform-reqs'
|
composer_options: '{{composer_action}} --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader --no-suggest --ignore-platform-reqs'
|
||||||
|
|
||||||
prepare_dirs:
|
prepare_dirs:
|
||||||
- .dep
|
- .dep
|
||||||
- releases
|
- releases
|
||||||
- shared/fileadmin
|
- shared/public/fileadmin
|
||||||
|
|
||||||
shared_dirs_private:
|
shared_dirs:
|
||||||
- fileadmin
|
- public/fileadmin
|
||||||
|
|
||||||
|
writable_recursive: true
|
||||||
writable_dirs:
|
writable_dirs:
|
||||||
- private/typo3temp
|
- public/typo3temp
|
||||||
- var
|
- var
|
||||||
writable_files:
|
- var/cache
|
||||||
- private/typo3conf/PackageStates.php
|
- var/log
|
||||||
|
|
||||||
rsync:
|
rsync:
|
||||||
exclude:
|
exclude_download:
|
||||||
- '-,p private/typo3temp/var/Cache'
|
- current
|
||||||
|
- shared/
|
||||||
|
- var/*
|
||||||
|
- '-,p public/typo3temp'
|
||||||
|
|
||||||
|
remote_path: /srv/{{INSTANCE_ID}}/data/htdocs/{{ENVIRONMENT}}
|
||||||
|
app_container_path: /usr/local/apache2/htdocs/{{ENVIRONMENT}}
|
||||||
|
|
||||||
|
hosts:
|
||||||
|
staging.evoweb.de:
|
||||||
|
hostname: '{{CI_HOST}}'
|
||||||
|
labels:
|
||||||
|
environment: staging
|
||||||
|
application_context: Production/Staging
|
||||||
|
htaccess: evoweb:website
|
||||||
|
|
||||||
|
www.evoweb.de:
|
||||||
|
hostname: '{{CI_HOST}}'
|
||||||
|
labels:
|
||||||
|
environment: production
|
||||||
|
application_context: Production
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
3
alias.sh
3
alias.sh
@ -9,7 +9,7 @@ function composer() {
|
|||||||
--env SSH_AUTH_SOCK=/ssh-agent \
|
--env SSH_AUTH_SOCK=/ssh-agent \
|
||||||
--env CI_HOST \
|
--env CI_HOST \
|
||||||
--env CI_PROJECT_DIR \
|
--env CI_PROJECT_DIR \
|
||||||
--env ENVIRONMENT_NAME \
|
--env ENVIRONMENT \
|
||||||
--env INSTANCE_ID \
|
--env INSTANCE_ID \
|
||||||
--env ADDITIONAL_CONFIG_FILE \
|
--env ADDITIONAL_CONFIG_FILE \
|
||||||
--env TYPO3_CONTEXT \
|
--env TYPO3_CONTEXT \
|
||||||
@ -18,6 +18,7 @@ function composer() {
|
|||||||
--volume "$(readlink -f ${SSH_AUTH_SOCK})":/ssh-agent \
|
--volume "$(readlink -f ${SSH_AUTH_SOCK})":/ssh-agent \
|
||||||
--volume /etc/passwd:/etc/passwd:ro \
|
--volume /etc/passwd:/etc/passwd:ro \
|
||||||
--volume "${HOME}":"${HOME}" \
|
--volume "${HOME}":"${HOME}" \
|
||||||
|
--volume "${HOME}/.ssh/known_hosts":/home/.ssh-agent/known_hosts \
|
||||||
--volume "${HOME}/.config/composer":/tmp \
|
--volume "${HOME}/.config/composer":/tmp \
|
||||||
--volume "${HOME}/.cache/composer":/cache \
|
--volume "${HOME}/.cache/composer":/cache \
|
||||||
--volume "${CI_PROJECT_DIR}":"${CI_PROJECT_DIR}" \
|
--volume "${CI_PROJECT_DIR}":"${CI_PROJECT_DIR}" \
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$classLoader = require dirname(__DIR__) . '/../vendor/autoload.php';
|
require(dirname(__DIR__) . '/../../vendor/autoload.php');
|
||||||
new \Evoweb\DeployerConfig\Config\Deployment();
|
new \Evoweb\DeployerConfig\Config\Deployment();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user