[TASK] Update deployer to 7.x

This commit is contained in:
Sebastian Fischer 2025-04-12 20:28:16 +02:00
parent fa42ef960c
commit b997f70ecf
5 changed files with 766 additions and 628 deletions

View File

@ -3,6 +3,7 @@
namespace Evoweb\DeployerConfig\Config;
use Deployer\Deployer;
use Deployer\Task\GroupTask;
use Deployer\Task\Task;
use phpDocumentor\Reflection\DocBlockFactory;
use ReflectionMethod;
@ -17,30 +18,32 @@ abstract class AbstractConfiguration
protected function initializeTasks(): void
{
foreach ($this->tasks as $name => $config) {
$this->registerTask($name, $config);
}
array_walk($this->tasks, [$this, 'registerTask']);
}
protected function registerTask(string $name, array $config): void
protected function registerTask(array $config, string $name): void
{
$methodName = $config['methodName'] ?? '';
if ($methodName === '' || !method_exists(static::class, $methodName)) {
$body = $config['body'] ?? '';
if (is_string($body) && !method_exists($this, $body)) {
return;
}
$task = new Task($name, $this->$methodName(...));
if (is_callable([$this, $body])) {
$task = new Task($name, [$this, $body]);
$description = $this->getFunctionSummary($methodName);
if ($description) {
$task->desc($description);
$description = $this->getFunctionSummary($body);
if ($description) {
$task->desc($description);
}
} elseif (is_array($body)) {
$task = new GroupTask($name, $body);
} else {
throw new \InvalidArgumentException('Task body should be a function or an array.');
}
$stages = $config['stages'] ?? [];
if (count($stages)) {
$task->onStage(...$stages);
}
array_map(function ($selector) use ($task) {
$task->addSelector($selector);
}, $config['stages'] ?? []);
$deployer = Deployer::get();
$deployer->tasks->set($name, $task);
@ -60,18 +63,9 @@ abstract class AbstractConfiguration
return $summary;
}
protected function getTasks(): array
{
return array_keys($this->tasks);
}
protected function get(string $name, $default = null)
{
return get($name, $default) ?? (
isset(Deployer::get()->config[$name])
? Deployer::get()->config->get($name)
: $default
);
return get($name, $default);
}
protected function set(string $name, $value): void
@ -81,7 +75,7 @@ abstract class AbstractConfiguration
protected function has(string $name): bool
{
return has($name) || Deployer::get()->config->has($name);
return has($name);
}
protected function hasArray(string $name): bool

File diff suppressed because it is too large Load Diff

View File

@ -2,26 +2,30 @@
namespace Evoweb\DeployerConfig\Config;
use Deployer\Host\Localhost;
use Deployer\Task\Context;
use RuntimeException;
use function Deployer\run;
use function Deployer\runLocally;
use function Deployer\test;
use function Deployer\writeln;
use function Deployer\testLocally;
use function Deployer\warning;
class Rsync extends AbstractConfiguration
{
protected array $defaultConfig = [
'exclude' => [
'.dep/repo',
'.git',
'.env',
'deploy.php',
'deploy.lock',
'current',
'shared/',
'var/*',
],
'exclude_upload' => [
'.dep/repo/',
'deploy.lock',
'current',
'shared/',
],
'exclude-file' => false,
'include' => [
'var/',
@ -36,12 +40,9 @@ class Rsync extends AbstractConfiguration
];
protected array $tasks = [
'rsync:warmup' => ['methodName' => 'warmup'],
'rsync:update_code' => ['methodName' => 'updateCode'],
'rsync:remote' => ['methodName' => 'remote'],
'rsync:remote_additional_targets' => ['methodName' => 'remoteAdditionalTargets'],
'rsync:switch_current' => ['methodName' => 'switchCurrent'],
'rsync:switch_current_additional_targets' => ['methodName' => 'switchCurrentAdditionalTargets'],
'rsync:warmup' => ['body' => 'warmup'],
'rsync:remote' => ['body' => 'remote'],
'rsync:switch_current' => ['body' => 'switchCurrent'],
];
public function __construct()
@ -79,18 +80,19 @@ class Rsync extends AbstractConfiguration
$this->set('rsync_timeout', $this->rsyncTimeout(...));
}
/**
* Warmup remote Rsync target
*/
public function warmup(): void
{
if (!test('[ -d "{{deploy_path}}" ]')) {
if (!testLocally('[ -d "{{deploy_path}}" ]')) {
runLocally('mkdir -p {{deploy_path}}');
}
if (test('[ -d "{{deploy_path}}" ]')) {
$identityFile = $this->get('identityFile') ? ' -i ' . $this->get('identityFile') : '';
run(
if (testLocally('[ -d "{{deploy_path}}" ]')) {
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
runLocally(
'rsync \
-e \'ssh -p {{port}}' . $identityFile . '\' \
{{rsync_flags}} \
@ -103,36 +105,7 @@ class Rsync extends AbstractConfiguration
{{rsync_dest}} {{deploy_path}}'
);
} else {
writeln('<comment>No destination folder found.</comment>');
}
}
/**
* Copy repository content to release folder
*/
public function updateCode(): void
{
$pathConfigName = 'ignore_update_code_paths';
if ($this->hasArray($pathConfigName)) {
$excludes = '';
$ignoreUpdateCodePaths = $this->get($pathConfigName);
foreach ($ignoreUpdateCodePaths as $path) {
$excludes .= ' --exclude=\'' . $path . '\'';
}
$identityFile = $this->get('identityFile') ? ' -i ' . $this->get('identityFile') : '';
run(
'rsync \
-e \'ssh -p {{port}}' . $identityFile . '\' \
{{rsync_flags}} \
{{rsync_options}} \
{{rsync_timeout}} \
--exclude=' . escapeshellarg('shared') . ' \
' . $excludes . ' \
{{rsync_includes}} \
{{rsync_filter}} \
{{CI_PROJECT_DIR}}/ \
{{release_path}}'
);
warning('<comment>No destination folder found.</comment>');
}
}
@ -142,27 +115,10 @@ class Rsync extends AbstractConfiguration
public function remote(): void
{
$config = $this->get('rsync_config');
$server = Context::get()->getHost();
$identityFile = $this->get('identityFile') ? ' -i ' . $this->get('identityFile') : '';
if ($server instanceof Localhost) {
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
if (test('[ -d "{{remote_path}}" ]')) {
runLocally(
'rsync \
-e \'ssh -p {{port}}' . $identityFile . '\' \
{{rsync_flags}} \
{{rsync_options}} \
{{rsync_timeout}} \
{{rsync_includes}} \
--exclude=' . escapeshellarg('shared/') . ' \
{{rsync_excludes_upload}} \
{{rsync_filter}} \
\'{{rsync_src}}/\' {{rsync_dest}}',
$config
);
return;
}
runLocally(
'rsync \
-e \'ssh -p {{port}}' . $identityFile . '\' \
{{rsync_flags}} \
{{rsync_options}} \
@ -172,40 +128,10 @@ class Rsync extends AbstractConfiguration
{{rsync_excludes_upload}} \
{{rsync_filter}} \
\'{{rsync_src}}/\' {{user}}@{{hostname}}:\'{{remote_path}}/\'',
$config
);
}
/**
* Rsync local->additional targets
*/
public function remoteAdditionalTargets(): void
{
$configName = 'additional_remote_targets';
if ($this->hasArray($configName)) {
$config = $this->get('rsync_config');
$identityFile = $this->get('identityFile') ? ' -i ' . $this->get('identityFile') : '';
$targets = $this->get($configName);
foreach ($targets as $target) {
$port = $target['port'] ?? '{{port}}';
$user = $target['user'] ?? '{{user}}';
$remotePath = $target['remote_path'] ?: '{{remote_path}}';
runLocally(
'rsync \
-e \'ssh -p ' . $port . $identityFile . '\' \
{{rsync_flags}} \
{{rsync_options}} \
{{rsync_timeout}} \
{{rsync_includes}} \
--exclude=' . escapeshellarg('shared/') . ' \
{{rsync_excludes_upload}} \
{{rsync_filter}} \
\'{{rsync_src}}/\' ' . $user . '@' . $target['hostname'] . ':\'' . $remotePath . '/\'',
$config
);
}
$config
);
} else {
writeln('No additional remote target configured');
warning('<comment>No destination folder found.</comment>');
}
}
@ -215,20 +141,7 @@ class Rsync extends AbstractConfiguration
public function switchCurrent(): void
{
$config = $this->get('rsync_config');
$server = Context::get()->getHost();
$identityFile = $this->get('identityFile') ? ' -i ' . $this->get('identityFile') : '';
if ($server instanceof Localhost) {
runLocally(
'rsync \
-e \'ssh -p {{port}}' . $identityFile . '\' \
{{rsync_flags}} \
{{rsync_options}} \
\'{{rsync_src}}/current\' {{rsync_dest}}',
$config
);
return;
}
$identityFile = $this->get('identity_file') ? ' -i ' . $this->get('identity_file') : '';
runLocally(
'rsync \
-e \'ssh -p {{port}}' . $identityFile . '\' \
@ -239,67 +152,6 @@ class Rsync extends AbstractConfiguration
);
}
/**
* Sync current after release was uploaded
*/
public function switchCurrentAdditionalTargets(): void
{
$configName = 'additional_remote_targets';
if ($this->hasArray($configName)) {
$config = $this->get('rsync_config');
$identityFile = $this->get('identityFile') ? ' -i ' . $this->get('identityFile') : '';
$targets = $this->get($configName);
foreach ($targets as $target) {
$port = $target['port'] ?? '{{port}}';
$user = $target['user'] ?? '{{user}}';
$remotePath = $target['remote_path'] ?: '{{remote_path}}';
runLocally(
'rsync \
-e \'ssh -p ' . $port . $identityFile . '\' \
{{rsync_flags}} \
{{rsync_options}} \
\'{{rsync_src}}/current\'' . ' ' . $user . '@' . $target['hostname'] . ':\'' . $remotePath . '/\'',
$config
);
}
} else {
writeln('No additional remote target configured');
}
}
protected function getSource(): string
{
$source = $this->get('rsync_src');
while (is_callable($source)) {
$source = $source();
}
if (!trim($source)) {
// if $src is not set here rsync is going to do a directory listing
// exiting with code 0, since only doing a directory listing clearly
// is not what we want to achieve we need to throw an exception
throw new RuntimeException('You need to specify a source path.');
}
return $source;
}
protected function getDestination(): string
{
$destination = $this->get('rsync_dest');
while (is_callable($destination)) {
$destination = $destination();
}
if (!trim($destination)) {
// if $dst is not set here we are going to sync to root
// and even worse - depending on rsync flags and permission -
// might end up deleting everything we have write permission to
throw new RuntimeException('You need to specify a destination path.');
}
return $destination;
}
public function rsyncConfig(): array
{

View File

@ -4,7 +4,7 @@
"type": "project",
"require": {
"deployer/deployer": "^v6.9 || dev-master",
"deployer/deployer": "^v7.5.0",
"phpdocumentor/reflection-docblock": "^5.3"
},

View File

@ -1,3 +1,4 @@
<?php
$classLoader = require dirname(__DIR__) . '/../vendor/autoload.php';
new \Evoweb\DeployerConfig\Config\Deployment();