From 08dce880be6d7277542b52683e3d7e4236b12b76 Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Fri, 26 Jan 2018 16:39:31 +0100 Subject: [PATCH 01/20] Added sleep task to allow delaying execution of other tasks --- src/Task/BuiltIn/SleepTask.php | 68 ++++++++++++++++++++++++++++ tests/Task/BuiltIn/SleepTaskTest.php | 31 +++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/Task/BuiltIn/SleepTask.php create mode 100644 tests/Task/BuiltIn/SleepTaskTest.php diff --git a/src/Task/BuiltIn/SleepTask.php b/src/Task/BuiltIn/SleepTask.php new file mode 100644 index 0000000..24c6051 --- /dev/null +++ b/src/Task/BuiltIn/SleepTask.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Mage\Task\BuiltIn; + +use Mage\Task\Exception\ErrorException; +use Mage\Task\AbstractTask; + +/** + * Sleep task. Sleeps for a given number of seconds so you can delay task + * execution. + * + * @author Yanick Witschi + */ +class SleepTask extends AbstractTask +{ + /** + * @return string + */ + public function getName() + { + return 'sleep'; + } + + /** + * @return string + */ + public function getDescription() + { + $options = $this->getOptions(); + + return sprintf('[Sleep] Sleeping for %s second(s)', (int) $options['seconds']); + } + + /** + * @return bool + * + * @throws ErrorException + */ + public function execute() + { + $options = $this->getOptions(); + + sleep((int) $options['seconds']); + + return true; + } + + /** + * @return array + */ + protected function getOptions() + { + $options = array_merge( + ['seconds' => 1], + $this->options + ); + + return $options; + } +} diff --git a/tests/Task/BuiltIn/SleepTaskTest.php b/tests/Task/BuiltIn/SleepTaskTest.php new file mode 100644 index 0000000..26f1756 --- /dev/null +++ b/tests/Task/BuiltIn/SleepTaskTest.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Mage\Tests\Task\BuiltIn; + +use Mage\Task\BuiltIn\SleepTask; +use Mage\Tests\Runtime\RuntimeMockup; +use PHPUnit_Framework_TestCase as TestCase; + +class SleepTaskTest extends TestCase +{ + public function testCommand() + { + $runtime = new RuntimeMockup(); + $runtime->setConfiguration(['environments' => ['test' => []]]); + $runtime->setEnvironment('test'); + + $task = new SleepTask(); + $task->setRuntime($runtime); + + $this->assertSame('[Sleep] Sleeping for 1 second(s)', $task->getDescription()); + $task->execute(); + } +} From 3f22cc6288fab1d6886d5640d418ec42743d68d5 Mon Sep 17 00:00:00 2001 From: Ante Galic Date: Tue, 12 Jun 2018 15:20:37 +0200 Subject: [PATCH 02/20] Add optional symlink --- src/Task/BuiltIn/Deploy/ReleaseTask.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Task/BuiltIn/Deploy/ReleaseTask.php b/src/Task/BuiltIn/Deploy/ReleaseTask.php index ab767f0..231dd2a 100644 --- a/src/Task/BuiltIn/Deploy/ReleaseTask.php +++ b/src/Task/BuiltIn/Deploy/ReleaseTask.php @@ -40,8 +40,10 @@ class ReleaseTask extends AbstractTask implements ExecuteOnRollbackInterface $hostPath = rtrim($this->runtime->getEnvOption('host_path'), '/'); $releaseId = $this->runtime->getReleaseId(); + + $symlink = $this->runtime->getEnvOption('symlink', 'current'); - $cmdLinkRelease = sprintf('cd %s && ln -snf releases/%s current', $hostPath, $releaseId); + $cmdLinkRelease = sprintf('cd %s && ln -snf releases/%s %s', $hostPath, $releaseId, $symlink); /** @var Process $process */ $process = $this->runtime->runRemoteCommand($cmdLinkRelease, false, null); From df248dd1b00f759e017793c0b576e97f5e024afe Mon Sep 17 00:00:00 2001 From: Fritz Michael Gschwantner Date: Mon, 10 Sep 2018 18:27:56 +0200 Subject: [PATCH 03/20] use fallback for posix_getpwuid on Windows --- src/Runtime/Runtime.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Runtime/Runtime.php b/src/Runtime/Runtime.php index 5b7368d..006282e 100644 --- a/src/Runtime/Runtime.php +++ b/src/Runtime/Runtime.php @@ -517,6 +517,11 @@ class Runtime */ public function getCurrentUser() { + // Windows fallback + if (!function_exists('posix_getpwuid')) { + return getenv('USERNAME') ?: ''; + } + $userData = posix_getpwuid(posix_geteuid()); return $userData['name']; } From 9a46f89266616911d24cf192fc1cdd956aedf6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 01:20:03 -0300 Subject: [PATCH 04/20] [Galactica] V5 initial scope --- .github/workflows/linters.yml | 32 +++ .github/workflows/tests.yml | 60 +++++ .gitignore | 2 +- .travis.yml | 3 +- CHANGELOG.md | 28 +-- CONTRIBUTING.md | 25 +- LICENSE | 2 +- README.md | 4 +- composer.json | 26 +- docs/dockers/docker-compose.yml | 6 +- docs/dockers/{php7.4 => php8.0}/Dockerfile | 4 +- docs/example-config.yml | 8 +- phpcs.xml.dist | 14 ++ phpstan.neon | 4 + phpunit.xml.dist | 61 ++--- src/Command/AbstractCommand.php | 29 +-- src/Command/BuiltIn/Config/DumpCommand.php | 14 +- .../BuiltIn/Config/EnvironmentsCommand.php | 14 +- src/Command/BuiltIn/DeployCommand.php | 108 +++++--- src/Command/BuiltIn/Releases/ListCommand.php | 31 ++- .../BuiltIn/Releases/RollbackCommand.php | 35 +-- src/Command/BuiltIn/VersionCommand.php | 14 +- src/Deploy/Strategy/ReleasesStrategy.php | 27 +- src/Deploy/Strategy/RsyncStrategy.php | 27 +- src/Deploy/Strategy/StrategyInterface.php | 30 ++- src/Mage.php | 5 +- src/MageApplication.php | 43 ++-- src/Runtime/Exception/RuntimeException.php | 5 +- src/Runtime/Runtime.php | 231 +++++++----------- src/Task/AbstractTask.php | 43 +--- .../BuiltIn/Composer/AbstractComposerTask.php | 11 +- .../BuiltIn/Composer/DumpAutoloadTask.php | 9 +- src/Task/BuiltIn/Composer/InstallTask.php | 11 +- src/Task/BuiltIn/Composer/SelfUpdateTask.php | 86 ------- .../BuiltIn/Deploy/Release/CleanupTask.php | 7 +- .../BuiltIn/Deploy/Release/PrepareTask.php | 7 +- src/Task/BuiltIn/Deploy/ReleaseTask.php | 9 +- src/Task/BuiltIn/Deploy/RsyncTask.php | 23 +- src/Task/BuiltIn/Deploy/Tar/CleanupTask.php | 7 +- src/Task/BuiltIn/Deploy/Tar/CopyTask.php | 20 +- src/Task/BuiltIn/Deploy/Tar/PrepareTask.php | 14 +- src/Task/BuiltIn/ExecTask.php | 13 +- src/Task/BuiltIn/FS/AbstractFileTask.php | 15 +- src/Task/BuiltIn/FS/ChangeModeTask.php | 14 +- src/Task/BuiltIn/FS/CopyTask.php | 14 +- src/Task/BuiltIn/FS/LinkTask.php | 14 +- src/Task/BuiltIn/FS/MoveTask.php | 11 +- src/Task/BuiltIn/FS/RemoveTask.php | 14 +- src/Task/BuiltIn/Git/ChangeBranchTask.php | 19 +- src/Task/BuiltIn/Git/UpdateTask.php | 13 +- .../BuiltIn/Symfony/AbstractSymfonyTask.php | 11 +- .../BuiltIn/Symfony/AssetsInstallTask.php | 18 +- src/Task/BuiltIn/Symfony/CacheClearTask.php | 7 +- .../BuiltIn/Symfony/CachePoolClearTask.php | 17 +- .../BuiltIn/Symfony/CachePoolPruneTask.php | 7 +- src/Task/BuiltIn/Symfony/CacheWarmupTask.php | 7 +- src/Task/Exception/ErrorException.php | 7 +- src/Task/Exception/SkipException.php | 5 +- src/Task/ExecuteOnRollbackInterface.php | 1 + src/Task/TaskFactory.php | 42 ++-- src/Utils.php | 47 ++-- .../BuiltIn/DeployCommandWithReleasesTest.php | 49 ++++ tests/MageApplicationMockup.php | 2 +- tests/MageApplicationWindowsMockup.php | 3 +- tests/Runtime/ProcessMockup.php | 9 +- tests/Runtime/RuntimeMockup.php | 18 +- tests/Runtime/RuntimeWindowsMockup.php | 2 +- tests/Task/AbstractTaskTest.php | 8 - .../BuiltIn/Composer/BasicComposerTask.php | 6 +- .../BuiltIn/Composer/SelfUpdateTaskTest.php | 174 ------------- tests/Task/Custom/NotInstantiableTask.php | 6 +- tests/Task/Custom/ValidTask.php | 6 +- tests/Task/CustomTask.php | 6 +- tests/Task/TestCaseFailTask.php | 6 +- tests/Task/TestCaseTask.php | 6 +- 75 files changed, 805 insertions(+), 931 deletions(-) create mode 100644 .github/workflows/linters.yml create mode 100644 .github/workflows/tests.yml rename docs/dockers/{php7.4 => php8.0}/Dockerfile (68%) create mode 100644 phpcs.xml.dist create mode 100644 phpstan.neon delete mode 100644 src/Task/BuiltIn/Composer/SelfUpdateTask.php delete mode 100644 tests/Task/BuiltIn/Composer/SelfUpdateTaskTest.php diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml new file mode 100644 index 0000000..83ccf61 --- /dev/null +++ b/.github/workflows/linters.yml @@ -0,0 +1,32 @@ +name: Linters + +on: + push: + branches: + - master + - galactica + pull_request: + release: + types: + - created + +jobs: + linters: + name: Linters + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Composer install + uses: php-actions/composer@v5 + with: + command: install + args: --ignore-platform-reqs --no-scripts + version: 2 + php_version: 8.0 + - name: PHPStan + run: ./vendor/bin/phpstan analyse + - name: PHP Code Sniffer + run: ./vendor/bin/phpcs diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..e3c563a --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,60 @@ +name: PHPUnit + +on: + push: + branches: + - master + - galactica + pull_request: + release: + types: + - created + +jobs: + unit_tests_80: + name: Unit tests with PHP 8.0 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Composer install + uses: php-actions/composer@v5 + with: + command: install + args: --ignore-platform-reqs --no-scripts + version: 2 + php_version: 8.0 + - name: Run tests + env: + XDEBUG_MODE: coverage + run: ./vendor/bin/phpunit --testsuite=unit + - name: Run Coveralls + env: + XDEBUG_MODE: coverage + run: ./vendor/bin/php-coveralls -v --coverage_clover build/logs/coverage.xml + + unit_tests_81: + name: Unit tests with PHP 8.1 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Composer install + uses: php-actions/composer@v5 + with: + command: install + args: --ignore-platform-reqs --no-scripts + version: 2 + php_version: 8.1 + - name: Run tests + env: + XDEBUG_MODE: coverage + run: ./vendor/bin/phpunit --testsuite=unit + - name: Run Coveralls + env: + XDEBUG_MODE: coverage + run: ./vendor/bin/php-coveralls -v --coverage_clover build/logs/coverage.xml diff --git a/.gitignore b/.gitignore index 34fa4e7..f8cb51b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ composer.lock .mage.yml .phpunit.result.cache - +.phpcs-cache diff --git a/.travis.yml b/.travis.yml index 96cce3e..3a15c80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ language: php php: - - '7.2' - - '7.4' - '8.0' + - '8.1' install: - composer install diff --git a/CHANGELOG.md b/CHANGELOG.md index 704d048..8d3fcfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,8 @@ -CHANGELOG for 4.X +CHANGELOG for 5.X ================= -* 4.1.1 (2021-02-20) - * Add `copyDirectory` option - * Bug fixes - * Improve testing and coverage - - -* 4.1.0 (2021-02-19) - * PHP 8 and Symfony 5 compatibility [PR#448] - * Timeout option for SSH [PR#436] - * Improve compatibility with Windows [PR#434] [PR#429] - * Improve config load [PR#422] - * Bug fixes [PR#448] [PR#424] - * Readme Update [PR#438] - - -* 4.0.0 (2018-04-02) - * v4 series release - * Refactored for Symfony 4 and PHP 7.1 - * Symfony Pool Clear task added - * Symfony Pool Prune task added - * Symfony Assetic task removed +* 5.0.0 (2022-04-15) + * v5 series release + * Refactored for Symfony 6 and PHP 8 + * Added strong types + * Removed task `composer/self-update` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc1ed8e..d262e04 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Please read the following guidelines to make your and our work easier and cleane 1. Write clean code with no mess left 2. Contribute the docs when adding configurable new feature -3. Create your pull request from `nostromo` branch +3. Create your pull request from `galactica` branch 4. Ensure your code is fully covered by tests ---------- @@ -28,39 +28,36 @@ In order to have the PRs prioritized name them with the following tags. [FEATURE] Create new PermissionsTask [HOTFIX] Exception not caught on deployment ``` -All Pull Requests must be done to the `nostromo` branch, only exception are Hotfixes. +All Pull Requests must be done to the `galactica` branch, only exception are Hotfixes. Remember of square brackets when adding issue number. If you'd forget adding them, your whole message will be a comment! # Developing Magallanes ## Branches The flow is pretty simple. -In most common cases we work on the `nostromo` branch. It's the branch with the main development for the current major version. All Pull Requests must merge with that branch. The `master` branch is used to move the validated code and generate the releases in an orderly fashion, also we could use it for hotfixes. +In most common cases we work on the `galactica` branch. It's the branch with the main development for the current major version. All Pull Requests must merge with that branch. The `master` branch is used to move the validated code and generate the releases in an orderly fashion, also we could use it for hotfixes. -If you want to use developing branch in your code, simple pass `dev-nostromo` to dependency version in your `composer.json` file: +If you want to use developing branch in your code, simple pass `dev-galactica` to dependency version in your `composer.json` file: ```json { "require": { - "andres-montanez/magallanes": "dev-nostromo" + "andres-montanez/magallanes": "dev-galactica" } } ``` ## Organization and code quality -We use [PSR2](http://www.php-fig.org/psr/psr-2/) as PHP coding standard. +We use [PSR-12](http://www.php-fig.org/psr/psr-12/) as PHP coding standard. ### Tools you can use to ensure your code quality -1. PHP-CodeSniffer -2. [PHP Mess Detector](https://phpmd.org/) -3. PHP Copy/Paste Detector -4. PHP Dead Code Detector -5. [PHP Coding Standards Fixer](http://cs.sensiolabs.org) with --level=psr2 +1. PHPStan `./vendor/bin/phpstan analyse` +2. PHP Code Sniffer `./vendor/bin/phpcs` ## Testing and quality We use PHPUnit to test our code. Most of the project is covered with tests, so if you want your code to be merged push it with proper testing and coverage (at least 95%). To execute the tests with code coverage report: -``` -vendor/bin/phpunit --coverage-clover build/logs/coverage.xml -vendor/bin/coveralls -v --coverage_clover build/logs/coverage.xml +```bash +./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml --coverage-text +./vendor/bin/php-coveralls -v --coverage_clover build/logs/coverage.xml ``` Tests structure follow almost the same structure as production code with `Test` suffix in class and file name. Follow the tests already made as guidelines. diff --git a/LICENSE b/LICENSE index 2130481..f5d91f0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 - 2017 Andrés Montañez +Copyright (c) 2011 - 2022 Andrés Montañez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/README.md b/README.md index 5a6bc40..e20260a 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Simply add the following dependency to your project’s composer.json file: ```json "require-dev": { - "andres-montanez/magallanes": "^4.0" + "andres-montanez/magallanes": "^5.0" } ``` Finally you can use **Magallanes** from the vendor's bin: @@ -26,4 +26,4 @@ vendor/bin/mage version ``` ### Codename Discovery One -Each new mayor version of **Magallanes** will have a codename (like Ubuntu), version 3 was _Nostromo_, and in the current version it is **_Discovery One_**, in homage to the spaceship from the ground breaking film *2001: A Space Odyssey (1968)*. +Each new mayor version of **Magallanes** will have a codename (like Ubuntu), version 3 was _Nostromo_, version 4 was _Discovery One_, and in the current version it is **_Galactica_**, in homage to the space battleship from the TV series Battlestar Galactica, both the '70s and the mind blowing revision of 2005. diff --git a/composer.json b/composer.json index 45fe073..903ae36 100644 --- a/composer.json +++ b/composer.json @@ -12,18 +12,20 @@ } ], "require": { - "php": "^7.2 | ^8.0", - "monolog/monolog": "~1.11 | ^2.0", - "symfony/console": "^4.0 | ^5.0", - "symfony/filesystem": "^4.0 | ^5.0", - "symfony/event-dispatcher": "^4.0 | ^5.0", - "symfony/finder": "^4.0 | ^5.0", - "symfony/yaml": "^4.0 | ^5.0", - "symfony/process": "^4.0 | ^5.0" + "php": "^8.0", + "monolog/monolog": "^2.5", + "symfony/console": "^6.0", + "symfony/filesystem": "^6.0", + "symfony/event-dispatcher": "^6.0", + "symfony/finder": "^6.0", + "symfony/yaml": "^6.0", + "symfony/process": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^8.0", - "php-coveralls/php-coveralls": "~2.0" + "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^1.5", + "squizlabs/php_codesniffer": "^3.6", + "php-coveralls/php-coveralls": "^2.5" }, "suggest": { "ext-posix": "*" @@ -41,8 +43,8 @@ "bin": ["bin/mage"], "extra": { "branch-alias": { - "dev-master": "4.0.x-dev", - "dev-discovery-one": "4.x-dev" + "dev-master": "5.0.x-dev", + "dev-discovery-one": "5.x-dev" } } } diff --git a/docs/dockers/docker-compose.yml b/docs/dockers/docker-compose.yml index 6ba830c..ad04dc5 100644 --- a/docs/dockers/docker-compose.yml +++ b/docs/dockers/docker-compose.yml @@ -1,7 +1,7 @@ version: '2' services: - php7.4: - container_name: mage-php7.4 - build: ./php7.4 + php8.0: + container_name: mage-php8.0 + build: ./php8.0 volumes: - ../../:/home/magephp diff --git a/docs/dockers/php7.4/Dockerfile b/docs/dockers/php8.0/Dockerfile similarity index 68% rename from docs/dockers/php7.4/Dockerfile rename to docs/dockers/php8.0/Dockerfile index abafc3b..a2492d5 100644 --- a/docs/dockers/php7.4/Dockerfile +++ b/docs/dockers/php8.0/Dockerfile @@ -1,11 +1,11 @@ -FROM ubuntu:20.04 +FROM ubuntu:21.10 ENV DEBIAN_FRONTEND=noninteractive \ TZ=UTC RUN apt-get update && apt-get upgrade -y RUN apt-get install -y vim curl git unzip -RUN apt-get install -y php7.4-cli php-zip php7.4-curl php7.4-xml php7.4-mbstring php7.4-xdebug +RUN apt-get install -y php8.0-cli php8.0-zip php8.0-curl php8.0-xml php8.0-mbstring php8.0-xdebug RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer diff --git a/docs/example-config.yml b/docs/example-config.yml index a59e97a..e27f4e4 100644 --- a/docs/example-config.yml +++ b/docs/example-config.yml @@ -7,10 +7,8 @@ magephp: host_path: /var/www/test releases: 4 exclude: - - vendor - - app/cache - - app/log - - web/app_dev.php + - var/cache + - var/log hosts: - webserver1 - webserver2 @@ -18,7 +16,7 @@ magephp: pre-deploy: - git/update - composer/install - - composer/generate-autoload + - composer/dump-autoload on-deploy: - symfony/cache-warmup: { env: 'prod' } - symfony/assets-install: { env: 'prod' } diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..38f2f10 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,14 @@ + + + + + + + + + + + + src/ + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..6e451fa --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - src diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f8680db..686da15 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,37 +1,28 @@ - - - - - - - - - - - - ./tests/ - - - - - - benchmark - intl-data - - - - - - ./src/ - - ./tests/ - - - + + + + ./src/ + + + ./tests/ + + + + + + + + + + + ./tests/ + + + + + benchmark + intl-data + + diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index ba94164..cc1712e 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -1,4 +1,5 @@ runtime = $runtime; - return $this; } /** * Logs a message - * - * @param string $message - * @param string $level */ - public function log($message, $level = LogLevel::DEBUG) + public function log(string $message, string $level = LogLevel::DEBUG): void { $this->runtime->log($message, $level); } /** * Get the Human friendly Stage name - * - * @return string */ - protected function getStageName() + protected function getStageName(): string { $utils = new Utils(); return $utils->getStageName($this->runtime->getStage()); @@ -71,7 +56,7 @@ abstract class AbstractCommand extends Command /** * Requires the configuration to be loaded */ - protected function requireConfig() + protected function requireConfig(): void { $app = $this->getApplication(); if ($app instanceof MageApplication) { diff --git a/src/Command/BuiltIn/Config/DumpCommand.php b/src/Command/BuiltIn/Config/DumpCommand.php index 8b7a185..181fd23 100644 --- a/src/Command/BuiltIn/Config/DumpCommand.php +++ b/src/Command/BuiltIn/Config/DumpCommand.php @@ -1,4 +1,5 @@ setName('config:dump') - ->setDescription('Dumps the Magallanes configuration') - ; + ->setDescription('Dumps the Magallanes configuration'); } /** * Execute the Command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int|mixed */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->requireConfig(); @@ -51,6 +47,6 @@ class DumpCommand extends AbstractCommand $output->writeln(''); $output->writeln('Finished Magallanes'); - return 0; + return self::SUCCESS; } } diff --git a/src/Command/BuiltIn/Config/EnvironmentsCommand.php b/src/Command/BuiltIn/Config/EnvironmentsCommand.php index b66616b..65e74eb 100644 --- a/src/Command/BuiltIn/Config/EnvironmentsCommand.php +++ b/src/Command/BuiltIn/Config/EnvironmentsCommand.php @@ -1,4 +1,5 @@ setName('config:environments') - ->setDescription('List all Magallanes configured Environments') - ; + ->setDescription('List all Magallanes configured Environments'); } /** * Execute the Command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int|mixed */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->requireConfig(); @@ -66,6 +62,6 @@ class EnvironmentsCommand extends AbstractCommand $output->writeln(''); $output->writeln('Finished Magallanes'); - return 0; + return self::SUCCESS; } } diff --git a/src/Command/BuiltIn/DeployCommand.php b/src/Command/BuiltIn/DeployCommand.php index bb2cb5c..684c57a 100644 --- a/src/Command/BuiltIn/DeployCommand.php +++ b/src/Command/BuiltIn/DeployCommand.php @@ -1,4 +1,5 @@ setName('deploy') ->setDescription('Deploy code to hosts') ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to') - ->addOption('branch', null, InputOption::VALUE_REQUIRED, 'Force to switch to a branch other than the one defined', false) - ; + ->addOption( + 'branch', + null, + InputOption::VALUE_REQUIRED, + 'Force to switch to a branch other than the one defined', + false + ); } /** * Execute the Command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return integer */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->requireConfig(); @@ -103,17 +102,15 @@ class DeployCommand extends AbstractCommand $output->writeln('Finished Magallanes'); - return $this->statusCode; + return intval($this->statusCode); } /** * Run the Deployment Process * - * @param OutputInterface $output - * @param StrategyInterface $strategy * @throws RuntimeException */ - protected function runDeployment(OutputInterface $output, StrategyInterface $strategy) + protected function runDeployment(OutputInterface $output, StrategyInterface $strategy): void { // Run "Pre Deploy" Tasks $this->runtime->setStage(Runtime::PRE_DEPLOY); @@ -140,16 +137,20 @@ class DeployCommand extends AbstractCommand } } - protected function runOnHosts(OutputInterface $output, $tasks) + /** + * @param string[] $tasks + */ + protected function runOnHosts(OutputInterface $output, array $tasks): void { $hosts = $this->runtime->getEnvOption('hosts'); if (!is_array($hosts) && !$hosts instanceof \Countable) { $hosts = []; } - if (count($hosts) == 0) { + + if (count($hosts) === 0) { $output->writeln(sprintf(' No hosts defined, skipping %s tasks', $this->getStageName())); $output->writeln(''); - return true; + return; } foreach ($hosts as $host) { @@ -165,21 +166,27 @@ class DeployCommand extends AbstractCommand /** * Runs all the tasks * - * @param OutputInterface $output - * @param $tasks - * @return bool + * @param string[] $tasks * @throws RuntimeException */ - protected function runTasks(OutputInterface $output, $tasks) + protected function runTasks(OutputInterface $output, array $tasks): bool { if (count($tasks) == 0) { - $output->writeln(sprintf(' No tasks defined for %s stage', $this->getStageName())); + $output->writeln( + sprintf(' No tasks defined for %s stage', $this->getStageName()) + ); $output->writeln(''); return true; } if ($this->runtime->getHostName() !== null) { - $output->writeln(sprintf(' Starting %s tasks on host %s:', $this->getStageName(), $this->runtime->getHostName())); + $output->writeln( + sprintf( + ' Starting %s tasks on host %s:', + $this->getStageName(), + $this->runtime->getHostName() + ) + ); } else { $output->writeln(sprintf(' Starting %s tasks:', $this->getStageName())); } @@ -188,7 +195,6 @@ class DeployCommand extends AbstractCommand $succeededTasks = 0; foreach ($tasks as $taskName) { - /** @var AbstractTask $task */ $task = $this->taskFactory->get($taskName); $output->write(sprintf(' Running %s ... ', $task->getDescription())); $this->log(sprintf('Running task %s (%s)', $task->getDescription(), $task->getName())); @@ -196,25 +202,48 @@ class DeployCommand extends AbstractCommand if ($this->runtime->inRollback() && !$task instanceof ExecuteOnRollbackInterface) { $succeededTasks++; $output->writeln('SKIPPED'); - $this->log(sprintf('Task %s (%s) finished with SKIPPED, it was in a Rollback', $task->getDescription(), $task->getName())); + $this->log( + sprintf( + 'Task %s (%s) finished with SKIPPED, it was in a Rollback', + $task->getDescription(), + $task->getName() + ) + ); } else { try { if ($task->execute()) { $succeededTasks++; $output->writeln('OK'); - $this->log(sprintf('Task %s (%s) finished with OK', $task->getDescription(), $task->getName())); + $this->log( + sprintf('Task %s (%s) finished with OK', $task->getDescription(), $task->getName()) + ); } else { $output->writeln('FAIL'); $this->statusCode = 180; - $this->log(sprintf('Task %s (%s) finished with FAIL', $task->getDescription(), $task->getName())); + $this->log( + sprintf('Task %s (%s) finished with FAIL', $task->getDescription(), $task->getName()) + ); } } catch (SkipException $exception) { $succeededTasks++; $output->writeln('SKIPPED'); - $this->log(sprintf('Task %s (%s) finished with SKIPPED, thrown SkipException', $task->getDescription(), $task->getName())); + $this->log( + sprintf( + 'Task %s (%s) finished with SKIPPED, thrown SkipException', + $task->getDescription(), + $task->getName() + ) + ); } catch (ErrorException $exception) { $output->writeln(sprintf('ERROR [%s]', $exception->getTrimmedMessage())); - $this->log(sprintf('Task %s (%s) finished with FAIL, with Error "%s"', $task->getDescription(), $task->getName(), $exception->getMessage())); + $this->log( + sprintf( + 'Task %s (%s) finished with FAIL, with Error "%s"', + $task->getDescription(), + $task->getName(), + $exception->getMessage() + ) + ); $this->statusCode = 190; } } @@ -229,7 +258,15 @@ class DeployCommand extends AbstractCommand $alertColor = 'green'; } - $output->writeln(sprintf(' Finished %d/%d tasks for %s.', $alertColor, $succeededTasks, $totalTasks, $this->getStageName())); + $output->writeln( + sprintf( + ' Finished %d/%d tasks for %s.', + $alertColor, + $succeededTasks, + $totalTasks, + $this->getStageName() + ) + ); $output->writeln(''); return ($succeededTasks == $totalTasks); @@ -238,8 +275,11 @@ class DeployCommand extends AbstractCommand /** * Exception for halting the the current process */ - protected function getException() + protected function getException(): RuntimeException { - return new RuntimeException(sprintf('Stage "%s" did not finished successfully, halting command.', $this->getStageName()), 50); + return new RuntimeException( + sprintf('Stage "%s" did not finished successfully, halting command.', $this->getStageName()), + 50 + ); } } diff --git a/src/Command/BuiltIn/Releases/ListCommand.php b/src/Command/BuiltIn/Releases/ListCommand.php index 3b5b780..294afff 100644 --- a/src/Command/BuiltIn/Releases/ListCommand.php +++ b/src/Command/BuiltIn/Releases/ListCommand.php @@ -1,4 +1,5 @@ setName('releases:list') ->setDescription('List the releases on an environment') - ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to') - ; + ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to'); } /** * Execute the Command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int|mixed */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->requireConfig(); @@ -102,7 +93,9 @@ class ListCommand extends AbstractCommand } if (count($releases) == 0) { - $output->writeln(sprintf(' No releases available on host %s:', $host)); + $output->writeln( + sprintf(' No releases available on host %s:', $host) + ); } else { // Get Current Release $cmdCurrentRelease = sprintf('readlink -f %s/current', $hostPath); @@ -110,7 +103,10 @@ class ListCommand extends AbstractCommand /** @var Process $process */ $process = $this->runtime->runRemoteCommand($cmdCurrentRelease, false); if (!$process->isSuccessful()) { - throw new RuntimeException(sprintf('Unable to retrieve current release from host "%s"', $host), 85); + throw new RuntimeException( + sprintf('Unable to retrieve current release from host "%s"', $host), + 85 + ); } $currentReleaseId = explode('/', trim($process->getOutput())); @@ -121,7 +117,8 @@ class ListCommand extends AbstractCommand foreach ($releases as $releaseId) { $releaseDate = $utils->getReleaseDate($releaseId); - $output->write(sprintf(' Release ID: %s - Date: %s [%s]', + $output->write(sprintf( + ' Release ID: %s - Date: %s [%s]', $releaseId, $releaseDate->format('Y-m-d H:i:s'), $utils->getTimeDiff($releaseDate) @@ -146,6 +143,6 @@ class ListCommand extends AbstractCommand $output->writeln('Finished Magallanes'); - return $this->statusCode; + return intval($this->statusCode); } } diff --git a/src/Command/BuiltIn/Releases/RollbackCommand.php b/src/Command/BuiltIn/Releases/RollbackCommand.php index 4837aa4..c27fe96 100644 --- a/src/Command/BuiltIn/Releases/RollbackCommand.php +++ b/src/Command/BuiltIn/Releases/RollbackCommand.php @@ -1,4 +1,5 @@ setName('releases:rollback') ->setDescription('Rollback to a release on an environment') ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to') - ->addArgument('release', InputArgument::REQUIRED, 'The ID or the Index of the release to rollback to') - ; + ->addArgument('release', InputArgument::REQUIRED, 'The ID or the Index of the release to rollback to'); } /** * Execute the Command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int|mixed */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->requireConfig(); @@ -68,11 +59,14 @@ class RollbackCommand extends DeployCommand } $releaseToRollback = $input->getArgument('release'); - if (($releaseId = $this->checkReleaseAvailability($releaseToRollback)) === false) { - throw new RuntimeException(sprintf('Release "%s" is not available on all hosts', $releaseToRollback), 72); + if ($this->checkReleaseAvailability($releaseToRollback) === false) { + throw new RuntimeException( + sprintf('Release "%s" is not available on all hosts', $releaseToRollback), + 72 + ); } - $this->runtime->setReleaseId($releaseId)->setRollback(true); + $this->runtime->setReleaseId($releaseToRollback)->setRollback(true); $output->writeln(sprintf(' Environment: %s', $this->runtime->getEnvironment())); $this->log(sprintf('Environment: %s', $this->runtime->getEnvironment())); @@ -95,16 +89,13 @@ class RollbackCommand extends DeployCommand $output->writeln('Finished Magallanes'); - return $this->statusCode; + return intval($this->statusCode); } /** * Check if the provided Release ID is available in all hosts - * - * @param string $releaseToRollback Release ID - * @return bool */ - protected function checkReleaseAvailability($releaseToRollback) + protected function checkReleaseAvailability(string $releaseToRollback): bool { $hosts = $this->runtime->getEnvOption('hosts'); $hostPath = rtrim($this->runtime->getEnvOption('host_path'), '/'); @@ -132,7 +123,7 @@ class RollbackCommand extends DeployCommand } if ($availableInHosts === count($hosts)) { - return $releaseToRollback; + return (bool) $releaseToRollback; } return false; diff --git a/src/Command/BuiltIn/VersionCommand.php b/src/Command/BuiltIn/VersionCommand.php index f5a1a0f..df65e44 100644 --- a/src/Command/BuiltIn/VersionCommand.php +++ b/src/Command/BuiltIn/VersionCommand.php @@ -1,4 +1,5 @@ setName('version') - ->setDescription('Get the version of Magallanes') - ; + ->setDescription('Get the version of Magallanes'); } /** * Executes the Command - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln(sprintf('Magallanes v%s [%s]', Mage::VERSION, Mage::CODENAME)); - return 0; + return self::SUCCESS; } } diff --git a/src/Deploy/Strategy/ReleasesStrategy.php b/src/Deploy/Strategy/ReleasesStrategy.php index 132fdd0..800ab55 100644 --- a/src/Deploy/Strategy/ReleasesStrategy.php +++ b/src/Deploy/Strategy/ReleasesStrategy.php @@ -1,4 +1,5 @@ runtime = $runtime; } - public function getPreDeployTasks() + public function getPreDeployTasks(): array { $this->checkStage(Runtime::PRE_DEPLOY); $tasks = $this->runtime->getTasks(); @@ -51,7 +49,7 @@ class ReleasesStrategy implements StrategyInterface return $tasks; } - public function getOnDeployTasks() + public function getOnDeployTasks(): array { $this->checkStage(Runtime::ON_DEPLOY); $tasks = $this->runtime->getTasks(); @@ -67,7 +65,7 @@ class ReleasesStrategy implements StrategyInterface return $tasks; } - public function getOnReleaseTasks() + public function getOnReleaseTasks(): array { $this->checkStage(Runtime::ON_RELEASE); $tasks = $this->runtime->getTasks(); @@ -79,7 +77,7 @@ class ReleasesStrategy implements StrategyInterface return $tasks; } - public function getPostReleaseTasks() + public function getPostReleaseTasks(): array { $this->checkStage(Runtime::POST_RELEASE); $tasks = $this->runtime->getTasks(); @@ -91,7 +89,7 @@ class ReleasesStrategy implements StrategyInterface return $tasks; } - public function getPostDeployTasks() + public function getPostDeployTasks(): array { $this->checkStage(Runtime::POST_DEPLOY); $tasks = $this->runtime->getTasks(); @@ -110,13 +108,14 @@ class ReleasesStrategy implements StrategyInterface /** * Check the runtime stage is correct * - * @param string $stage * @throws RuntimeException */ - private function checkStage($stage) + private function checkStage(string $stage): void { if ($this->runtime->getStage() !== $stage) { - throw new RuntimeException(sprintf('Invalid stage, got "%s" but expected "%s"', $this->runtime->getStage(), $stage)); + throw new RuntimeException( + sprintf('Invalid stage, got "%s" but expected "%s"', $this->runtime->getStage(), $stage) + ); } } } diff --git a/src/Deploy/Strategy/RsyncStrategy.php b/src/Deploy/Strategy/RsyncStrategy.php index 2be748e..c7b5f1a 100644 --- a/src/Deploy/Strategy/RsyncStrategy.php +++ b/src/Deploy/Strategy/RsyncStrategy.php @@ -1,4 +1,5 @@ runtime = $runtime; } - public function getPreDeployTasks() + public function getPreDeployTasks(): array { $this->checkStage(Runtime::PRE_DEPLOY); $tasks = $this->runtime->getTasks(); @@ -47,7 +45,7 @@ class RsyncStrategy implements StrategyInterface return $tasks; } - public function getOnDeployTasks() + public function getOnDeployTasks(): array { $this->checkStage(Runtime::ON_DEPLOY); $tasks = $this->runtime->getTasks(); @@ -59,17 +57,17 @@ class RsyncStrategy implements StrategyInterface return $tasks; } - public function getOnReleaseTasks() + public function getOnReleaseTasks(): array { return []; } - public function getPostReleaseTasks() + public function getPostReleaseTasks(): array { return []; } - public function getPostDeployTasks() + public function getPostDeployTasks(): array { $this->checkStage(Runtime::POST_DEPLOY); $tasks = $this->runtime->getTasks(); @@ -84,13 +82,14 @@ class RsyncStrategy implements StrategyInterface /** * Check the runtime stage is correct * - * @param $stage * @throws RuntimeException */ - private function checkStage($stage) + private function checkStage(string $stage): void { if ($this->runtime->getStage() !== $stage) { - throw new RuntimeException(sprintf('Invalid stage, got "%s" but expected "%s"', $this->runtime->getStage(), $stage)); + throw new RuntimeException( + sprintf('Invalid stage, got "%s" but expected "%s"', $this->runtime->getStage(), $stage) + ); } } } diff --git a/src/Deploy/Strategy/StrategyInterface.php b/src/Deploy/Strategy/StrategyInterface.php index 6bd9c77..9da78df 100644 --- a/src/Deploy/Strategy/StrategyInterface.php +++ b/src/Deploy/Strategy/StrategyInterface.php @@ -1,4 +1,5 @@ addListener(ConsoleEvents::ERROR, function (ConsoleErrorEvent $event) { $output = $event->getOutput(); $command = $event->getCommand(); - $output->writeln(sprintf('Oops, exception thrown while running command %s', $command->getName())); + $output->writeln( + sprintf('Oops, exception thrown while running command %s', $command->getName()) + ); $exitCode = $event->getExitCode(); $event->setError(new \LogicException('Caught exception', $exitCode, $event->getError())); }); @@ -63,7 +65,7 @@ class MageApplication extends Application * * @throws RuntimeException */ - public function configure() + public function configure(): void { if (!file_exists($this->file) || !is_readable($this->file)) { throw new RuntimeException(sprintf('The file "%s" does not exists or is not readable.', $this->file)); @@ -78,15 +80,22 @@ class MageApplication extends Application if (array_key_exists('magephp', $config) && is_array($config['magephp'])) { $logger = null; - if (array_key_exists('log_dir', $config['magephp']) && file_exists($config['magephp']['log_dir']) && is_dir($config['magephp']['log_dir'])) { + if ( + array_key_exists('log_dir', $config['magephp']) && + file_exists($config['magephp']['log_dir']) && is_dir($config['magephp']['log_dir']) + ) { $logfile = sprintf('%s/%s.log', $config['magephp']['log_dir'], date('Ymd_His')); $config['magephp']['log_file'] = $logfile; $logger = new Logger('magephp'); $logger->pushHandler(new StreamHandler($logfile)); - } elseif (array_key_exists('log_dir', $config['magephp']) && !is_dir($config['magephp']['log_dir'])) { - throw new RuntimeException(sprintf('The configured log_dir "%s" does not exists or is not a directory.', $config['magephp']['log_dir'])); + throw new RuntimeException( + sprintf( + 'The configured log_dir "%s" does not exists or is not a directory.', + $config['magephp']['log_dir'] + ) + ); } $this->runtime->setConfiguration($config['magephp']); @@ -94,13 +103,15 @@ class MageApplication extends Application return; } - throw new RuntimeException(sprintf('The file "%s" does not have a valid Magallanes configuration.', $this->file)); + throw new RuntimeException( + sprintf('The file "%s" does not have a valid Magallanes configuration.', $this->file) + ); } /** * Loads the BuiltIn Commands */ - protected function loadBuiltInCommands() + protected function loadBuiltInCommands(): void { $finder = new Finder(); $finder->files()->in(__DIR__ . '/Command/BuiltIn')->name('*Command.php'); @@ -109,7 +120,7 @@ class MageApplication extends Application foreach ($finder as $file) { $class = substr('\\Mage\\Command\\BuiltIn\\' . str_replace('/', '\\', $file->getRelativePathname()), 0, -4); if (class_exists($class)) { - $reflex = new ReflectionClass($class); + $reflex = new \ReflectionClass($class); if ($reflex->isInstantiable()) { $command = new $class(); if ($command instanceof AbstractCommand) { @@ -123,20 +134,16 @@ class MageApplication extends Application /** * Gets the Runtime instance to use - * - * @return Runtime */ - protected function instantiateRuntime() + protected function instantiateRuntime(): Runtime { return new Runtime(); } /** * Get the Runtime instance - * - * @return Runtime */ - public function getRuntime() + public function getRuntime(): Runtime { return $this->runtime; } diff --git a/src/Runtime/Exception/RuntimeException.php b/src/Runtime/Exception/RuntimeException.php index 5b0fc75..a7dd09f 100644 --- a/src/Runtime/Exception/RuntimeException.php +++ b/src/Runtime/Exception/RuntimeException.php @@ -1,4 +1,5 @@ */ -class RuntimeException extends Exception +class RuntimeException extends \Exception { } diff --git a/src/Runtime/Runtime.php b/src/Runtime/Runtime.php index e1f026a..ba483f5 100644 --- a/src/Runtime/Runtime.php +++ b/src/Runtime/Runtime.php @@ -1,4 +1,5 @@ Magallanes configuration */ - protected $configuration = []; + protected array $configuration = []; /** * @var string|null Environment being deployed */ - protected $environment; + protected ?string $environment = null; /** - * @var string Stage of Deployment + * @var string|null Stage of Deployment */ - protected $stage; + protected ?string $stage = null; /** * @var string|null The host being deployed to */ - protected $workingHost = null; + protected ?string $workingHost = null; /** * @var string|null The Release ID */ - protected $releaseId = null; + protected ?string $releaseId = null; /** - * @var array Hold a bag of variables for sharing information between tasks, if needed + * @var array Hold a bag of variables for sharing information between tasks, if needed */ protected $vars = []; - /** - * @var LoggerInterface|null The logger instance - */ - protected $logger; + protected ?LoggerInterface $logger = null; /** * @var bool Indicates if a Rollback operation is in progress */ - protected $rollback = false; + protected bool $rollback = false; - public function isWindows() + public function isWindows(): bool { return stripos(PHP_OS, 'WIN') === 0; } /** * Generate the Release ID - * - * @return Runtime */ - public function generateReleaseId() + public function generateReleaseId(): self { $this->setReleaseId(date('YmdHis')); return $this; @@ -89,11 +86,8 @@ class Runtime /** * Sets the Release ID - * - * @param string $releaseId Release ID - * @return Runtime */ - public function setReleaseId($releaseId) + public function setReleaseId(string $releaseId): self { $this->releaseId = $releaseId; return $this; @@ -101,21 +95,16 @@ class Runtime /** * Retrieve the current Release ID - * - * @return null|string Release ID */ - public function getReleaseId() + public function getReleaseId(): ?string { return $this->releaseId; } /** * Sets the Runtime in Rollback mode On or Off - * - * @param bool $inRollback - * @return Runtime */ - public function setRollback($inRollback) + public function setRollback(bool $inRollback): self { $this->rollback = $inRollback; return $this; @@ -123,35 +112,25 @@ class Runtime /** * Indicates if Runtime is in rollback - * - * @return bool */ - public function inRollback() + public function inRollback(): bool { return $this->rollback; } /** * Sets a value in the Vars bag - * - * @param string $key Variable name - * @param string $value Variable value - * @return Runtime */ - public function setVar($key, $value) + public function setVar(string $key, string $value): self { $this->vars[$key] = $value; return $this; } /** - * Retrieve a value from the Vars bag - * - * @param string $key Variable name - * @param mixed $default Variable default value, returned if not found - * @return string + * Retrieve a value from the Vars bag, or a default (null) if not set */ - public function getVar($key, $default = null) + public function getVar(string $key, mixed $default = null): ?string { if (array_key_exists($key, $this->vars)) { return $this->vars[$key]; @@ -162,11 +141,8 @@ class Runtime /** * Sets the Logger instance - * - * @param LoggerInterface $logger Logger instance - * @return Runtime */ - public function setLogger(LoggerInterface $logger = null) + public function setLogger(?LoggerInterface $logger = null): self { $this->logger = $logger; return $this; @@ -175,10 +151,9 @@ class Runtime /** * Sets the Magallanes Configuration to the Runtime * - * @param array $configuration Configuration - * @return Runtime + * @param array $configuration */ - public function setConfiguration($configuration) + public function setConfiguration(array $configuration): self { $this->configuration = $configuration; return $this; @@ -187,21 +162,17 @@ class Runtime /** * Retrieve the Configuration * - * @return array + * @return array $configuration */ - public function getConfiguration() + public function getConfiguration(): array { return $this->configuration; } /** * Retrieves the Configuration Option for a specific section in the configuration - * - * @param string $key Section name - * @param mixed $default Default value - * @return mixed */ - public function getConfigOption($key, $default = null) + public function getConfigOption(string $key, mixed $default = null): mixed { if (array_key_exists($key, $this->configuration)) { return $this->configuration[$key]; @@ -212,14 +183,13 @@ class Runtime /** * Returns the Configuration Option for a specific section the current Environment - * - * @param string $key Section/Parameter name - * @param mixed $default Default value - * @return mixed */ - public function getEnvOption($key, $default = null) + public function getEnvOption(string $key, mixed $default = null): mixed { - if (!array_key_exists('environments', $this->configuration) || !is_array($this->configuration['environments'])) { + if ( + !array_key_exists('environments', $this->configuration) || + !is_array($this->configuration['environments']) + ) { return $default; } @@ -238,12 +208,10 @@ class Runtime * Shortcut to get the the configuration option for a specific environment and merge it with * the global one (environment specific overrides the global one if present). * - * @param $key - * @param array $defaultEnv - * - * @return array + * @param array $defaultEnv + * @return array */ - public function getMergedOption($key, $defaultEnv = []) + public function getMergedOption(string $key, array $defaultEnv = []): array { $userGlobalOptions = $this->getConfigOption($key, $defaultEnv); $userEnvOptions = $this->getEnvOption($key, $defaultEnv); @@ -256,12 +224,8 @@ class Runtime /** * Overwrites an Environment Configuration Option - * - * @param string $key - * @param mixed $value - * @return Runtime */ - public function setEnvOption($key, $value) + public function setEnvOption(string $key, mixed $value): self { if (array_key_exists('environments', $this->configuration) && is_array($this->configuration['environments'])) { if (array_key_exists($this->environment, $this->configuration['environments'])) { @@ -275,13 +239,14 @@ class Runtime /** * Sets the working Environment * - * @param string $environment Environment name - * @return Runtime * @throws RuntimeException */ - public function setEnvironment($environment) + public function setEnvironment(string $environment): self { - if (array_key_exists('environments', $this->configuration) && array_key_exists($environment, $this->configuration['environments'])) { + if ( + array_key_exists('environments', $this->configuration) && + array_key_exists($environment, $this->configuration['environments']) + ) { $this->environment = $environment; return $this; } @@ -291,21 +256,16 @@ class Runtime /** * Returns the current working Environment - * - * @return null|string */ - public function getEnvironment() + public function getEnvironment(): ?string { return $this->environment; } /** * Sets the working stage - * - * @param string $stage Stage code - * @return Runtime */ - public function setStage($stage) + public function setStage(string $stage): self { $this->stage = $stage; return $this; @@ -313,10 +273,8 @@ class Runtime /** * Retrieve the current working Stage - * - * @return string */ - public function getStage() + public function getStage(): ?string { return $this->stage; } @@ -324,11 +282,14 @@ class Runtime /** * Retrieve the defined Tasks for the current Environment and Stage * - * @return array + * @return string[] */ - public function getTasks() + public function getTasks(): array { - if (!array_key_exists('environments', $this->configuration) || !is_array($this->configuration['environments'])) { + if ( + !array_key_exists('environments', $this->configuration) || + !is_array($this->configuration['environments']) + ) { return []; } @@ -347,11 +308,8 @@ class Runtime /** * Sets the working Host - * - * @param string $host Host name - * @return Runtime */ - public function setWorkingHost($host) + public function setWorkingHost(?string $host): self { $this->workingHost = $host; return $this; @@ -359,21 +317,16 @@ class Runtime /** * Retrieve the working Host - * - * @return null|string */ - public function getWorkingHost() + public function getWorkingHost(): ?string { return $this->workingHost; } /** * Logs a Message into the Logger - * - * @param string $message Log message - * @param string $level Log Level */ - public function log($message, $level = LogLevel::DEBUG) + public function log(string $message, string $level = LogLevel::DEBUG): void { if ($this->logger instanceof LoggerInterface) { $this->logger->log($level, $message); @@ -382,12 +335,8 @@ class Runtime /** * Executes a command, it will be run Locally or Remotely based on the working Stage - * - * @param string $cmd Command to execute - * @param int $timeout Seconds to wait - * @return Process */ - public function runCommand($cmd, $timeout = 120) + public function runCommand(string $cmd, int $timeout = 120): Process { switch ($this->getStage()) { case self::ON_DEPLOY: @@ -401,12 +350,8 @@ class Runtime /** * Execute a command locally - * - * @param string $cmd Command to execute - * @param int $timeout Seconds to wait - * @return Process */ - public function runLocalCommand($cmd, $timeout = 120) + public function runLocalCommand(string $cmd, int $timeout = 120): Process { $this->log($cmd, LogLevel::INFO); @@ -424,13 +369,8 @@ class Runtime /** * Executes a command remotely, if jail is true, it will run inside the Host Path and the Release (if available) - * - * @param string $cmd Command to execute - * @param bool $jail Jail the command - * @param int $timeout Seconds to wait - * @return Process */ - public function runRemoteCommand($cmd, $jail, $timeout = 120) + public function runRemoteCommand(string $cmd, bool $jail, int $timeout = 120): Process { $user = $this->getEnvOption('user', $this->getCurrentUser()); $sudo = $this->getEnvOption('sudo', false); @@ -450,7 +390,14 @@ class Runtime } $cmdRemote = str_replace('"', '\"', $cmdDelegate); - $cmdLocal = sprintf('ssh -p %d %s %s@%s "%s"', $sshConfig['port'], $sshConfig['flags'], $user, $host, $cmdRemote); + $cmdLocal = sprintf( + 'ssh -p %d %s %s@%s "%s"', + $sshConfig['port'], + $sshConfig['flags'], + $user, + $host, + $cmdRemote + ); return $this->runLocalCommand($cmdLocal, $timeout); } @@ -458,11 +405,17 @@ class Runtime /** * Get the SSH configuration based on the environment * - * @return array + * @return array */ - public function getSSHConfig() + public function getSSHConfig(): array { - $sshConfig = $this->getEnvOption('ssh', ['port' => 22, 'flags' => '-q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no']); + $sshConfig = $this->getEnvOption( + 'ssh', + [ + 'port' => 22, + 'flags' => '-q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' + ] + ); if ($this->getHostPort() !== null) { $sshConfig['port'] = $this->getHostPort(); @@ -485,46 +438,38 @@ class Runtime /** * Get the current Host Port or default ssh port - * - * @return integer */ - public function getHostPort() + public function getHostPort(): ?int { $info = explode(':', $this->getWorkingHost()); - return isset($info[1]) ? $info[1] : null; + return isset($info[1]) ? intval($info[1]) : null; } /** * Get the current Host Name - * - * @return string */ - public function getHostName() + public function getHostName(): ?string { if (strpos($this->getWorkingHost(), ':') === false) { return $this->getWorkingHost(); } $info = explode(':', $this->getWorkingHost()); - return $info[0]; + return strval($info[0]); } /** * Gets a Temporal File name - * - * @return string */ - public function getTempFile() + public function getTempFile(): string { return tempnam(sys_get_temp_dir(), 'mage'); } /** * Get the current user - * - * @return string */ - public function getCurrentUser() + public function getCurrentUser(): string { $userData = posix_getpwuid(posix_geteuid()); return $userData['name']; @@ -533,19 +478,17 @@ class Runtime /** * Shortcut for getting Branch information * - * @return boolean|string + * @return bool|string */ - public function getBranch() + public function getBranch(): mixed { return $this->getEnvOption('branch', false); } /** * Guesses the Deploy Strategy to use - * - * @return StrategyInterface */ - public function guessStrategy() + public function guessStrategy(): StrategyInterface { $strategy = new RsyncStrategy(); diff --git a/src/Task/AbstractTask.php b/src/Task/AbstractTask.php index ee03134..af22a50 100644 --- a/src/Task/AbstractTask.php +++ b/src/Task/AbstractTask.php @@ -1,4 +1,5 @@ */ + protected array $options = []; - /** - * @var Runtime - */ - protected $runtime; + protected Runtime $runtime; /** * Get the Name/Code of the Task - * - * @return string */ - abstract public function getName(); + abstract public function getName(): string; /** * Get a short Description of the Task - * - * @return string */ - abstract public function getDescription(); + abstract public function getDescription(): string; /** * Executes the Command - * - * @return bool */ - abstract public function execute(); + abstract public function execute(): bool; /** * Set additional Options for the Task * - * @param array $options Options - * @return AbstractTask + * @param array $options */ - public function setOptions($options = []) + public function setOptions(array $options = []): self { - if (!is_array($options)) { - $options = []; - } - $this->options = array_merge($this->getDefaults(), $options); return $this; } /** * Set the Runtime instance - * - * @param Runtime $runtime - * @return AbstractTask */ - public function setRuntime(Runtime $runtime) + public function setRuntime(Runtime $runtime): self { $this->runtime = $runtime; return $this; @@ -80,9 +62,10 @@ abstract class AbstractTask /** * Return Default options - * @return array + * + * @return array */ - public function getDefaults() + public function getDefaults(): array { return []; } diff --git a/src/Task/BuiltIn/Composer/AbstractComposerTask.php b/src/Task/BuiltIn/Composer/AbstractComposerTask.php index bce2234..2e98687 100644 --- a/src/Task/BuiltIn/Composer/AbstractComposerTask.php +++ b/src/Task/BuiltIn/Composer/AbstractComposerTask.php @@ -1,4 +1,5 @@ 'composer'], @@ -31,7 +35,10 @@ abstract class AbstractComposerTask extends AbstractTask return $options; } - protected function getComposerOptions() + /** + * @return array + */ + protected function getComposerOptions(): array { return []; } diff --git a/src/Task/BuiltIn/Composer/DumpAutoloadTask.php b/src/Task/BuiltIn/Composer/DumpAutoloadTask.php index 4e09bce..87dbfd5 100644 --- a/src/Task/BuiltIn/Composer/DumpAutoloadTask.php +++ b/src/Task/BuiltIn/Composer/DumpAutoloadTask.php @@ -1,4 +1,5 @@ getOptions(); $cmd = sprintf('%s dump-autoload %s', $options['path'], $options['flags']); @@ -40,7 +41,7 @@ class DumpAutoloadTask extends AbstractComposerTask return $process->isSuccessful(); } - protected function getComposerOptions() + protected function getComposerOptions(): array { return ['flags' => '--optimize']; } diff --git a/src/Task/BuiltIn/Composer/InstallTask.php b/src/Task/BuiltIn/Composer/InstallTask.php index 55a6a8d..a03f792 100644 --- a/src/Task/BuiltIn/Composer/InstallTask.php +++ b/src/Task/BuiltIn/Composer/InstallTask.php @@ -1,4 +1,5 @@ getOptions(); $cmd = sprintf('%s install %s', $options['path'], $options['flags']); /** @var Process $process */ - $process = $this->runtime->runCommand(trim($cmd), $options['timeout']); + $process = $this->runtime->runCommand(trim($cmd), intval($options['timeout'])); return $process->isSuccessful(); } - protected function getComposerOptions() + protected function getComposerOptions(): array { return ['flags' => '--optimize-autoloader', 'timeout' => 120]; } diff --git a/src/Task/BuiltIn/Composer/SelfUpdateTask.php b/src/Task/BuiltIn/Composer/SelfUpdateTask.php deleted file mode 100644 index a151d95..0000000 --- a/src/Task/BuiltIn/Composer/SelfUpdateTask.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Mage\Task\BuiltIn\Composer; - -use Mage\Task\Exception\SkipException; -use Symfony\Component\Process\Process; -use DateTime; - -/** - * Composer Task - Self update - * - * @author Yanick Witschi - */ -class SelfUpdateTask extends AbstractComposerTask -{ - public function getName() - { - return 'composer/self-update'; - } - - public function getDescription() - { - return '[Composer] Self Update'; - } - - public function execute() - { - $options = $this->getOptions(); - $cmdVersion = sprintf('%s --version', $options['path']); - /** @var Process $process */ - $process = $this->runtime->runCommand(trim($cmdVersion)); - if (!$process->isSuccessful()) { - return false; - } - - $buildDate = $this->getBuildDate($process->getOutput()); - if (!$buildDate instanceof DateTime) { - return false; - } - - $compareDate = $this->getCompareDate(); - if ($buildDate >= $compareDate) { - throw new SkipException(); - } - - $cmdUpdate = sprintf('%s self-update', $options['path']); - /** @var Process $process */ - $process = $this->runtime->runCommand(trim($cmdUpdate)); - - return $process->isSuccessful(); - } - - protected function getBuildDate($output) - { - $buildDate = null; - $output = explode("\n", $output); - foreach ($output as $row) { - if (strpos($row, 'Composer version ') === 0) { - $buildDate = DateTime::createFromFormat('Y-m-d H:i:s', substr(trim($row), -19)); - } - } - - return $buildDate; - } - - protected function getCompareDate() - { - $options = $this->getOptions(); - $compareDate = new DateTime(); - $compareDate->modify(sprintf('now -%d days', $options['days'])); - return $compareDate; - } - - protected function getComposerOptions() - { - return ['days' => 60]; - } -} diff --git a/src/Task/BuiltIn/Deploy/Release/CleanupTask.php b/src/Task/BuiltIn/Deploy/Release/CleanupTask.php index 30039e1..9abcaf6 100644 --- a/src/Task/BuiltIn/Deploy/Release/CleanupTask.php +++ b/src/Task/BuiltIn/Deploy/Release/CleanupTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('host_path'), '/'); $currentReleaseId = $this->runtime->getReleaseId(); diff --git a/src/Task/BuiltIn/Deploy/Release/PrepareTask.php b/src/Task/BuiltIn/Deploy/Release/PrepareTask.php index 74117b5..edf81e8 100644 --- a/src/Task/BuiltIn/Deploy/Release/PrepareTask.php +++ b/src/Task/BuiltIn/Deploy/Release/PrepareTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('host_path'), '/'); diff --git a/src/Task/BuiltIn/Deploy/ReleaseTask.php b/src/Task/BuiltIn/Deploy/ReleaseTask.php index ab767f0..fdc404a 100644 --- a/src/Task/BuiltIn/Deploy/ReleaseTask.php +++ b/src/Task/BuiltIn/Deploy/ReleaseTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('releases', false)) { throw new ErrorException('This task is only available with releases enabled', 40); @@ -44,7 +45,7 @@ class ReleaseTask extends AbstractTask implements ExecuteOnRollbackInterface $cmdLinkRelease = sprintf('cd %s && ln -snf releases/%s current', $hostPath, $releaseId); /** @var Process $process */ - $process = $this->runtime->runRemoteCommand($cmdLinkRelease, false, null); + $process = $this->runtime->runRemoteCommand($cmdLinkRelease, false, 0); return $process->isSuccessful(); } } diff --git a/src/Task/BuiltIn/Deploy/RsyncTask.php b/src/Task/BuiltIn/Deploy/RsyncTask.php index 1310a5a..c4598b6 100644 --- a/src/Task/BuiltIn/Deploy/RsyncTask.php +++ b/src/Task/BuiltIn/Deploy/RsyncTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('rsync', '-avz'); $sshConfig = $this->runtime->getSSHConfig(); @@ -46,14 +47,24 @@ class RsyncTask extends AbstractTask $excludes = $this->getExcludes(); $from = $this->runtime->getEnvOption('from', './'); - $cmdRsync = sprintf('rsync -e "ssh -p %d %s" %s %s %s %s@%s:%s', $sshConfig['port'], $sshConfig['flags'], $flags, $excludes, $from, $user, $host, $targetDir); + $cmdRsync = sprintf( + 'rsync -e "ssh -p %d %s" %s %s %s %s@%s:%s', + $sshConfig['port'], + $sshConfig['flags'], + $flags, + $excludes, + $from, + $user, + $host, + $targetDir + ); /** @var Process $process */ - $process = $this->runtime->runLocalCommand($cmdRsync, null); + $process = $this->runtime->runLocalCommand($cmdRsync, 0); return $process->isSuccessful(); } - protected function getExcludes() + protected function getExcludes(): string { $excludes = $this->runtime->getMergedOption('exclude', []); $excludes = array_merge(['.git'], array_filter($excludes)); diff --git a/src/Task/BuiltIn/Deploy/Tar/CleanupTask.php b/src/Task/BuiltIn/Deploy/Tar/CleanupTask.php index f538271..4355232 100644 --- a/src/Task/BuiltIn/Deploy/Tar/CleanupTask.php +++ b/src/Task/BuiltIn/Deploy/Tar/CleanupTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('releases', false)) { throw new ErrorException('This task is only available with releases enabled', 40); diff --git a/src/Task/BuiltIn/Deploy/Tar/CopyTask.php b/src/Task/BuiltIn/Deploy/Tar/CopyTask.php index 570cdbf..5c0f934 100644 --- a/src/Task/BuiltIn/Deploy/Tar/CopyTask.php +++ b/src/Task/BuiltIn/Deploy/Tar/CopyTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('releases', false)) { throw new ErrorException('This task is only available with releases enabled', 40); @@ -50,10 +51,19 @@ class CopyTask extends AbstractTask $tarLocal = $this->runtime->getVar('tar_local'); $tarRemote = basename($tarLocal); - $cmdCopy = sprintf('scp -P %d %s %s %s@%s:%s/%s', $sshConfig['port'], $sshConfig['flags'], $tarLocal, $user, $host, $targetDir, $tarRemote); + $cmdCopy = sprintf( + 'scp -P %d %s %s %s@%s:%s/%s', + $sshConfig['port'], + $sshConfig['flags'], + $tarLocal, + $user, + $host, + $targetDir, + $tarRemote + ); /** @var Process $process */ - $process = $this->runtime->runLocalCommand($cmdCopy, $sshConfig['timeout']); + $process = $this->runtime->runLocalCommand($cmdCopy, intval($sshConfig['timeout'])); if ($process->isSuccessful()) { $cmdUnTar = sprintf('cd %s && %s %s %s', $targetDir, $tarPath, $flags, $tarRemote); $process = $this->runtime->runRemoteCommand($cmdUnTar, false, 600); diff --git a/src/Task/BuiltIn/Deploy/Tar/PrepareTask.php b/src/Task/BuiltIn/Deploy/Tar/PrepareTask.php index e4c5daa..d1e853e 100644 --- a/src/Task/BuiltIn/Deploy/Tar/PrepareTask.php +++ b/src/Task/BuiltIn/Deploy/Tar/PrepareTask.php @@ -1,4 +1,5 @@ runtime->getEnvOption('releases', false)) { throw new ErrorException('This task is only available with releases enabled', 40); @@ -42,7 +43,10 @@ class PrepareTask extends AbstractTask $excludes = $this->getExcludes(); $tarPath = $this->runtime->getEnvOption('tar_create_path', 'tar'); - $flags = $this->runtime->getEnvOption('tar_create', $this->runtime->isWindows() ? '--force-local -c -z -p -f' : 'cfzp'); + $flags = $this->runtime->getEnvOption( + 'tar_create', + $this->runtime->isWindows() ? '--force-local -c -z -p -f' : 'cfzp' + ); $from = $this->runtime->getEnvOption('from', './'); if ($this->runtime->getEnvOption('copyDirectory', false)) { @@ -56,7 +60,7 @@ class PrepareTask extends AbstractTask return $process->isSuccessful(); } - protected function getExcludes() + protected function getExcludes(): string { $excludes = $this->runtime->getMergedOption('exclude', []); $excludes = array_merge(['.git'], array_filter($excludes)); diff --git a/src/Task/BuiltIn/ExecTask.php b/src/Task/BuiltIn/ExecTask.php index 0c7fc17..589e3f4 100644 --- a/src/Task/BuiltIn/ExecTask.php +++ b/src/Task/BuiltIn/ExecTask.php @@ -1,4 +1,5 @@ getOptions(); @@ -48,7 +49,7 @@ class ExecTask extends AbstractTask * * @throws ErrorException */ - public function execute() + public function execute(): bool { $options = $this->getOptions(); @@ -57,14 +58,14 @@ class ExecTask extends AbstractTask } /** @var Process $process */ - $process = $this->runtime->runCommand($options['cmd'], $options['timeout']); + $process = $this->runtime->runCommand(strval($options['cmd']), intval($options['timeout'])); return $process->isSuccessful(); } /** - * @return array + * @return array */ - protected function getOptions() + protected function getOptions(): array { $options = array_merge( ['cmd' => '', 'desc' => '', 'timeout' => 120], diff --git a/src/Task/BuiltIn/FS/AbstractFileTask.php b/src/Task/BuiltIn/FS/AbstractFileTask.php index 6243946..2ce5d2b 100644 --- a/src/Task/BuiltIn/FS/AbstractFileTask.php +++ b/src/Task/BuiltIn/FS/AbstractFileTask.php @@ -1,4 +1,5 @@ * @throws ErrorException */ - protected function getOptions() + protected function getOptions(): array { $mandatory = $this->getParameters(); $defaults = array_keys($this->getDefaults()); @@ -44,18 +45,16 @@ abstract class AbstractFileTask extends AbstractTask /** * Returns the mandatory parameters * - * @return array + * @return string[] */ - abstract protected function getParameters(); + abstract protected function getParameters(): array; /** * Returns a file with the placeholders replaced * - * @param string $file - * @return string * @throws ErrorException */ - protected function getFile($file) + protected function getFile(string $file): string { $mapping = [ '%environment%' => $this->runtime->getEnvironment(), @@ -73,7 +72,7 @@ abstract class AbstractFileTask extends AbstractTask return str_replace( array_keys($mapping), array_values($mapping), - $options[$file] + strval($options[$file]) ); } } diff --git a/src/Task/BuiltIn/FS/ChangeModeTask.php b/src/Task/BuiltIn/FS/ChangeModeTask.php index 1422c3f..7619c44 100644 --- a/src/Task/BuiltIn/FS/ChangeModeTask.php +++ b/src/Task/BuiltIn/FS/ChangeModeTask.php @@ -1,4 +1,5 @@ getFile('file'), $this->options['mode']); - } catch (Exception $exception) { + } catch (\Exception $exception) { return '[FS] Chmod [missing parameters]'; } } - public function execute() + public function execute(): bool { $file = $this->getFile('file'); $mode = $this->options['mode']; @@ -48,12 +48,12 @@ class ChangeModeTask extends AbstractFileTask return $process->isSuccessful(); } - protected function getParameters() + protected function getParameters(): array { return ['file', 'mode', 'flags']; } - public function getDefaults() + public function getDefaults(): array { return ['flags' => null]; } diff --git a/src/Task/BuiltIn/FS/CopyTask.php b/src/Task/BuiltIn/FS/CopyTask.php index 469b19c..eca25d8 100644 --- a/src/Task/BuiltIn/FS/CopyTask.php +++ b/src/Task/BuiltIn/FS/CopyTask.php @@ -1,4 +1,5 @@ getFile('from'), $this->getFile('to')); - } catch (Exception $exception) { + } catch (\Exception $exception) { return '[FS] Copy [missing parameters]'; } } - public function execute() + public function execute(): bool { $copyFrom = $this->getFile('from'); $copyTo = $this->getFile('to'); @@ -48,12 +48,12 @@ class CopyTask extends AbstractFileTask return $process->isSuccessful(); } - protected function getParameters() + protected function getParameters(): array { return ['from', 'to', 'flags']; } - public function getDefaults() + public function getDefaults(): array { return ['flags' => '-p']; } diff --git a/src/Task/BuiltIn/FS/LinkTask.php b/src/Task/BuiltIn/FS/LinkTask.php index 12721e0..5d5ed62 100644 --- a/src/Task/BuiltIn/FS/LinkTask.php +++ b/src/Task/BuiltIn/FS/LinkTask.php @@ -1,4 +1,5 @@ getFile('from'), $this->getFile('to')); - } catch (Exception $exception) { + } catch (\Exception $exception) { return '[FS] Link [missing parameters]'; } } - public function execute() + public function execute(): bool { $linkFrom = $this->getFile('from'); $linkTo = $this->getFile('to'); @@ -48,12 +48,12 @@ class LinkTask extends AbstractFileTask return $process->isSuccessful(); } - protected function getParameters() + protected function getParameters(): array { return ['from', 'to', 'flags']; } - public function getDefaults() + public function getDefaults(): array { return ['flags' => '-snf']; } diff --git a/src/Task/BuiltIn/FS/MoveTask.php b/src/Task/BuiltIn/FS/MoveTask.php index a13ecc1..bd8ce8f 100644 --- a/src/Task/BuiltIn/FS/MoveTask.php +++ b/src/Task/BuiltIn/FS/MoveTask.php @@ -1,4 +1,5 @@ getFile('from'), $this->getFile('to')); @@ -34,7 +35,7 @@ class MoveTask extends AbstractFileTask } } - public function execute() + public function execute(): bool { $moveFrom = $this->getFile('from'); $moveTo = $this->getFile('to'); @@ -48,12 +49,12 @@ class MoveTask extends AbstractFileTask return $process->isSuccessful(); } - protected function getParameters() + protected function getParameters(): array { return ['from', 'to', 'flags']; } - public function getDefaults() + public function getDefaults(): array { return ['flags' => null]; } diff --git a/src/Task/BuiltIn/FS/RemoveTask.php b/src/Task/BuiltIn/FS/RemoveTask.php index 1f90724..d37b585 100644 --- a/src/Task/BuiltIn/FS/RemoveTask.php +++ b/src/Task/BuiltIn/FS/RemoveTask.php @@ -1,4 +1,5 @@ getFile('file')); - } catch (Exception $exception) { + } catch (\Exception $exception) { return '[FS] Remove [missing parameters]'; } } - public function execute() + public function execute(): bool { $file = $this->getFile('file'); $flags = $this->options['flags']; @@ -47,12 +47,12 @@ class RemoveTask extends AbstractFileTask return $process->isSuccessful(); } - protected function getParameters() + protected function getParameters(): array { return ['file', 'flags']; } - public function getDefaults() + public function getDefaults(): array { return ['flags' => null]; } diff --git a/src/Task/BuiltIn/Git/ChangeBranchTask.php b/src/Task/BuiltIn/Git/ChangeBranchTask.php index 172207c..94a4756 100644 --- a/src/Task/BuiltIn/Git/ChangeBranchTask.php +++ b/src/Task/BuiltIn/Git/ChangeBranchTask.php @@ -1,4 +1,5 @@ getOptions(); $branch = $options['branch']; - if ($this->runtime->getVar('git_revert_branch', false)) { + if ($this->runtime->getVar('git_revert_branch', null)) { $branch = $this->runtime->getVar('git_revert_branch'); } return sprintf('[Git] Change Branch (%s)', $branch); } - public function execute() + public function execute(): bool { $options = $this->getOptions(); - $branch = $this->runtime->getVar('git_revert_branch', false); + /** @var string|bool */ + $branch = $this->runtime->getVar('git_revert_branch', null); - if ($branch === false) { + if (!$branch) { $cmdGetCurrent = sprintf('%s branch | grep "*"', $options['path']); /** @var Process $process */ @@ -68,7 +70,10 @@ class ChangeBranchTask extends AbstractTask return $process->isSuccessful(); } - protected function getOptions() + /** + * @return array + */ + protected function getOptions(): array { $branch = $this->runtime->getEnvOption('branch', 'master'); $options = array_merge( diff --git a/src/Task/BuiltIn/Git/UpdateTask.php b/src/Task/BuiltIn/Git/UpdateTask.php index 33aa8ac..44cfef0 100644 --- a/src/Task/BuiltIn/Git/UpdateTask.php +++ b/src/Task/BuiltIn/Git/UpdateTask.php @@ -1,4 +1,5 @@ getOptions(); $command = $options['path'] . ' pull'; - /** @var Process $process */ $process = $this->runtime->runLocalCommand($command); return $process->isSuccessful(); } - protected function getOptions() + /** + * @return array + */ + protected function getOptions(): array { $branch = $this->runtime->getEnvOption('branch', 'master'); $options = array_merge( diff --git a/src/Task/BuiltIn/Symfony/AbstractSymfonyTask.php b/src/Task/BuiltIn/Symfony/AbstractSymfonyTask.php index 6ee9475..ca22af5 100644 --- a/src/Task/BuiltIn/Symfony/AbstractSymfonyTask.php +++ b/src/Task/BuiltIn/Symfony/AbstractSymfonyTask.php @@ -1,4 +1,5 @@ + */ + protected function getOptions(): array { $options = array_merge( ['console' => 'bin/console', 'env' => 'dev', 'flags' => ''], @@ -31,7 +35,10 @@ abstract class AbstractSymfonyTask extends AbstractTask return $options; } - protected function getSymfonyOptions() + /** + * @return array + */ + protected function getSymfonyOptions(): array { return []; } diff --git a/src/Task/BuiltIn/Symfony/AssetsInstallTask.php b/src/Task/BuiltIn/Symfony/AssetsInstallTask.php index d13300a..f84c264 100644 --- a/src/Task/BuiltIn/Symfony/AssetsInstallTask.php +++ b/src/Task/BuiltIn/Symfony/AssetsInstallTask.php @@ -1,4 +1,5 @@ getOptions(); - $command = sprintf('%s assets:install %s --env=%s %s', $options['console'], $options['target'], $options['env'], $options['flags']); + $command = sprintf( + '%s assets:install %s --env=%s %s', + $options['console'], + $options['target'], + $options['env'], + $options['flags'] + ); - /** @var Process $process */ $process = $this->runtime->runCommand(trim($command)); return $process->isSuccessful(); } - protected function getSymfonyOptions() + protected function getSymfonyOptions(): array { return ['target' => 'web', 'flags' => '--symlink --relative']; } diff --git a/src/Task/BuiltIn/Symfony/CacheClearTask.php b/src/Task/BuiltIn/Symfony/CacheClearTask.php index a309ffa..3f12b05 100644 --- a/src/Task/BuiltIn/Symfony/CacheClearTask.php +++ b/src/Task/BuiltIn/Symfony/CacheClearTask.php @@ -1,4 +1,5 @@ getOptions(); $command = $options['console'] . ' cache:clear --env=' . $options['env'] . ' ' . $options['flags']; diff --git a/src/Task/BuiltIn/Symfony/CachePoolClearTask.php b/src/Task/BuiltIn/Symfony/CachePoolClearTask.php index bd83d88..d788258 100644 --- a/src/Task/BuiltIn/Symfony/CachePoolClearTask.php +++ b/src/Task/BuiltIn/Symfony/CachePoolClearTask.php @@ -1,4 +1,5 @@ getOptions(); @@ -38,7 +39,13 @@ class CachePoolClearTask extends AbstractSymfonyTask throw new ErrorException('Parameter "pools" is not defined'); } - $command = $options['console'] . ' cache:pool:clear ' . $options['pools'] . ' --env=' . $options['env'] . ' ' . $options['flags']; + $command = sprintf( + '%s cache:pool:clear %s --env=%s %s', + $options['console'], + $options['pools'], + $options['env'], + $options['flags'] + ); /** @var Process $process */ $process = $this->runtime->runCommand(trim($command)); @@ -46,7 +53,7 @@ class CachePoolClearTask extends AbstractSymfonyTask return $process->isSuccessful(); } - protected function getSymfonyOptions() + protected function getSymfonyOptions(): array { return ['pools' => null]; } diff --git a/src/Task/BuiltIn/Symfony/CachePoolPruneTask.php b/src/Task/BuiltIn/Symfony/CachePoolPruneTask.php index f8c07ac..4cf8c35 100644 --- a/src/Task/BuiltIn/Symfony/CachePoolPruneTask.php +++ b/src/Task/BuiltIn/Symfony/CachePoolPruneTask.php @@ -1,4 +1,5 @@ getOptions(); $command = $options['console'] . ' cache:pool:prune --env=' . $options['env'] . ' ' . $options['flags']; diff --git a/src/Task/BuiltIn/Symfony/CacheWarmupTask.php b/src/Task/BuiltIn/Symfony/CacheWarmupTask.php index d35f0a4..19b951b 100644 --- a/src/Task/BuiltIn/Symfony/CacheWarmupTask.php +++ b/src/Task/BuiltIn/Symfony/CacheWarmupTask.php @@ -1,4 +1,5 @@ getOptions(); $command = $options['console'] . ' cache:warmup --env=' . $options['env'] . ' ' . $options['flags']; diff --git a/src/Task/Exception/ErrorException.php b/src/Task/Exception/ErrorException.php index 56b4751..164dceb 100644 --- a/src/Task/Exception/ErrorException.php +++ b/src/Task/Exception/ErrorException.php @@ -1,4 +1,5 @@ */ -class ErrorException extends Exception +class ErrorException extends \Exception { - public function getTrimmedMessage($maxLength = 60) + public function getTrimmedMessage(int $maxLength = 60): string { $message = $this->getMessage(); diff --git a/src/Task/Exception/SkipException.php b/src/Task/Exception/SkipException.php index 4d23bb2..14868e3 100644 --- a/src/Task/Exception/SkipException.php +++ b/src/Task/Exception/SkipException.php @@ -1,4 +1,5 @@ */ -class SkipException extends Exception +class SkipException extends \Exception { } diff --git a/src/Task/ExecuteOnRollbackInterface.php b/src/Task/ExecuteOnRollbackInterface.php index 2c8fe81..5f8e732 100644 --- a/src/Task/ExecuteOnRollbackInterface.php +++ b/src/Task/ExecuteOnRollbackInterface.php @@ -1,4 +1,5 @@ setRuntime($this->runtime); $this->registeredTasks[$task->getName()] = $task; @@ -60,11 +54,10 @@ class TaskFactory * Get a Task by it's registered Name/Code, or it can be a Class Name, * in that case the class will be instantiated * - * @param string $name Name/Code or Class of the Task - * @return AbstractTask + * @param string|mixed[] $name * @throws RuntimeException */ - public function get($name) + public function get(mixed $name): AbstractTask { $options = []; if (is_array($name)) { @@ -96,14 +89,22 @@ class TaskFactory /** * Load BuiltIn Tasks */ - protected function loadBuiltInTasks() + protected function loadBuiltInTasks(): void { $finder = new Finder(); $finder->files()->in(__DIR__ . '/BuiltIn')->name('*Task.php'); /** @var SplFileInfo $file */ foreach ($finder as $file) { - $taskClass = substr('\\Mage\\Task\\BuiltIn\\' . str_replace('/', '\\', $file->getRelativePathname()), 0, -4); + $taskClass = substr( + '\\Mage\\Task\\BuiltIn\\' . str_replace( + '/', + '\\', + $file->getRelativePathname() + ), + 0, + -4 + ); if (class_exists($taskClass)) { $reflex = new ReflectionClass($taskClass); if ($reflex->isInstantiable()) { @@ -118,10 +119,11 @@ class TaskFactory /** * Load Custom Tasks - * @param array $tasksToLoad PreRegistered Tasks + * + * @param string[] $tasksToLoad * @throws RuntimeException */ - protected function loadCustomTasks($tasksToLoad) + protected function loadCustomTasks(array $tasksToLoad): void { foreach ($tasksToLoad as $taskClass) { if (!class_exists($taskClass)) { @@ -135,7 +137,9 @@ class TaskFactory $task = new $taskClass(); if (!$task instanceof AbstractTask) { - throw new RuntimeException(sprintf('Custom Task "%s" must inherit "Mage\\Task\\AbstractTask".', $taskClass)); + throw new RuntimeException( + sprintf('Custom Task "%s" must inherit "Mage\\Task\\AbstractTask".', $taskClass) + ); } // Add Task diff --git a/src/Utils.php b/src/Utils.php index 4dbe5ba..c90d223 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -1,4 +1,5 @@ diff($releaseDate); if ($diff->days > 7) { diff --git a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php index 7cb7cd9..bb94584 100755 --- a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php +++ b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php @@ -530,6 +530,55 @@ class DeployCommandWithReleasesTest extends TestCase $this->assertNotEquals(0, $tester->getStatusCode()); } + public function testDeploymentFailCleanupReleases() + { + $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost.yml'); + + $application->getRuntime()->setReleaseId('20170101015120'); + + /** @var AbstractCommand $command */ + $command = $application->find('deploy'); + $this->assertTrue($command instanceof DeployCommand); + + $application->getRuntime()->forceFail('ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015110"'); + + $tester = new CommandTester($command); + $tester->execute(['command' => $command->getName(), 'environment' => 'test']); + + $ranCommands = $application->getRuntime()->getRanCommands(); + + $testCase = array( + 0 => 'git branch | grep "*"', + 1 => 'git checkout test', + 2 => 'git pull', + 3 => 'composer install --optimize-autoloader', + 4 => 'composer dump-autoload --optimize', + 5 => 'tar cfzp /tmp/mageXYZ --exclude=".git" --exclude="./var/cache/*" --exclude="./var/log/*" --exclude="./web/app_dev.php" ./', + 6 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "mkdir -p /var/www/test/releases/1234567890"', + 7 => 'scp -P 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no /tmp/mageXYZ tester@testhost:/var/www/test/releases/1234567890/mageXYZ', + 8 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && tar xfzop mageXYZ"', + 9 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm /var/www/test/releases/1234567890/mageXYZ"', + 10 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:warmup --env=dev"', + 11 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console assets:install web --env=dev --symlink --relative"', + 12 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:pool:prune --env=dev"', + 13 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test && ln -snf releases/1234567890 current"', + 14 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "ls -1 /var/www/test/releases"', + 15 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015110"', + ); + + // Check total of Executed Commands + $this->assertEquals(count($testCase), count($ranCommands)); + + // Check Generated Commands + foreach ($testCase as $index => $command) { + $this->assertEquals($command, $ranCommands[$index]); + } + + $this->assertStringContainsString('Running [Release] Cleaning up old Releases ... FAIL', $tester->getDisplay()); + $this->assertStringContainsString('Stage "Post Release" did not finished successfully, halting command.', $tester->getDisplay()); + $this->assertNotEquals(0, $tester->getStatusCode()); + } + public function testDeploymentFailMidway() { $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost.yml'); diff --git a/tests/MageApplicationMockup.php b/tests/MageApplicationMockup.php index 674c195..c472cdd 100644 --- a/tests/MageApplicationMockup.php +++ b/tests/MageApplicationMockup.php @@ -20,7 +20,7 @@ class MageApplicationMockup extends MageApplication * * @return RuntimeMockup */ - protected function instantiateRuntime() + protected function instantiateRuntime(): RuntimeMockup { return new RuntimeMockup(); } diff --git a/tests/MageApplicationWindowsMockup.php b/tests/MageApplicationWindowsMockup.php index a1845ee..75472c1 100644 --- a/tests/MageApplicationWindowsMockup.php +++ b/tests/MageApplicationWindowsMockup.php @@ -12,6 +12,7 @@ namespace Mage\Tests; use Mage\Tests\Runtime\RuntimeWindowsMockup; use Mage\MageApplication; +use Mage\Runtime\Runtime; class MageApplicationWindowsMockup extends MageApplication { @@ -20,7 +21,7 @@ class MageApplicationWindowsMockup extends MageApplication * * @return RuntimeWindowsMockup */ - protected function instantiateRuntime() + protected function instantiateRuntime(): Runtime { return new RuntimeWindowsMockup(); } diff --git a/tests/Runtime/ProcessMockup.php b/tests/Runtime/ProcessMockup.php index ea6d529..4d638a1 100644 --- a/tests/Runtime/ProcessMockup.php +++ b/tests/Runtime/ProcessMockup.php @@ -24,9 +24,10 @@ class ProcessMockup extends Process $this->commandline = $commandline; } - public function setTimeout($timeout) + public function setTimeout(?float $timeout): static { $this->timeout = $timeout; + return $this; } public function run(callable $callback = null, array $env = array()): int @@ -58,17 +59,17 @@ class ProcessMockup extends Process return 0; } - public function isSuccessful() + public function isSuccessful(): bool { return $this->success; } - public function getErrorOutput() + public function getErrorOutput(): string { return ''; } - public function getOutput() + public function getOutput(): string { if ($this->commandline == 'git branch | grep "*"') { return '* master'; diff --git a/tests/Runtime/RuntimeMockup.php b/tests/Runtime/RuntimeMockup.php index 65b6c32..d74d903 100644 --- a/tests/Runtime/RuntimeMockup.php +++ b/tests/Runtime/RuntimeMockup.php @@ -31,10 +31,8 @@ class RuntimeMockup extends Runtime /** * Generate the Release ID - * - * @return Runtime */ - public function generateReleaseId() + public function generateReleaseId(): Runtime { $this->setReleaseId('1234567890'); return $this; @@ -42,12 +40,8 @@ class RuntimeMockup extends Runtime /** * Execute a command locally - * - * @param string $cmd Command to execute - * @param int $timeout Seconds to wait - * @return Process */ - public function runLocalCommand($cmd, $timeout = 120) + public function runLocalCommand(string $cmd, int $timeout = 120): Process { $this->ranCommands[] = $cmd; $this->ranCommandTimeouts[$cmd] = $timeout; @@ -62,10 +56,8 @@ class RuntimeMockup extends Runtime /** * Gets a Temporal File name - * - * @return string */ - public function getTempFile() + public function getTempFile(): string { return '/tmp/mageXYZ'; } @@ -76,13 +68,13 @@ class RuntimeMockup extends Runtime * @param string $environment * @return Runtime */ - public function setInvalidEnvironment($environment) + public function setInvalidEnvironment($environment): Runtime { $this->environment = $environment; return $this; } - public function forceFail($cmd) + public function forceFail($cmd): void { $this->forceFail[] = $cmd; } diff --git a/tests/Runtime/RuntimeWindowsMockup.php b/tests/Runtime/RuntimeWindowsMockup.php index 805031f..0a9c640 100644 --- a/tests/Runtime/RuntimeWindowsMockup.php +++ b/tests/Runtime/RuntimeWindowsMockup.php @@ -12,7 +12,7 @@ namespace Mage\Tests\Runtime; class RuntimeWindowsMockup extends RuntimeMockup { - public function isWindows() + public function isWindows(): bool { return true; } diff --git a/tests/Task/AbstractTaskTest.php b/tests/Task/AbstractTaskTest.php index 595ac41..3e64121 100644 --- a/tests/Task/AbstractTaskTest.php +++ b/tests/Task/AbstractTaskTest.php @@ -16,14 +16,6 @@ use PHPUnit\Framework\TestCase; class AbstractTaskTest extends TestCase { - public function testNotArrayOptions() - { - $task = new TestCaseTask(); - $task->setOptions('not an array'); - - $this->assertTrue(is_array($task->getOptions())); - } - public function testFailingTask() { $task = new TestCaseFailTask(); diff --git a/tests/Task/BuiltIn/Composer/BasicComposerTask.php b/tests/Task/BuiltIn/Composer/BasicComposerTask.php index 3261aef..55b1aab 100644 --- a/tests/Task/BuiltIn/Composer/BasicComposerTask.php +++ b/tests/Task/BuiltIn/Composer/BasicComposerTask.php @@ -20,17 +20,17 @@ use Symfony\Component\Process\Process; */ class BasicComposerTask extends AbstractComposerTask { - public function getName() + public function getName(): string { return 'composer/help'; } - public function getDescription() + public function getDescription(): string { return '[Composer] Help'; } - public function execute() + public function execute(): bool { $options = $this->getOptions(); $cmd = sprintf('%s help', $options['path']); diff --git a/tests/Task/BuiltIn/Composer/SelfUpdateTaskTest.php b/tests/Task/BuiltIn/Composer/SelfUpdateTaskTest.php deleted file mode 100644 index 880dec7..0000000 --- a/tests/Task/BuiltIn/Composer/SelfUpdateTaskTest.php +++ /dev/null @@ -1,174 +0,0 @@ -setConfiguration(['environments' => ['test' => []]]); - $runtime->setEnvironment('test'); - - $task = new SelfUpdateTask(); - $task->setOptions(['path' => 'composer']); - $task->setRuntime($runtime); - $this->assertEquals('[Composer] Self Update', $task->getDescription()); - - try { - $task->execute(); - } catch (Exception $exception) { - $this->assertTrue($exception instanceof SkipException, 'Update should been skipped'); - } - - $ranCommands = $runtime->getRanCommands(); - $testCase = array( - 0 => 'composer --version', - ); - - // Check total of Executed Commands - $this->assertEquals(count($testCase), count($ranCommands)); - - // Check Generated Commands - foreach ($testCase as $index => $command) { - $this->assertEquals($command, $ranCommands[$index]); - } - } - - public function testSelfUpdateAsRootTask() - { - $runtime = new RuntimeMockup(); - $runtime->setConfiguration(['environments' => ['test' => []]]); - $runtime->setEnvironment('test'); - - $task = new SelfUpdateTask(); - $task->setOptions(['path' => './composer']); - $task->setRuntime($runtime); - - try { - $task->execute(); - } catch (Exception $exception) { - $this->assertTrue($exception instanceof SkipException, 'Update should been skipped'); - } - - $ranCommands = $runtime->getRanCommands(); - $testCase = array( - 0 => './composer --version', - ); - - // Check total of Executed Commands - $this->assertEquals(count($testCase), count($ranCommands)); - - // Check Generated Commands - foreach ($testCase as $index => $command) { - $this->assertEquals($command, $ranCommands[$index]); - } - } - - public function testSelfUpdateMustUpdateTask() - { - $runtime = new RuntimeMockup(); - $runtime->setConfiguration(['environments' => ['test' => []]]); - $runtime->setEnvironment('test'); - - $task = new SelfUpdateTask(); - $task->setOptions(['path' => 'composer.phar']); - $task->setRuntime($runtime); - - try { - $result = $task->execute(); - $this->assertTrue($result, 'Result should be successful'); - } catch (Exception $exception) { - if ($exception instanceof SkipException) { - $this->assertTrue(false, 'Update should not have been skipped'); - } - } - - $ranCommands = $runtime->getRanCommands(); - $testCase = array( - 0 => 'composer.phar --version', - 1 => 'composer.phar self-update', - ); - - // Check total of Executed Commands - $this->assertEquals(count($testCase), count($ranCommands)); - - // Check Generated Commands - foreach ($testCase as $index => $command) { - $this->assertEquals($command, $ranCommands[$index]); - } - } - - public function testSelfUpdateWrongOutputTask() - { - $runtime = new RuntimeMockup(); - $runtime->setConfiguration(['environments' => ['test' => []]]); - $runtime->setEnvironment('test'); - - $task = new SelfUpdateTask(); - $task->setOptions(['path' => 'php composer']); - $task->setRuntime($runtime); - - try { - $result = $task->execute(); - $this->assertFalse($result, 'Result should be failure'); - } catch (Exception $exception) { - if ($exception instanceof SkipException) { - $this->assertTrue(false, 'Update should not have been skipped'); - } - } - - $ranCommands = $runtime->getRanCommands(); - $testCase = array( - 0 => 'php composer --version', - ); - - // Check total of Executed Commands - $this->assertEquals(count($testCase), count($ranCommands)); - - // Check Generated Commands - foreach ($testCase as $index => $command) { - $this->assertEquals($command, $ranCommands[$index]); - } - } - - public function testSelfUpdateFailExecTask() - { - $runtime = new RuntimeMockup(); - $runtime->setConfiguration(['environments' => ['test' => []]]); - $runtime->setEnvironment('test'); - - $task = new SelfUpdateTask(); - $task->setOptions(['path' => 'composer']); - $task->setRuntime($runtime); - $runtime->forceFail('composer --version'); - - try { - $result = $task->execute(); - $this->assertFalse($result, 'Result should be failure'); - } catch (Exception $exception) { - if ($exception instanceof SkipException) { - $this->assertTrue(false, 'Update should not have been skipped'); - } - } - - $ranCommands = $runtime->getRanCommands(); - $testCase = array( - 0 => 'composer --version', - ); - - // Check total of Executed Commands - $this->assertEquals(count($testCase), count($ranCommands)); - - // Check Generated Commands - foreach ($testCase as $index => $command) { - $this->assertEquals($command, $ranCommands[$index]); - } - } -} diff --git a/tests/Task/Custom/NotInstantiableTask.php b/tests/Task/Custom/NotInstantiableTask.php index e7eff55..0d534ca 100644 --- a/tests/Task/Custom/NotInstantiableTask.php +++ b/tests/Task/Custom/NotInstantiableTask.php @@ -23,7 +23,7 @@ abstract class NotInstantiableTask extends AbstractTask /** * @return string */ - public function getName() + public function getName(): string { return 'custom-not-instantiable'; } @@ -31,7 +31,7 @@ abstract class NotInstantiableTask extends AbstractTask /** * @return string */ - public function getDescription() + public function getDescription(): string { return '[Custom] Not Instantiable*'; } @@ -39,7 +39,7 @@ abstract class NotInstantiableTask extends AbstractTask /** * @return bool */ - public function execute() + public function execute(): bool { /** @var Process $process */ $process = $this->runtime->runCommand('echo "custom-not-instantiable"'); diff --git a/tests/Task/Custom/ValidTask.php b/tests/Task/Custom/ValidTask.php index ce2b1a8..261caad 100644 --- a/tests/Task/Custom/ValidTask.php +++ b/tests/Task/Custom/ValidTask.php @@ -23,7 +23,7 @@ class ValidTask extends AbstractTask /** * @return string */ - public function getName() + public function getName(): string { return 'custom-valid'; } @@ -31,7 +31,7 @@ class ValidTask extends AbstractTask /** * @return string */ - public function getDescription() + public function getDescription(): string { return '[Custom] Valid*'; } @@ -39,7 +39,7 @@ class ValidTask extends AbstractTask /** * @return bool */ - public function execute() + public function execute(): bool { /** @var Process $process */ $process = $this->runtime->runCommand('echo "custom-valid"'); diff --git a/tests/Task/CustomTask.php b/tests/Task/CustomTask.php index 75c7acf..42c2109 100644 --- a/tests/Task/CustomTask.php +++ b/tests/Task/CustomTask.php @@ -19,17 +19,17 @@ use Mage\Task\AbstractTask; */ class CustomTask extends AbstractTask { - public function getName() + public function getName(): string { return 'custom'; } - public function getDescription() + public function getDescription(): string { return '[Custom] Dummy Task'; } - public function execute() + public function execute(): bool { return true; } diff --git a/tests/Task/TestCaseFailTask.php b/tests/Task/TestCaseFailTask.php index 41101e5..458ed71 100644 --- a/tests/Task/TestCaseFailTask.php +++ b/tests/Task/TestCaseFailTask.php @@ -15,17 +15,17 @@ use Mage\Task\AbstractTask; class TestCaseFailTask extends AbstractTask { - public function getName() + public function getName(): string { return 'test-fail'; } - public function getDescription() + public function getDescription(): string { return '[Test] This is a Test Task which Fails'; } - public function execute() + public function execute(): bool { throw new ErrorException('This is a text with a lot of characters'); } diff --git a/tests/Task/TestCaseTask.php b/tests/Task/TestCaseTask.php index daa1656..dba69b9 100644 --- a/tests/Task/TestCaseTask.php +++ b/tests/Task/TestCaseTask.php @@ -14,17 +14,17 @@ use Mage\Task\AbstractTask; class TestCaseTask extends AbstractTask { - public function getName() + public function getName(): string { return 'test'; } - public function getDescription() + public function getDescription(): string { return '[Test] This is a Test Task'; } - public function execute() + public function execute(): bool { return true; } From a3ce2679e640132c8ec5b943bd7b68b441ea54b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 01:30:12 -0300 Subject: [PATCH 05/20] [Galactica] V5 - tests --- .github/workflows/tests.yml | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e3c563a..45fa04e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: - name: Run tests env: XDEBUG_MODE: coverage - run: ./vendor/bin/phpunit --testsuite=unit + run: ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml - name: Run Coveralls env: XDEBUG_MODE: coverage @@ -53,7 +53,7 @@ jobs: - name: Run tests env: XDEBUG_MODE: coverage - run: ./vendor/bin/phpunit --testsuite=unit + run: ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml - name: Run Coveralls env: XDEBUG_MODE: coverage diff --git a/README.md b/README.md index e20260a..cab3efd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Magallanes -[![SymfonyInsight](https://insight.symfony.com/projects/ed0de53a-a12e-459b-9464-34def5907b56/mini.svg)](https://insight.symfony.com/projects/ed0de53a-a12e-459b-9464-34def5907b56) -[![Build Status](https://img.shields.io/travis/andres-montanez/Magallanes/master.svg)](https://travis-ci.org/andres-montanez/Magallanes) +![Linters](https://github.com/andres-montanez/Magallanes/actions/workflows/linters.yml/badge.svg?) +![Tests](https://github.com/andres-montanez/Magallanes/actions/workflows/tests.yml/badge.svg?) [![Coverage Status](https://img.shields.io/coveralls/andres-montanez/Magallanes/master.svg)](https://coveralls.io/github/andres-montanez/Magallanes?branch=master) [![Code Quality](https://img.shields.io/scrutinizer/g/andres-montanez/Magallanes.svg)](https://scrutinizer-ci.com/g/andres-montanez/Magallanes/) [![Latest Stable Version](https://img.shields.io/packagist/v/andres-montanez/magallanes.svg?label=stable)](https://packagist.org/packages/andres-montanez/magallanes) From 23b179432163efe20466485e2cba9e41d919fe64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 01:41:27 -0300 Subject: [PATCH 06/20] [Galactica] V5 - tests --- .github/workflows/tests.yml | 6 +----- src/Runtime/Runtime.php | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 45fa04e..c49af12 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: run: ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml - name: Run Coveralls env: - XDEBUG_MODE: coverage + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: ./vendor/bin/php-coveralls -v --coverage_clover build/logs/coverage.xml unit_tests_81: @@ -54,7 +54,3 @@ jobs: env: XDEBUG_MODE: coverage run: ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml - - name: Run Coveralls - env: - XDEBUG_MODE: coverage - run: ./vendor/bin/php-coveralls -v --coverage_clover build/logs/coverage.xml diff --git a/src/Runtime/Runtime.php b/src/Runtime/Runtime.php index ba483f5..571aebd 100644 --- a/src/Runtime/Runtime.php +++ b/src/Runtime/Runtime.php @@ -441,7 +441,7 @@ class Runtime */ public function getHostPort(): ?int { - $info = explode(':', $this->getWorkingHost()); + $info = explode(':', strval($this->getWorkingHost())); return isset($info[1]) ? intval($info[1]) : null; } @@ -450,7 +450,7 @@ class Runtime */ public function getHostName(): ?string { - if (strpos($this->getWorkingHost(), ':') === false) { + if (strpos(strval($this->getWorkingHost()), ':') === false) { return $this->getWorkingHost(); } From e6ec0442307f0d19d2b06de793ae967733fba2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 01:55:49 -0300 Subject: [PATCH 07/20] [Galactica] V5 - improve exec task --- CHANGELOG.md | 1 + src/Task/BuiltIn/ExecTask.php | 16 +++++++++++++- tests/Task/BuiltIn/ExecTaskTest.php | 33 +++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d3fcfb..60f0231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,4 @@ CHANGELOG for 5.X * Refactored for Symfony 6 and PHP 8 * Added strong types * Removed task `composer/self-update` + * Allow `exec` task to interpolate `%environment%` and `%release%` diff --git a/src/Task/BuiltIn/ExecTask.php b/src/Task/BuiltIn/ExecTask.php index 589e3f4..a5a3705 100644 --- a/src/Task/BuiltIn/ExecTask.php +++ b/src/Task/BuiltIn/ExecTask.php @@ -57,8 +57,22 @@ class ExecTask extends AbstractTask throw new ErrorException('Parameter "cmd" is not defined'); } + $mapping = [ + '%environment%' => $this->runtime->getEnvironment(), + ]; + + if ($this->runtime->getReleaseId() !== null) { + $mapping['%release%'] = $this->runtime->getReleaseId(); + } + + $cmd = str_replace( + array_keys($mapping), + array_values($mapping), + strval($options['cmd']) + ); + /** @var Process $process */ - $process = $this->runtime->runCommand(strval($options['cmd']), intval($options['timeout'])); + $process = $this->runtime->runCommand($cmd, intval($options['timeout'])); return $process->isSuccessful(); } diff --git a/tests/Task/BuiltIn/ExecTaskTest.php b/tests/Task/BuiltIn/ExecTaskTest.php index 048670c..a17e78a 100755 --- a/tests/Task/BuiltIn/ExecTaskTest.php +++ b/tests/Task/BuiltIn/ExecTaskTest.php @@ -25,10 +25,10 @@ class ExecTest extends TestCase $runtime->setEnvironment('test'); $task = new ExecTask(); - $task->setOptions(['cmd' => 'ls -l', 'desc' => 'Loading docker']); + $task->setOptions(['cmd' => 'ls -l', 'desc' => 'Command description']); $task->setRuntime($runtime); - $this->assertStringContainsString('[Exec] Loading docker', $task->getDescription()); + $this->assertStringContainsString('[Exec] Command description', $task->getDescription()); $task->execute(); $ranCommands = $runtime->getRanCommands(); @@ -46,6 +46,35 @@ class ExecTest extends TestCase } } + public function testSimpleCommandWithInterpolation() + { + $runtime = new RuntimeMockup(); + $runtime->setConfiguration(['environments' => ['test' => []]]); + $runtime->setEnvironment('test'); + $runtime->setReleaseId('1234'); + + $task = new ExecTask(); + $task->setOptions(['cmd' => 'cp %environment%.env /app/%release%/.env', 'desc' => 'Copy config']); + $task->setRuntime($runtime); + + $this->assertStringContainsString('[Exec] Copy config', $task->getDescription()); + $task->execute(); + + $ranCommands = $runtime->getRanCommands(); + + $testCase = array( + 0 => 'cp test.env /app/1234/.env', + ); + + // Check total of Executed Commands + $this->assertEquals(count($testCase), count($ranCommands)); + + // Check Generated Commands + foreach ($testCase as $index => $command) { + $this->assertEquals($command, $ranCommands[$index]); + } + } + public function testCommandWithoutDescription() { $runtime = new RuntimeMockup(); From 47cb64137cfcfbebf04d41f8b5d5e4be785f8704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 18:06:48 -0300 Subject: [PATCH 08/20] [Galactica] tweaks --- src/Task/BuiltIn/Deploy/Release/CleanupTask.php | 2 +- src/Task/BuiltIn/Git/ChangeBranchTask.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Task/BuiltIn/Deploy/Release/CleanupTask.php b/src/Task/BuiltIn/Deploy/Release/CleanupTask.php index 9abcaf6..0656d0d 100644 --- a/src/Task/BuiltIn/Deploy/Release/CleanupTask.php +++ b/src/Task/BuiltIn/Deploy/Release/CleanupTask.php @@ -49,7 +49,7 @@ class CleanupTask extends AbstractTask sort($releases); $releasesToDelete = array_slice($releases, 0, count($releases) - $maxReleases); foreach ($releasesToDelete as $releaseId) { - if ($releaseId != $currentReleaseId) { + if ($releaseId !== $currentReleaseId) { $cmdDeleteRelease = sprintf('rm -rf %s/releases/%s', $hostPath, $releaseId); /** @var Process $process */ $process = $this->runtime->runRemoteCommand($cmdDeleteRelease, false); diff --git a/src/Task/BuiltIn/Git/ChangeBranchTask.php b/src/Task/BuiltIn/Git/ChangeBranchTask.php index 94a4756..991c5c6 100644 --- a/src/Task/BuiltIn/Git/ChangeBranchTask.php +++ b/src/Task/BuiltIn/Git/ChangeBranchTask.php @@ -55,7 +55,7 @@ class ChangeBranchTask extends AbstractTask } $currentBranch = str_replace('* ', '', trim($process->getOutput())); - if ($currentBranch == $options['branch']) { + if ($currentBranch === $options['branch']) { throw new SkipException(); } From 728f70fe6d2b7b7e579ee4081dae7be4d9d303ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 18:13:59 -0300 Subject: [PATCH 09/20] [Galactica] Sleep task tweaks --- src/Task/BuiltIn/SleepTask.php | 22 +++++++--------------- tests/Task/BuiltIn/ExecTaskTest.php | 3 +-- tests/Task/BuiltIn/SleepTaskTest.php | 23 +++++++++++++++++++++-- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/Task/BuiltIn/SleepTask.php b/src/Task/BuiltIn/SleepTask.php index 24c6051..07dfda8 100644 --- a/src/Task/BuiltIn/SleepTask.php +++ b/src/Task/BuiltIn/SleepTask.php @@ -21,42 +21,34 @@ use Mage\Task\AbstractTask; */ class SleepTask extends AbstractTask { - /** - * @return string - */ - public function getName() + public function getName(): string { return 'sleep'; } - /** - * @return string - */ - public function getDescription() + public function getDescription(): string { $options = $this->getOptions(); - return sprintf('[Sleep] Sleeping for %s second(s)', (int) $options['seconds']); + return sprintf('[Sleep] Sleeping for %d second(s)', $options['seconds']); } /** - * @return bool - * * @throws ErrorException */ - public function execute() + public function execute(): bool { $options = $this->getOptions(); - sleep((int) $options['seconds']); + sleep(intval($options['seconds'])); return true; } /** - * @return array + * @return array */ - protected function getOptions() + protected function getOptions(): array { $options = array_merge( ['seconds' => 1], diff --git a/tests/Task/BuiltIn/ExecTaskTest.php b/tests/Task/BuiltIn/ExecTaskTest.php index a17e78a..930a985 100755 --- a/tests/Task/BuiltIn/ExecTaskTest.php +++ b/tests/Task/BuiltIn/ExecTaskTest.php @@ -12,7 +12,6 @@ namespace Mage\Tests\Task\BuiltIn; use Mage\Task\Exception\ErrorException; use Mage\Task\BuiltIn\ExecTask; -use Exception; use Mage\Tests\Runtime\RuntimeMockup; use PHPUnit\Framework\TestCase; @@ -118,7 +117,7 @@ class ExecTest extends TestCase try { $task->execute(); $this->assertTrue(false, 'Task did not failed'); - } catch (Exception $exception) { + } catch (\Exception $exception) { $this->assertTrue($exception instanceof ErrorException); $this->assertEquals('Parameter "cmd" is not defined', $exception->getMessage()); } diff --git a/tests/Task/BuiltIn/SleepTaskTest.php b/tests/Task/BuiltIn/SleepTaskTest.php index 26f1756..0349b3c 100644 --- a/tests/Task/BuiltIn/SleepTaskTest.php +++ b/tests/Task/BuiltIn/SleepTaskTest.php @@ -12,11 +12,11 @@ namespace Mage\Tests\Task\BuiltIn; use Mage\Task\BuiltIn\SleepTask; use Mage\Tests\Runtime\RuntimeMockup; -use PHPUnit_Framework_TestCase as TestCase; +use PHPUnit\Framework\TestCase; class SleepTaskTest extends TestCase { - public function testCommand() + public function testTaskWithDefault() { $runtime = new RuntimeMockup(); $runtime->setConfiguration(['environments' => ['test' => []]]); @@ -28,4 +28,23 @@ class SleepTaskTest extends TestCase $this->assertSame('[Sleep] Sleeping for 1 second(s)', $task->getDescription()); $task->execute(); } + + public function testTaskWithValue() + { + $runtime = new RuntimeMockup(); + $runtime->setConfiguration(['environments' => ['test' => []]]); + $runtime->setEnvironment('test'); + + $task = new SleepTask(); + $task->setOptions(['seconds' => 2]); + $task->setRuntime($runtime); + + $this->assertSame('[Sleep] Sleeping for 2 second(s)', $task->getDescription()); + + $startedAt = microtime(true); + $task->execute(); + $finishedAt = microtime(true); + + $this->assertGreaterThanOrEqual(2, $finishedAt - $startedAt); + } } From 732b5d9cb6fed003d4af1316dd03b80942ba2d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 18:33:28 -0300 Subject: [PATCH 10/20] [Galactica] Allow to verride symlink name --- .../BuiltIn/DeployCommandWithReleasesTest.php | 50 +++++++++++++++++++ tests/Deploy/StrategyTest.php | 1 - tests/Resources/testhost-custom-symlink.yml | 28 +++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tests/Resources/testhost-custom-symlink.yml diff --git a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php index bb94584..8ea13f7 100755 --- a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php +++ b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php @@ -69,6 +69,56 @@ class DeployCommandWithReleasesTest extends TestCase $this->assertEquals(0, $tester->getStatusCode()); } + public function testDeploymentWithReleasesCommandsCustomSymlink() + { + $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost-custom-symlink.yml'); + + $application->getRuntime()->setReleaseId('20170101015120'); + + /** @var AbstractCommand $command */ + $command = $application->find('deploy'); + $this->assertTrue($command instanceof DeployCommand); + + $tester = new CommandTester($command); + $tester->execute(['command' => $command->getName(), 'environment' => 'test']); + + $ranCommands = $application->getRuntime()->getRanCommands(); + + $testCase = array( + 0 => 'git branch | grep "*"', + 1 => 'git checkout test', + 2 => 'git pull', + 3 => 'composer install --optimize-autoloader', + 4 => 'composer dump-autoload --optimize', + 5 => 'tar cfzp /tmp/mageXYZ --exclude=".git" --exclude="./var/cache/*" --exclude="./var/log/*" --exclude="./web/app_dev.php" ./', + 6 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "mkdir -p /var/www/test/releases/1234567890"', + 7 => 'scp -P 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no /tmp/mageXYZ tester@testhost:/var/www/test/releases/1234567890/mageXYZ', + 8 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && tar xfzop mageXYZ"', + 9 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm /var/www/test/releases/1234567890/mageXYZ"', + 10 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:warmup --env=dev"', + 11 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console assets:install web --env=dev --symlink --relative"', + 12 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:pool:prune --env=dev"', + 13 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test && ln -snf releases/1234567890 prod"', + 14 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "ls -1 /var/www/test/releases"', + 15 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015110"', + 16 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015111"', + 17 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015112"', + 18 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015113"', + 19 => 'rm /tmp/mageXYZ', + 20 => 'git checkout master', + ); + + // Check total of Executed Commands + $this->assertEquals(count($testCase), count($ranCommands)); + + // Check Generated Commands + foreach ($testCase as $index => $command) { + $this->assertEquals($command, $ranCommands[$index]); + } + + $this->assertEquals(0, $tester->getStatusCode()); + } + public function testDeploymentWithReleasesWithPortCommands() { $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost-with-port.yml'); diff --git a/tests/Deploy/StrategyTest.php b/tests/Deploy/StrategyTest.php index 9800a02..607dc09 100755 --- a/tests/Deploy/StrategyTest.php +++ b/tests/Deploy/StrategyTest.php @@ -114,5 +114,4 @@ class StrategyTest extends TestCase $this->assertEquals(sprintf('Invalid stage, got "%s" but expected "%s"', Runtime::PRE_DEPLOY, Runtime::POST_DEPLOY), $exception->getMessage()); } } - } diff --git a/tests/Resources/testhost-custom-symlink.yml b/tests/Resources/testhost-custom-symlink.yml new file mode 100644 index 0000000..be2a3e5 --- /dev/null +++ b/tests/Resources/testhost-custom-symlink.yml @@ -0,0 +1,28 @@ +magephp: + log_dir: /tmp + environments: + test: + user: tester + branch: test + host_path: /var/www/test + releases: 4 + symlink: prod + exclude: + - ./var/cache/* + - ./var/log/* + - ./web/app_dev.php + - + - + hosts: + - testhost + pre-deploy: + - git/update + - composer/install + - composer/dump-autoload + on-deploy: + - symfony/cache-warmup: { env: 'dev' } + - symfony/assets-install: { env: 'dev' } + - symfony/cache-pool-prune: { env: 'dev' } + on-release: + post-release: + post-deploy: From d3023a6767640849428d7b63be6442988b379d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 18:35:38 -0300 Subject: [PATCH 11/20] [Galactica] Improve PSR-12 --- src/Task/BuiltIn/Deploy/ReleaseTask.php | 2 +- src/Task/BuiltIn/SleepTask.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Task/BuiltIn/Deploy/ReleaseTask.php b/src/Task/BuiltIn/Deploy/ReleaseTask.php index 924e4ff..adecf2b 100644 --- a/src/Task/BuiltIn/Deploy/ReleaseTask.php +++ b/src/Task/BuiltIn/Deploy/ReleaseTask.php @@ -41,7 +41,7 @@ class ReleaseTask extends AbstractTask implements ExecuteOnRollbackInterface $hostPath = rtrim($this->runtime->getEnvOption('host_path'), '/'); $releaseId = $this->runtime->getReleaseId(); - + $symlink = $this->runtime->getEnvOption('symlink', 'current'); $cmdLinkRelease = sprintf('cd %s && ln -snf releases/%s %s', $hostPath, $releaseId, $symlink); diff --git a/src/Task/BuiltIn/SleepTask.php b/src/Task/BuiltIn/SleepTask.php index 07dfda8..6415dea 100644 --- a/src/Task/BuiltIn/SleepTask.php +++ b/src/Task/BuiltIn/SleepTask.php @@ -1,4 +1,5 @@ Date: Sun, 10 Apr 2022 18:53:26 -0300 Subject: [PATCH 12/20] [Galactica] Improve Windows compatibility --- src/Runtime/Runtime.php | 15 ++++++++++----- tests/Runtime/RuntimeWindowsMockup.php | 5 +++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Runtime/Runtime.php b/src/Runtime/Runtime.php index f0f30bb..6b68611 100644 --- a/src/Runtime/Runtime.php +++ b/src/Runtime/Runtime.php @@ -75,6 +75,11 @@ class Runtime return stripos(PHP_OS, 'WIN') === 0; } + public function hasPosix(): bool + { + return function_exists('posix_getpwuid'); + } + /** * Generate the Release ID */ @@ -471,13 +476,13 @@ class Runtime */ public function getCurrentUser(): string { - // Windows fallback - if (!function_exists('posix_getpwuid')) { - return getenv('USERNAME') ?: ''; + if ($this->hasPosix()) { + $userData = posix_getpwuid(posix_geteuid()); + return $userData['name']; } - $userData = posix_getpwuid(posix_geteuid()); - return $userData['name']; + // Windows fallback + return strval(getenv('USERNAME')); } /** diff --git a/tests/Runtime/RuntimeWindowsMockup.php b/tests/Runtime/RuntimeWindowsMockup.php index 0a9c640..050aaa1 100644 --- a/tests/Runtime/RuntimeWindowsMockup.php +++ b/tests/Runtime/RuntimeWindowsMockup.php @@ -16,4 +16,9 @@ class RuntimeWindowsMockup extends RuntimeMockup { return true; } + + public function hasPosix(): bool + { + return false; + } } From 2783292899bf5c8536518919fa61f971c2e0bca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 19:38:43 -0300 Subject: [PATCH 13/20] [Galactica] New log_limit option --- src/MageApplication.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/MageApplication.php b/src/MageApplication.php index 529498d..d0087eb 100644 --- a/src/MageApplication.php +++ b/src/MageApplication.php @@ -24,6 +24,7 @@ use Symfony\Component\Console\Application; use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Exception\ParseException; use Mage\Runtime\Exception\RuntimeException; +use Symfony\Component\Filesystem\Filesystem; /** * The Console Application for launching the Mage command in a standalone instance @@ -89,6 +90,9 @@ class MageApplication extends Application $logger = new Logger('magephp'); $logger->pushHandler(new StreamHandler($logfile)); + + $logLimit = isset($config['magephp']['log_limit']) ? intval($config['magephp']['log_limit']) : 30; + $this->clearOldLogs($config['magephp']['log_dir'], $logLimit); } elseif (array_key_exists('log_dir', $config['magephp']) && !is_dir($config['magephp']['log_dir'])) { throw new RuntimeException( sprintf( @@ -108,6 +112,24 @@ class MageApplication extends Application ); } + protected function clearOldLogs(string $logDir, int $logLimit): void + { + $filesystem = new Filesystem(); + $finder = new Finder(); + + $finder + ->files() + ->followLinks() + ->in($logDir) + ->name('*.log') + ->sortByModifiedTime() + ->reverseSorting(); + + $logs = iterator_to_array($finder); + $logsToRemove = array_slice($logs, $logLimit - 1); + $filesystem->remove($logsToRemove); + } + /** * Loads the BuiltIn Commands */ From b893e102c66512d46b5c8954eba143b8aa6dc5d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 19:47:10 -0300 Subject: [PATCH 14/20] [Galactica] Improve tests --- .gitignore | 1 + tests/Resources/basic.yml | 4 ++-- tests/Resources/broken-git-branch.yml | 2 +- tests/Resources/composer-env.yml | 2 +- tests/Resources/composer.yml | 2 +- tests/Resources/global-exclude.yml | 2 +- tests/Resources/invalid-task.yml | 2 +- tests/Resources/no-hosts.yml | 4 ++-- tests/Resources/symfony-envconf.yml | 2 +- tests/Resources/testhost-custom-symlink.yml | 2 +- tests/Resources/testhost-custom-task.yml | 4 ++-- tests/Resources/testhost-fail-copy-tar.yml | 2 +- tests/Resources/testhost-fail-get-current.yml | 2 +- tests/Resources/testhost-fail-get-releases.yml | 2 +- tests/Resources/testhost-force-release.yml | 4 ++-- tests/Resources/testhost-force-tar1.yml | 4 ++-- tests/Resources/testhost-force-tar2.yml | 4 ++-- tests/Resources/testhost-force-tar3.yml | 4 ++-- tests/Resources/testhost-no-hosts.yml | 2 +- tests/Resources/testhost-no-releases.yml | 2 +- tests/Resources/testhost-not-have-release.yml | 2 +- tests/Resources/testhost-skipping.yml | 4 ++-- tests/Resources/testhost-sudo.yml | 4 ++-- tests/Resources/testhost-with-error.yml | 4 ++-- tests/Resources/testhost-with-from-copy-directory.yml | 4 ++-- tests/Resources/testhost-with-from.yml | 4 ++-- tests/Resources/testhost-with-port.yml | 4 ++-- tests/Resources/testhost-with-postdeploy-error.yml | 4 ++-- tests/Resources/testhost-with-release-timeout.yml | 4 ++-- tests/Resources/testhost-without-releases-with-from.yml | 4 ++-- tests/Resources/testhost-without-releases-with-port.yml | 4 ++-- tests/Resources/testhost-without-releases.yml | 4 ++-- tests/Resources/testhost.yml | 4 ++-- 33 files changed, 52 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index f8cb51b..d72fbfb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.lock .mage.yml .phpunit.result.cache .phpcs-cache +.logs diff --git a/tests/Resources/basic.yml b/tests/Resources/basic.yml index 28c7978..79ac85a 100644 --- a/tests/Resources/basic.yml +++ b/tests/Resources/basic.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: production: user: app @@ -24,4 +24,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/broken-git-branch.yml b/tests/Resources/broken-git-branch.yml index 7263cf7..d0caa31 100644 --- a/tests/Resources/broken-git-branch.yml +++ b/tests/Resources/broken-git-branch.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/composer-env.yml b/tests/Resources/composer-env.yml index 2421fdf..db96928 100644 --- a/tests/Resources/composer-env.yml +++ b/tests/Resources/composer-env.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ composer: path: /usr/bin/composer.phar environments: diff --git a/tests/Resources/composer.yml b/tests/Resources/composer.yml index f8f1bff..134d1ee 100644 --- a/tests/Resources/composer.yml +++ b/tests/Resources/composer.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ composer: path: /usr/bin/composer.phar environments: diff --git a/tests/Resources/global-exclude.yml b/tests/Resources/global-exclude.yml index cfa5ddf..2795c8e 100644 --- a/tests/Resources/global-exclude.yml +++ b/tests/Resources/global-exclude.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ composer: path: /usr/bin/composer.phar exclude: diff --git a/tests/Resources/invalid-task.yml b/tests/Resources/invalid-task.yml index 57dd007..f60ab93 100644 --- a/tests/Resources/invalid-task.yml +++ b/tests/Resources/invalid-task.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/no-hosts.yml b/tests/Resources/no-hosts.yml index 6771cc6..914f6e7 100644 --- a/tests/Resources/no-hosts.yml +++ b/tests/Resources/no-hosts.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -20,4 +20,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/symfony-envconf.yml b/tests/Resources/symfony-envconf.yml index 3d4dff9..6833ebd 100644 --- a/tests/Resources/symfony-envconf.yml +++ b/tests/Resources/symfony-envconf.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: symfony: { env: 'testenv' } diff --git a/tests/Resources/testhost-custom-symlink.yml b/tests/Resources/testhost-custom-symlink.yml index be2a3e5..6dd060d 100644 --- a/tests/Resources/testhost-custom-symlink.yml +++ b/tests/Resources/testhost-custom-symlink.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-custom-task.yml b/tests/Resources/testhost-custom-task.yml index 8253e17..cea5685 100644 --- a/tests/Resources/testhost-custom-task.yml +++ b/tests/Resources/testhost-custom-task.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -17,4 +17,4 @@ magephp: - Mage\Tests\Task\CustomTask on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-fail-copy-tar.yml b/tests/Resources/testhost-fail-copy-tar.yml index 80809c7..dee2b99 100644 --- a/tests/Resources/testhost-fail-copy-tar.yml +++ b/tests/Resources/testhost-fail-copy-tar.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-fail-get-current.yml b/tests/Resources/testhost-fail-get-current.yml index 635b457..2073ed3 100644 --- a/tests/Resources/testhost-fail-get-current.yml +++ b/tests/Resources/testhost-fail-get-current.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-fail-get-releases.yml b/tests/Resources/testhost-fail-get-releases.yml index b9c4e88..9b5dc34 100644 --- a/tests/Resources/testhost-fail-get-releases.yml +++ b/tests/Resources/testhost-fail-get-releases.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-force-release.yml b/tests/Resources/testhost-force-release.yml index e59bccb..1fba188 100644 --- a/tests/Resources/testhost-force-release.yml +++ b/tests/Resources/testhost-force-release.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -12,4 +12,4 @@ magephp: hosts: - host2 on-deploy: - - deploy/release \ No newline at end of file + - deploy/release diff --git a/tests/Resources/testhost-force-tar1.yml b/tests/Resources/testhost-force-tar1.yml index 61a1a5a..03e22c6 100644 --- a/tests/Resources/testhost-force-tar1.yml +++ b/tests/Resources/testhost-force-tar1.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -12,4 +12,4 @@ magephp: hosts: - host2 pre-deploy: - - deploy/tar/prepare \ No newline at end of file + - deploy/tar/prepare diff --git a/tests/Resources/testhost-force-tar2.yml b/tests/Resources/testhost-force-tar2.yml index db26ad0..9ebc36c 100644 --- a/tests/Resources/testhost-force-tar2.yml +++ b/tests/Resources/testhost-force-tar2.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -12,4 +12,4 @@ magephp: hosts: - host2 on-deploy: - - deploy/tar/copy \ No newline at end of file + - deploy/tar/copy diff --git a/tests/Resources/testhost-force-tar3.yml b/tests/Resources/testhost-force-tar3.yml index cd2eeee..2b42f32 100644 --- a/tests/Resources/testhost-force-tar3.yml +++ b/tests/Resources/testhost-force-tar3.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -12,4 +12,4 @@ magephp: hosts: - host2 post-deploy: - - deploy/tar/cleanup \ No newline at end of file + - deploy/tar/cleanup diff --git a/tests/Resources/testhost-no-hosts.yml b/tests/Resources/testhost-no-hosts.yml index a6c4a5a..e206757 100644 --- a/tests/Resources/testhost-no-hosts.yml +++ b/tests/Resources/testhost-no-hosts.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-no-releases.yml b/tests/Resources/testhost-no-releases.yml index 88f9da0..056f25b 100644 --- a/tests/Resources/testhost-no-releases.yml +++ b/tests/Resources/testhost-no-releases.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-not-have-release.yml b/tests/Resources/testhost-not-have-release.yml index 4a23a85..b01b138 100644 --- a/tests/Resources/testhost-not-have-release.yml +++ b/tests/Resources/testhost-not-have-release.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester diff --git a/tests/Resources/testhost-skipping.yml b/tests/Resources/testhost-skipping.yml index 5ce8f07..0981777 100644 --- a/tests/Resources/testhost-skipping.yml +++ b/tests/Resources/testhost-skipping.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -21,4 +21,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-sudo.yml b/tests/Resources/testhost-sudo.yml index 55a19ca..109372f 100644 --- a/tests/Resources/testhost-sudo.yml +++ b/tests/Resources/testhost-sudo.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -23,4 +23,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-with-error.yml b/tests/Resources/testhost-with-error.yml index d2dba50..df2d8c5 100644 --- a/tests/Resources/testhost-with-error.yml +++ b/tests/Resources/testhost-with-error.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -20,4 +20,4 @@ magephp: - deploy/rsync on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-with-from-copy-directory.yml b/tests/Resources/testhost-with-from-copy-directory.yml index 4ef8d17..6a89432 100644 --- a/tests/Resources/testhost-with-from-copy-directory.yml +++ b/tests/Resources/testhost-with-from-copy-directory.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -26,4 +26,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-with-from.yml b/tests/Resources/testhost-with-from.yml index 1d4c91e..247780f 100644 --- a/tests/Resources/testhost-with-from.yml +++ b/tests/Resources/testhost-with-from.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -25,4 +25,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-with-port.yml b/tests/Resources/testhost-with-port.yml index 94e3ee6..913df4e 100644 --- a/tests/Resources/testhost-with-port.yml +++ b/tests/Resources/testhost-with-port.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -24,4 +24,4 @@ magephp: - symfony/cache-pool-prune: { env: 'prod' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-with-postdeploy-error.yml b/tests/Resources/testhost-with-postdeploy-error.yml index c2e2956..ab1d356 100644 --- a/tests/Resources/testhost-with-postdeploy-error.yml +++ b/tests/Resources/testhost-with-postdeploy-error.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -20,4 +20,4 @@ magephp: on-release: post-release: post-deploy: - - deploy/tar/cleanup \ No newline at end of file + - deploy/tar/cleanup diff --git a/tests/Resources/testhost-with-release-timeout.yml b/tests/Resources/testhost-with-release-timeout.yml index 61091f6..4639f10 100644 --- a/tests/Resources/testhost-with-release-timeout.yml +++ b/tests/Resources/testhost-with-release-timeout.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -28,4 +28,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-without-releases-with-from.yml b/tests/Resources/testhost-without-releases-with-from.yml index 3520f7d..b526fec 100644 --- a/tests/Resources/testhost-without-releases-with-from.yml +++ b/tests/Resources/testhost-without-releases-with-from.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -22,4 +22,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-without-releases-with-port.yml b/tests/Resources/testhost-without-releases-with-port.yml index 27755a2..6b26bb7 100644 --- a/tests/Resources/testhost-without-releases-with-port.yml +++ b/tests/Resources/testhost-without-releases-with-port.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -21,4 +21,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost-without-releases.yml b/tests/Resources/testhost-without-releases.yml index 7165c96..1afb1b9 100644 --- a/tests/Resources/testhost-without-releases.yml +++ b/tests/Resources/testhost-without-releases.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -21,4 +21,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: diff --git a/tests/Resources/testhost.yml b/tests/Resources/testhost.yml index b1b630e..a6d8d5a 100644 --- a/tests/Resources/testhost.yml +++ b/tests/Resources/testhost.yml @@ -1,5 +1,5 @@ magephp: - log_dir: /tmp + log_dir: .logs/ environments: test: user: tester @@ -24,4 +24,4 @@ magephp: - symfony/cache-pool-prune: { env: 'dev' } on-release: post-release: - post-deploy: \ No newline at end of file + post-deploy: From 0d17d6b3453efb6c66e7c0c111f1cb018d4d4394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 19:53:25 -0300 Subject: [PATCH 15/20] [Galactica] Fix tests --- .github/workflows/tests.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c49af12..0456b54 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,9 @@ jobs: - name: Run tests env: XDEBUG_MODE: coverage - run: ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml + run: + mkdir .logs + ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml - name: Run Coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -53,4 +55,6 @@ jobs: - name: Run tests env: XDEBUG_MODE: coverage - run: ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml + run: + mkdir .logs + ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml From b80efc1e09abde7733bb7f716b901e1ca8689733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 20:00:47 -0300 Subject: [PATCH 16/20] [Galactica] Fix tests --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0456b54..2b0f972 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: - name: Run tests env: XDEBUG_MODE: coverage - run: + run: | mkdir .logs ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml - name: Run Coveralls @@ -55,6 +55,6 @@ jobs: - name: Run tests env: XDEBUG_MODE: coverage - run: + run: | mkdir .logs ./vendor/bin/phpunit --coverage-clover build/logs/coverage.xml From 5d2ab6fa6476dfccb488cfff21458f28cc7dda84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 21:34:29 -0300 Subject: [PATCH 17/20] [Galactica] Allow to deploy a specific tag. --- src/Command/BuiltIn/DeployCommand.php | 22 ++++++++- src/Deploy/Strategy/ReleasesStrategy.php | 18 +++++-- src/Deploy/Strategy/RsyncStrategy.php | 13 ++++- src/Runtime/Runtime.php | 10 ++++ src/Task/BuiltIn/Git/ChangeBranchTask.php | 10 +++- src/Task/BuiltIn/Git/UpdateTask.php | 9 +++- .../Command/BuiltIn/DeployCommandMiscTest.php | 20 ++++++++ .../BuiltIn/DeployCommandWithReleasesTest.php | 49 +++++++++++++++++++ 8 files changed, 139 insertions(+), 12 deletions(-) diff --git a/src/Command/BuiltIn/DeployCommand.php b/src/Command/BuiltIn/DeployCommand.php index 684c57a..027dff0 100644 --- a/src/Command/BuiltIn/DeployCommand.php +++ b/src/Command/BuiltIn/DeployCommand.php @@ -42,12 +42,19 @@ class DeployCommand extends AbstractCommand $this ->setName('deploy') ->setDescription('Deploy code to hosts') - ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to') + ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to.') ->addOption( 'branch', null, InputOption::VALUE_REQUIRED, - 'Force to switch to a branch other than the one defined', + 'Force to switch to a branch other than the one defined.', + false + ) + ->addOption( + 'tag', + null, + InputOption::VALUE_REQUIRED, + 'Deploys a specific tag.', false ); } @@ -83,14 +90,25 @@ class DeployCommand extends AbstractCommand $output->writeln(sprintf(' Strategy: %s', $strategy->getName())); + if (($input->getOption('branch') !== false) && ($input->getOption('tag') !== false)) { + throw new RuntimeException('Branch and Tag options are mutually exclusive.'); + } + if ($input->getOption('branch') !== false) { $this->runtime->setEnvOption('branch', $input->getOption('branch')); } + if ($input->getOption('tag') !== false) { + $this->runtime->setEnvOption('branch', false); + $this->runtime->setEnvOption('tag', $input->getOption('tag')); + $output->writeln(sprintf(' Tag: %s', $this->runtime->getEnvOption('tag'))); + } + if ($this->runtime->getEnvOption('branch', false)) { $output->writeln(sprintf(' Branch: %s', $this->runtime->getEnvOption('branch'))); } + $output->writeln(''); $this->runDeployment($output, $strategy); } catch (RuntimeException $exception) { diff --git a/src/Deploy/Strategy/ReleasesStrategy.php b/src/Deploy/Strategy/ReleasesStrategy.php index 800ab55..8d8dca3 100644 --- a/src/Deploy/Strategy/ReleasesStrategy.php +++ b/src/Deploy/Strategy/ReleasesStrategy.php @@ -38,7 +38,11 @@ class ReleasesStrategy implements StrategyInterface $this->checkStage(Runtime::PRE_DEPLOY); $tasks = $this->runtime->getTasks(); - if ($this->runtime->getBranch() && !$this->runtime->inRollback() && !in_array('git/change-branch', $tasks)) { + if ( + ($this->runtime->getBranch() || $this->runtime->getTag()) && + !$this->runtime->inRollback() && + !in_array('git/change-branch', $tasks) + ) { array_unshift($tasks, 'git/change-branch'); } @@ -94,12 +98,16 @@ class ReleasesStrategy implements StrategyInterface $this->checkStage(Runtime::POST_DEPLOY); $tasks = $this->runtime->getTasks(); - if (!$this->runtime->inRollback() && !in_array('deploy/tar/cleanup', $tasks)) { - array_unshift($tasks, 'deploy/tar/cleanup'); + if ( + ($this->runtime->getBranch() || $this->runtime->getTag()) && + !$this->runtime->inRollback() && + !in_array('git/change-branch', $tasks) + ) { + array_unshift($tasks, 'git/change-branch'); } - if ($this->runtime->getBranch() && !$this->runtime->inRollback() && !in_array('git/change-branch', $tasks)) { - array_push($tasks, 'git/change-branch'); + if (!$this->runtime->inRollback() && !in_array('deploy/tar/cleanup', $tasks)) { + array_unshift($tasks, 'deploy/tar/cleanup'); } return $tasks; diff --git a/src/Deploy/Strategy/RsyncStrategy.php b/src/Deploy/Strategy/RsyncStrategy.php index c7b5f1a..15f6984 100644 --- a/src/Deploy/Strategy/RsyncStrategy.php +++ b/src/Deploy/Strategy/RsyncStrategy.php @@ -38,7 +38,11 @@ class RsyncStrategy implements StrategyInterface $this->checkStage(Runtime::PRE_DEPLOY); $tasks = $this->runtime->getTasks(); - if ($this->runtime->getBranch() && !$this->runtime->inRollback() && !in_array('git/change-branch', $tasks)) { + if ( + ($this->runtime->getBranch() || $this->runtime->getTag()) && + !$this->runtime->inRollback() && + !in_array('git/change-branch', $tasks) + ) { array_unshift($tasks, 'git/change-branch'); } @@ -72,7 +76,12 @@ class RsyncStrategy implements StrategyInterface $this->checkStage(Runtime::POST_DEPLOY); $tasks = $this->runtime->getTasks(); - if ($this->runtime->getBranch() && !$this->runtime->inRollback() && !in_array('git/change-branch', $tasks)) { + if ( + ($this->runtime->getBranch() || + $this->runtime->getTag()) && + !$this->runtime->inRollback() && + !in_array('git/change-branch', $tasks) + ) { array_push($tasks, 'git/change-branch'); } diff --git a/src/Runtime/Runtime.php b/src/Runtime/Runtime.php index 6b68611..ab86483 100644 --- a/src/Runtime/Runtime.php +++ b/src/Runtime/Runtime.php @@ -495,6 +495,16 @@ class Runtime return $this->getEnvOption('branch', false); } + /** + * Shortcut for getting Tag information + * + * @return bool|string + */ + public function getTag(): mixed + { + return $this->getEnvOption('tag', false); + } + /** * Guesses the Deploy Strategy to use */ diff --git a/src/Task/BuiltIn/Git/ChangeBranchTask.php b/src/Task/BuiltIn/Git/ChangeBranchTask.php index 991c5c6..c49a7cb 100644 --- a/src/Task/BuiltIn/Git/ChangeBranchTask.php +++ b/src/Task/BuiltIn/Git/ChangeBranchTask.php @@ -30,12 +30,17 @@ class ChangeBranchTask extends AbstractTask public function getDescription(): string { $options = $this->getOptions(); + $tag = $options['tag']; $branch = $options['branch']; if ($this->runtime->getVar('git_revert_branch', null)) { $branch = $this->runtime->getVar('git_revert_branch'); } + if ($tag) { + return sprintf('[Git] Checkout Tag (%s)', $tag); + } + return sprintf('[Git] Change Branch (%s)', $branch); } @@ -59,7 +64,7 @@ class ChangeBranchTask extends AbstractTask throw new SkipException(); } - $branch = $options['branch']; + $branch = $options['tag'] ? $options['tag'] : $options['branch']; $this->runtime->setVar('git_revert_branch', $currentBranch); } @@ -75,9 +80,10 @@ class ChangeBranchTask extends AbstractTask */ protected function getOptions(): array { + $tag = $this->runtime->getEnvOption('tag', false); $branch = $this->runtime->getEnvOption('branch', 'master'); $options = array_merge( - ['path' => 'git', 'branch' => $branch], + ['path' => 'git', 'branch' => $branch, 'tag' => $tag], $this->options ); diff --git a/src/Task/BuiltIn/Git/UpdateTask.php b/src/Task/BuiltIn/Git/UpdateTask.php index 44cfef0..1fae7b6 100644 --- a/src/Task/BuiltIn/Git/UpdateTask.php +++ b/src/Task/BuiltIn/Git/UpdateTask.php @@ -13,6 +13,7 @@ namespace Mage\Task\BuiltIn\Git; use Symfony\Component\Process\Process; use Mage\Task\AbstractTask; +use Mage\Task\Exception\SkipException; /** * Git Task - Pull @@ -34,6 +35,10 @@ class UpdateTask extends AbstractTask public function execute(): bool { $options = $this->getOptions(); + if ($options['tag']) { + throw new SkipException(); + } + $command = $options['path'] . ' pull'; $process = $this->runtime->runLocalCommand($command); @@ -47,8 +52,10 @@ class UpdateTask extends AbstractTask protected function getOptions(): array { $branch = $this->runtime->getEnvOption('branch', 'master'); + $tag = $this->runtime->getEnvOption('tag', false); + $options = array_merge( - ['path' => 'git', 'branch' => $branch], + ['path' => 'git', 'branch' => $branch, 'tag' => $tag], $this->options ); diff --git a/tests/Command/BuiltIn/DeployCommandMiscTest.php b/tests/Command/BuiltIn/DeployCommandMiscTest.php index 240ee21..9fb501f 100755 --- a/tests/Command/BuiltIn/DeployCommandMiscTest.php +++ b/tests/Command/BuiltIn/DeployCommandMiscTest.php @@ -37,6 +37,26 @@ class DeployCommandMiscTest extends TestCase $this->assertEquals(0, $tester->getStatusCode()); } + public function testTagAndBranch() + { + $application = new MageApplicationMockup(__DIR__ . '/../../Resources/no-hosts.yml'); + + /** @var AbstractCommand $command */ + $command = $application->find('deploy'); + $this->assertTrue($command instanceof DeployCommand); + + $tester = new CommandTester($command); + $tester->execute([ + 'command' => $command->getName(), + 'environment' => 'test', + '--branch' => 'branch', + '--tag' => 'tag' + ]); + + $this->assertTrue(strpos($tester->getDisplay(), 'Branch and Tag options are mutually exclusive.') !== false); + $this->assertGreaterThan(0, $tester->getStatusCode()); + } + public function testInvalidLog() { $application = new MageApplicationMockup(__DIR__ . '/../../Resources/invalid-log.yml'); diff --git a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php index 8ea13f7..fd38478 100755 --- a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php +++ b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php @@ -69,6 +69,55 @@ class DeployCommandWithReleasesTest extends TestCase $this->assertEquals(0, $tester->getStatusCode()); } + public function testDeploymentWithReleasesCommandsWithTag() + { + $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost.yml'); + + $application->getRuntime()->setReleaseId('20170101015120'); + + /** @var AbstractCommand $command */ + $command = $application->find('deploy'); + $this->assertTrue($command instanceof DeployCommand); + + $tester = new CommandTester($command); + $tester->execute(['command' => $command->getName(), 'environment' => 'test', '--tag' => 'v1.0.0']); + + $ranCommands = $application->getRuntime()->getRanCommands(); + + $testCase = array( + 0 => 'git branch | grep "*"', + 1 => 'git checkout v1.0.0', + 2 => 'composer install --optimize-autoloader', + 3 => 'composer dump-autoload --optimize', + 4 => 'tar cfzp /tmp/mageXYZ --exclude=".git" --exclude="./var/cache/*" --exclude="./var/log/*" --exclude="./web/app_dev.php" ./', + 5 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "mkdir -p /var/www/test/releases/1234567890"', + 6 => 'scp -P 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no /tmp/mageXYZ tester@testhost:/var/www/test/releases/1234567890/mageXYZ', + 7 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && tar xfzop mageXYZ"', + 8 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm /var/www/test/releases/1234567890/mageXYZ"', + 9 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:warmup --env=dev"', + 10 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console assets:install web --env=dev --symlink --relative"', + 11 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:pool:prune --env=dev"', + 12 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test && ln -snf releases/1234567890 current"', + 13 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "ls -1 /var/www/test/releases"', + 14 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015110"', + 15 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015111"', + 16 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015112"', + 17 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015113"', + 18 => 'rm /tmp/mageXYZ', + 19 => 'git checkout master', + ); + + // Check total of Executed Commands + $this->assertEquals(count($testCase), count($ranCommands)); + + // Check Generated Commands + foreach ($testCase as $index => $command) { + $this->assertEquals($command, $ranCommands[$index]); + } + + $this->assertEquals(0, $tester->getStatusCode()); + } + public function testDeploymentWithReleasesCommandsCustomSymlink() { $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost-custom-symlink.yml'); From 223bd680cf0a7e7bbeb02d505645041088e9d44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 21:38:27 -0300 Subject: [PATCH 18/20] [Galactica] Update readme and changelog. --- CHANGELOG.md | 15 ++++++++++----- README.md | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60f0231..0b9d14a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,13 @@ CHANGELOG for 5.X ================= * 5.0.0 (2022-04-15) - * v5 series release - * Refactored for Symfony 6 and PHP 8 - * Added strong types - * Removed task `composer/self-update` - * Allow `exec` task to interpolate `%environment%` and `%release%` + * v5 series release. + * Refactored for Symfony 6 and PHP 8. + * Added strong types. + * Removed task `composer/self-update`. + * Allow `exec` task to interpolate `%environment%` and `%release%`. + * Added new `sleep` task to day execution [PR#414]. + * Added new `symlink` option to define the name of symbolic link on the Release [PR#425]. + * Improved Windows compatibility [PR#427]. + * Added new `log_limit` option to limit how many logs are kept [Issue#403]. + * Add new deploy option `--tag` to specify deploying a specific tag [Issue#192] [Issue#315]. diff --git a/README.md b/README.md index cab3efd..fb20160 100644 --- a/README.md +++ b/README.md @@ -25,5 +25,5 @@ Finally you can use **Magallanes** from the vendor's bin: vendor/bin/mage version ``` -### Codename Discovery One +### Codename Galactica Each new mayor version of **Magallanes** will have a codename (like Ubuntu), version 3 was _Nostromo_, version 4 was _Discovery One_, and in the current version it is **_Galactica_**, in homage to the space battleship from the TV series Battlestar Galactica, both the '70s and the mind blowing revision of 2005. From 11839074098dbafc14562da71855b7982af3d41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Sun, 10 Apr 2022 23:48:09 -0300 Subject: [PATCH 19/20] [Galactica] Add alternative flags for SCP. --- CHANGELOG.md | 1 + src/Task/BuiltIn/Deploy/Tar/CopyTask.php | 2 +- .../BuiltIn/DeployCommandWithReleasesTest.php | 50 +++++++++++++++++++ .../testhost-with-release-scp-flags.yml | 30 +++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/Resources/testhost-with-release-scp-flags.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b9d14a..282b07b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,3 +12,4 @@ CHANGELOG for 5.X * Improved Windows compatibility [PR#427]. * Added new `log_limit` option to limit how many logs are kept [Issue#403]. * Add new deploy option `--tag` to specify deploying a specific tag [Issue#192] [Issue#315]. + * Added new `scp_flags` option for the `scp` command when SSH flags are incompatible with. diff --git a/src/Task/BuiltIn/Deploy/Tar/CopyTask.php b/src/Task/BuiltIn/Deploy/Tar/CopyTask.php index 5c0f934..909dd34 100644 --- a/src/Task/BuiltIn/Deploy/Tar/CopyTask.php +++ b/src/Task/BuiltIn/Deploy/Tar/CopyTask.php @@ -54,7 +54,7 @@ class CopyTask extends AbstractTask $cmdCopy = sprintf( 'scp -P %d %s %s %s@%s:%s/%s', $sshConfig['port'], - $sshConfig['flags'], + isset($sshConfig['scp_flags']) ? $sshConfig['scp_flags'] : $sshConfig['flags'], $tarLocal, $user, $host, diff --git a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php index fd38478..fc909f2 100755 --- a/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php +++ b/tests/Command/BuiltIn/DeployCommandWithReleasesTest.php @@ -418,6 +418,56 @@ class DeployCommandWithReleasesTest extends TestCase $this->assertEquals(0, $tester->getStatusCode()); } + public function testDeploymentWithReleasesWithSCPFlags() + { + $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost-with-release-scp-flags.yml'); + + $application->getRuntime()->setReleaseId('20170101015120'); + + /** @var AbstractCommand $command */ + $command = $application->find('deploy'); + $this->assertTrue($command instanceof DeployCommand); + + $tester = new CommandTester($command); + $tester->execute(['command' => $command->getName(), 'environment' => 'test']); + + $ranCommands = $application->getRuntime()->getRanCommands(); + + $testCase = array( + 0 => 'git branch | grep "*"', + 1 => 'git checkout test', + 2 => 'git pull', + 3 => 'composer install --optimize-autoloader', + 4 => 'composer dump-autoload --optimize', + 5 => 'tar cfzp /tmp/mageXYZ --exclude=".git" --exclude="./var/cache/*" --exclude="./var/log/*" --exclude="./web/app_dev.php" ./', + 6 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "mkdir -p /var/www/test/releases/1234567890"', + 7 => 'scp -P 22 -p -l 1000 /tmp/mageXYZ tester@testhost:/var/www/test/releases/1234567890/mageXYZ', + 8 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && tar xfzop mageXYZ"', + 9 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm /var/www/test/releases/1234567890/mageXYZ"', + 10 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:warmup --env=dev"', + 11 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console assets:install web --env=dev --symlink --relative"', + 12 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test/releases/1234567890 && bin/console cache:pool:prune --env=dev"', + 13 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "cd /var/www/test && ln -snf releases/1234567890 current"', + 14 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "ls -1 /var/www/test/releases"', + 15 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015110"', + 16 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015111"', + 17 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015112"', + 18 => 'ssh -p 22 -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no tester@testhost "rm -rf /var/www/test/releases/20170101015113"', + 19 => 'rm /tmp/mageXYZ', + 20 => 'git checkout master', + ); + + // Check total of Executed Commands + $this->assertEquals(count($testCase), count($ranCommands)); + + // Check Generated Commands + foreach ($testCase as $index => $command) { + $this->assertEquals($command, $ranCommands[$index]); + } + + $this->assertEquals(0, $tester->getStatusCode()); + } + public function testDeploymentWithoutReleasesTarPrepare() { $application = new MageApplicationMockup(__DIR__ . '/../../Resources/testhost-force-tar1.yml'); diff --git a/tests/Resources/testhost-with-release-scp-flags.yml b/tests/Resources/testhost-with-release-scp-flags.yml new file mode 100644 index 0000000..28cab31 --- /dev/null +++ b/tests/Resources/testhost-with-release-scp-flags.yml @@ -0,0 +1,30 @@ +magephp: + log_dir: .logs/ + environments: + test: + user: tester + branch: test + from: ./ + host_path: /var/www/test + releases: 4 + exclude: + - ./var/cache/* + - ./var/log/* + - ./web/app_dev.php + - + - + hosts: + - testhost + ssh: + scp_flags: '-p -l 1000' + pre-deploy: + - git/update + - composer/install + - composer/dump-autoload + on-deploy: + - symfony/cache-warmup: { env: 'dev' } + - symfony/assets-install: { env: 'dev' } + - symfony/cache-pool-prune: { env: 'dev' } + on-release: + post-release: + post-deploy: From a41e07eba6cd3b1abdd82974178e1753405a0648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Mon, 11 Apr 2022 00:20:05 -0300 Subject: [PATCH 20/20] [Galactica] Changelog update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 282b07b..39f81fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,4 +12,4 @@ CHANGELOG for 5.X * Improved Windows compatibility [PR#427]. * Added new `log_limit` option to limit how many logs are kept [Issue#403]. * Add new deploy option `--tag` to specify deploying a specific tag [Issue#192] [Issue#315]. - * Added new `scp_flags` option for the `scp` command when SSH flags are incompatible with. + * Added new `scp_flags` option for the `scp` command when SSH flags are incompatible with [Issue#439].