From 25c6f3e882c5c308c4659129fa3c7599058227f1 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 26 Nov 2018 18:01:43 +0100 Subject: [PATCH 01/74] Update readme.md --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index fa6ae1b5..edceacc4 100644 --- a/readme.md +++ b/readme.md @@ -16,10 +16,10 @@ Phabalicious is the successor of the python tool [fabalicious](https://github.co ## Add it via composer.json -* run `composer require factorial.io/phabalicious` +* run `composer require factorial-io/phabalicious` * then you can run phabalicious via `./vendor/factorial-io/fabablicious/bin/phab` (or create a symbolic link) -## Running pha +## Running phab * Run `phab list` to get a list of all available commands. * run `phab help ` to get some help for a given command. From 6a0424dae557a712be45414ea252e398405e2509 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 26 Nov 2018 18:19:06 +0100 Subject: [PATCH 02/74] First version of circleci --- .circleci/config.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..a6d6f930 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,37 @@ +# PHP CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-php/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/php:7.1-browsers + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/mysql:9.4 + + working_directory: ~/repo + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "composer.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: composer install -n --prefer-dist + + - save_cache: + paths: + - ./vendor + key: v1-dependencies-{{ checksum "composer.json" }} + + # run tests! + - run: phpunit From 73ae490f7614f626304318aa60b91da80d57c684 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 26 Nov 2018 18:30:33 +0100 Subject: [PATCH 03/74] Next try with circle-ci --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a6d6f930..0da41d07 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: build: docker: # specify the version you desire here - - image: circleci/php:7.1-browsers + - image: factorial/phabalicious-test-runner # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images @@ -26,7 +26,7 @@ jobs: # fallback to using the latest cache if no exact match is found - v1-dependencies- - - run: composer install -n --prefer-dist + - run: php /composer.phar install - save_cache: paths: @@ -34,4 +34,4 @@ jobs: key: v1-dependencies-{{ checksum "composer.json" }} # run tests! - - run: phpunit + - run: cd tests; ../vendor/bin/phpunit --exclude-group docker . From d31f6d47d0cdc72eb3361bd479efc4cfdf02b874 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 26 Nov 2018 19:37:22 +0100 Subject: [PATCH 04/74] Set version --- bin/phab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/phab b/bin/phab index 61ff551e..e7b5f917 100755 --- a/bin/phab +++ b/bin/phab @@ -45,7 +45,7 @@ $output = $container->get(ConsoleOutput::class); /** @var Application $application */ $application = $container->get(Application::class); -$application->setVersion('3.0.0'); +$application->setVersion('3.0.0-alpha.1'); $application->setName('phabalicious'); $application->setDefaultCommand('list'); From 73fc59ddf3cf0722a6bf60e1103cfa5b80117a89 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 26 Nov 2018 19:38:28 +0100 Subject: [PATCH 05/74] Build-script for releases --- build/create-release.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 build/create-release.sh diff --git a/build/create-release.sh b/build/create-release.sh new file mode 100644 index 00000000..cabb9ac4 --- /dev/null +++ b/build/create-release.sh @@ -0,0 +1,27 @@ +GH_USER=factorial-io +GH_PATH=`cat ~/.ghtoken` +GH_REPO=phabalicious +GH_TARGET=master +ASSETS_PATH=./ +VERSION=`git describe --tags | sed 's/-[0-9]-g[a-z0-9]\{7\}//'` +echo "Releasing ${VERSION} ..." +cd .. +composer build-phar +cd build + +res=`curl --user "$GH_USER:$GH_PATH" -X POST https://api.github.com/repos/${GH_USER}/${GH_REPO}/releases \ +-d " +{ + \"tag_name\": \"v$VERSION\", + \"target_commitish\": \"$GH_TARGET\", + \"name\": \"v$VERSION\", + \"body\": \"new version $VERSION\", + \"draft\": false, + \"prerelease\": false +}"` +echo Create release result: ${res} +rel_id=`echo ${res} | python -c 'import json,sys;print(json.load(sys.stdin)["id"])'` +file_name=phabalicious-${VERSION}.phar + +curl --user "$GH_USER:$GH_PATH" -X POST https://uploads.github.com/repos/${GH_USER}/${GH_REPO}/releases/${rel_id}/assets?name=${file_name}\ + --header 'Content-Type: text/javascript ' --upload-file ${ASSETS_PATH}/phabalicious.phar From 92b9bdd4538bd195cfc2e33074bc35dec1d28b33 Mon Sep 17 00:00:00 2001 From: Shibin Das Date: Tue, 27 Nov 2018 16:04:45 +0100 Subject: [PATCH 06/74] Update 'readme.md' Added necessary step to get Build from source working. --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index edceacc4..8f554e28 100644 --- a/readme.md +++ b/readme.md @@ -11,6 +11,7 @@ Phabalicious is the successor of the python tool [fabalicious](https://github.co ## Build from source * Clone the repository +* run `composer install` * run `composer build-phar` * run `composer install-phar` this will copy the app to /usr/local/bin and make it executable. From 814f92537e2e9868bd08ab74f0c24884a79c843f Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 27 Nov 2018 20:31:48 +0100 Subject: [PATCH 07/74] Add test-case for app:scaffold --- tests/AppScaffoldCommandTest.php | 77 +++++++++++++++++++ .../scaffold-tests/scaffold-drupal-8.yml | 2 - .../scaffold-tests/ssh-keys/docker-root-key | 27 ------- .../ssh-keys/docker-root-key.pub | 1 - .../scaffold-tests/ssh-keys/known_hosts | 2 - 5 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 tests/AppScaffoldCommandTest.php delete mode 100644 tests/assets/scaffold-tests/ssh-keys/docker-root-key delete mode 100644 tests/assets/scaffold-tests/ssh-keys/docker-root-key.pub delete mode 100644 tests/assets/scaffold-tests/ssh-keys/known_hosts diff --git a/tests/AppScaffoldCommandTest.php b/tests/AppScaffoldCommandTest.php new file mode 100644 index 00000000..1ac52825 --- /dev/null +++ b/tests/AppScaffoldCommandTest.php @@ -0,0 +1,77 @@ +application = new Application(); + $this->application->setVersion('3.0.0'); + $logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); + + $configuration = new ConfigurationService($this->application, $logger); + $method_factory = new MethodFactory($configuration, $logger); + $method_factory->addMethod(new ScriptMethod($logger)); + + $this->application->add(new AppScaffoldCommand($configuration, $method_factory)); + } + + public function testAppScaffolder() + { + $command = $this->application->find('app:scaffold'); + $commandTester = new CommandTester($command); + $commandTester->execute(array( + '--short-name' => 'TST', + '--name' => 'Test', + '--output' => '/tmp', + '--override' => true, + 'scaffold-url' => getcwd() . '/assets/scaffold-tests/scaffold-drupal-commerce.yml' + )); + + // the output of the command in the console + $output = $commandTester->getDisplay(); + + $this->testFileContent('/tmp/test/.fabfile.yaml', 'name: Test'); + $this->testFileContent('/tmp/test/.fabfile.yaml', 'key: tst'); + $this->testFileContent('/tmp/test/.fabfile.yaml', 'host: test.test'); + $this->testFileContent( + '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', + 'name: Test deployment module' + ); + $this->testFileContent( + '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', + 'name: Test deployment module' + ); + $this->testFileContent( + '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.install', + 'function tst_deploy_install()' + ); + } + + private function testFileContent($filename, $needle) + { + + $haystack = file_get_contents($filename); + $this->assertContains($needle, $haystack); + } +} diff --git a/tests/assets/scaffold-tests/scaffold-drupal-8.yml b/tests/assets/scaffold-tests/scaffold-drupal-8.yml index ba1402c9..4b35509a 100644 --- a/tests/assets/scaffold-tests/scaffold-drupal-8.yml +++ b/tests/assets/scaffold-tests/scaffold-drupal-8.yml @@ -18,11 +18,9 @@ sshKeys: scaffold: - rm -rf %rootFolder% - composer create-project %composerProject% %rootFolder% --stability dev --no-interaction - - cd %rootFolder%; composer require drupal/coffee - cd %rootFolder%; composer require drupal/devel - copy_assets(%rootFolder%) - copy_assets(%rootFolder%/web/modules/custom/%shortName%_deploy, deployModuleAssets) - - copy_assets(%rootFolder%/ssh-keys, sshKeys) - cd %rootFolder%; git init . - cd %rootFolder%; git add . - cd %rootFolder%; git commit -m "Initial commit by phabalicious" \ No newline at end of file diff --git a/tests/assets/scaffold-tests/ssh-keys/docker-root-key b/tests/assets/scaffold-tests/ssh-keys/docker-root-key deleted file mode 100644 index 9a71d707..00000000 --- a/tests/assets/scaffold-tests/ssh-keys/docker-root-key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA5srq1zzi2/PQIkmPGGD2ThyN98yJG1g4tBj+AUH7m6oW2P7M -U6WNWdZF1ajcKN1zQ25GjOw4jfn/8VkC93ANgeRBX/NFQoiYkjBJgBv+/WGD06Fx -8TeKu2zTK3TdYwcLVSHyQEfEma604XTjWI8VGb/yuj6iP0IIxD2g5j9TChD9HBxG -bwwC8WYsLsW8OnRTLKOvGRTIZnjFTJREkBlmhs3lAswDb4Od62N90jOclTmcaSN1 -Fuo0MHeaBF1wsjHlsX3yMvc5yyuSExjwDWjlhs16Pnz56upapmZPk0lh7AjM7MKq -QKjuQZmquPD4Ebp/zeicS3P8Wvdod8pDd4DqDwIDAQABAoIBAQCBCX8X7IDifYUn -Rn1tIflUXv65R3B5C3BYsYiC54Nn20d+96cCNZO8YOMWvJyrdHVXhDaJ4CEWsGp7 -ZEsWUV4b+6TZoshclMbJJZpSuFRvErCECMYOGgHFHOlMaMDG909Mv/gUHIw9aMLV -M2dRQl6H0RxDKXXJbIA+SD7HvSwOebVXqu/RC6pU6hK9pVUq0r7X3ZAD53jp+PBg -oj4S8sUu4Rh8yb9hNMWLZkmvkNm69gr0Yhj6UOpP1s+f1ztvB4uAhWu5bgWzqJsG -8bc5tyDTksb0OsXfIeJMnDg/lte9cF0GFEfp6WlC5m5Dkx1ffnWGfdzzLMDhI7pF -C6361nAxAoGBAPXTN1ri7Q/lVXRU+CiNAZhKaw3XVfbGKSH6w19MQ7BanWvti5QX -At1IGX9KrX9zQ6YtUU/zcsEvB4dr/qaRu8sszGoYLsiizcgrReUeR70WP5nNlAaA -50RfF7IESkfiWAOvnUgsK462di5QtyU+47jNA5cf8MeKu/jE4AvUnxu9AoGBAPBY -apNn0pO/OYkrOTEG3LtXLDVuPTaV1RP5I4bz4Az9UmPUsdMwvBASx/Qe2R5ZgVRa -YvO9sBBH5V21rgH9On2rqGfSKrhvteXa0wN5+iQ3BBlRePhgDQ3D+IyuNGK1q4PY -fTe59pEwAjVBov3wrC4wDtFEURWrEtlJqAirVTO7AoGBAL3KMsSiyvAo2U8Vgvqb -0w1m9zwacq4x0/P+DPT4hpITg9Kd9dOB6J47WiQi3cy2ixYzisG1bXWk/6UYReUI -QvrcPX3z6brRpxrR/gak2DIuiTAPvic/Qk5RNJQmJ8tT/yvpW/8qyv5F9PxRKPVC -lsJI1mrJKDaG8BViuq+nmqfpAoGBANtsXSBmUOGCW0zXoUcZNLv0QfAlzMzgzb+G -XOEAFTTGsUljDVX50Df8bYB6CU6j+GbCfkR4kRzMBqMfEtXOEnBZH05pmYb4teA7 -fxpVagFWGO/kacSYLFK871XAVSMpKIUeSHNv26OBaQKmAeBEsW0Zgu2aqUxW+sZV -cIs5oHexAoGASkK64OrWItZD8R06J3ZAnThumcvJZCSwY53hSBJIcjcL/e8dazTd -wjLqqBDGsKQMTuzqNs0Wj4lvygdNGsB5zFQxGuoocaxyCC2+fvLNzK3maAva+gsX -jLwzoboZiTv0qqDw9ywERvy1AahA0MDGRoFMuarGqXRrkOQNPDx6/NM= ------END RSA PRIVATE KEY----- diff --git a/tests/assets/scaffold-tests/ssh-keys/docker-root-key.pub b/tests/assets/scaffold-tests/ssh-keys/docker-root-key.pub deleted file mode 100644 index 57014ce8..00000000 --- a/tests/assets/scaffold-tests/ssh-keys/docker-root-key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDmyurXPOLb89AiSY8YYPZOHI33zIkbWDi0GP4BQfubqhbY/sxTpY1Z1kXVqNwo3XNDbkaM7DiN+f/xWQL3cA2B5EFf80VCiJiSMEmAG/79YYPToXHxN4q7bNMrdN1jBwtVIfJAR8SZrrThdONYjxUZv/K6PqI/QgjEPaDmP1MKEP0cHEZvDALxZiwuxbw6dFMso68ZFMhmeMVMlESQGWaGzeUCzANvg53rY33SM5yVOZxpI3UW6jQwd5oEXXCyMeWxffIy9znLK5ITGPANaOWGzXo+fPnq6lqmZk+TSWHsCMzswqpAqO5Bmaq48PgRun/N6JxLc/xa92h3ykN3gOoP docker@docker.local diff --git a/tests/assets/scaffold-tests/ssh-keys/known_hosts b/tests/assets/scaffold-tests/ssh-keys/known_hosts deleted file mode 100644 index bd1d53a5..00000000 --- a/tests/assets/scaffold-tests/ssh-keys/known_hosts +++ /dev/null @@ -1,2 +0,0 @@ -[source.factorial.io]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCfp3kjMalh/c10bjVYF00IotFIwPQrr8iOhBjfRbe5lS43Gd3+XkTcKdUnmPYvF6wt6YxvUYcn0YYfzncpA0FzFw8461gcBoIVRvC+kV+LOsi/jy7lkfSoCCThLWW0EE8iP0FaorzVl4SrJtHcRiv9v0RY8CzZ8LeADsWu8bhY3eHdcg4F4tBvggrRxja7HbSszisp9ls6fgi+KhowBW7FN0E1cFl8HOZ6K9K0+Qg3PM/3ivpWQ66IGXDRAPHK/bMwME09wAl7o8Qb67SnNKYxqaKunB+bJisez6j5ETuzwZtiKxQ8Hh3Ke33pHRi8xqWmmc4N0EK3ENkPdZ6P7w/9 -github.com,192.30.252.128 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== From ecda056b9de9a3fd50401ca4b6745f5611efddb7 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 27 Nov 2018 20:53:01 +0100 Subject: [PATCH 08/74] Check if container is available before running waitForServices or copySSHKeys --- Changelog.md | 2 ++ src/Method/DockerMethod.php | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index ec30632c..22d7204b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -66,6 +66,8 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav docker: service: web + The `name` will be discarded, if a `service`-entry is set. + ### Changed diff --git a/src/Method/DockerMethod.php b/src/Method/DockerMethod.php index f1718ed5..14fbc44e 100644 --- a/src/Method/DockerMethod.php +++ b/src/Method/DockerMethod.php @@ -70,6 +70,13 @@ public function validateConfig(array $config, ValidationErrorBagInterface $error } } + public function alterConfig(ConfigurationService $configuration_service, array &$data) + { + if (!empty($data['docker']['service'])) { + unset($data['docker']['name']); + } + } + /** * @param HostConfig $host_config * @param TaskContextInterface $context @@ -165,6 +172,9 @@ public function getInternalTasks() /** * @param HostConfig $hostconfig * @param TaskContextInterface $context + * @throws ValidationFailedException + * @throws \Phabalicious\Exception\MismatchedVersionException + * @throws \Phabalicious\Exception\MissingDockerHostConfigException */ public function waitForServices(HostConfig $hostconfig, TaskContextInterface $context) { @@ -177,6 +187,13 @@ public function waitForServices(HostConfig $hostconfig, TaskContextInterface $co $container_name = $this->getDockerContainerName($hostconfig, $context); $shell = $docker_config->shell(); + if (!$this->isContainerRunning($docker_config, $container_name)) { + throw new \RuntimeException(sprintf( + 'Docker container %s not running, check your `host.docker.name` configuration!', + $container_name + )); + } + while ($tries < $max_tries) { $error_log_level = new ScopedErrorLogLevel($shell, LogLevel::NOTICE); $result = $shell->run(sprintf('#!docker exec %s #!supervisorctl status', $container_name), true, false); @@ -251,7 +268,10 @@ private function copySSHKeys(HostConfig $hostconfig, TaskContextInterface $conte $shell = $docker_config->shell(); $container_name = $this->getDockerContainerName($hostconfig, $context); if (!$this->isContainerRunning($docker_config, $container_name)) { - throw new \RuntimeException(sprintf('Docker container %s not running', $container_name)); + throw new \RuntimeException(sprintf( + 'Docker container %s not running, check your `host.docker.name` configuration!', + $container_name + )); } $shell->run(sprintf('#!docker exec %s mkdir -p /root/.ssh', $container_name)); From b99cf016122784c7d09613dfa5d3b038f557c8ae Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 27 Nov 2018 21:05:28 +0100 Subject: [PATCH 09/74] Fix test --- tests/AppScaffoldCommandTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/AppScaffoldCommandTest.php b/tests/AppScaffoldCommandTest.php index 1ac52825..b2a8ced4 100644 --- a/tests/AppScaffoldCommandTest.php +++ b/tests/AppScaffoldCommandTest.php @@ -51,24 +51,24 @@ public function testAppScaffolder() // the output of the command in the console $output = $commandTester->getDisplay(); - $this->testFileContent('/tmp/test/.fabfile.yaml', 'name: Test'); - $this->testFileContent('/tmp/test/.fabfile.yaml', 'key: tst'); - $this->testFileContent('/tmp/test/.fabfile.yaml', 'host: test.test'); - $this->testFileContent( + $this->checkFileContent('/tmp/test/.fabfile.yaml', 'name: Test'); + $this->checkFileContent('/tmp/test/.fabfile.yaml', 'key: tst'); + $this->checkFileContent('/tmp/test/.fabfile.yaml', 'host: test.test'); + $this->checkFileContent( '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', 'name: Test deployment module' ); - $this->testFileContent( + $this->checkFileContent( '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', 'name: Test deployment module' ); - $this->testFileContent( + $this->checkFileContent( '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.install', 'function tst_deploy_install()' ); } - private function testFileContent($filename, $needle) + private function checkFileContent($filename, $needle) { $haystack = file_get_contents($filename); From 70c2ce9b472bc1c8b2e098945c9754ef9d52525f Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 27 Nov 2018 21:21:54 +0100 Subject: [PATCH 10/74] Harden test --- tests/AppScaffoldCommandTest.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/AppScaffoldCommandTest.php b/tests/AppScaffoldCommandTest.php index b2a8ced4..2e1c8fda 100644 --- a/tests/AppScaffoldCommandTest.php +++ b/tests/AppScaffoldCommandTest.php @@ -38,12 +38,17 @@ public function setup() public function testAppScaffolder() { + $target_folder = getcwd() . '/tmp'; + if (!is_dir($target_folder)) { + mkdir($target_folder); + } + $command = $this->application->find('app:scaffold'); $commandTester = new CommandTester($command); $commandTester->execute(array( '--short-name' => 'TST', '--name' => 'Test', - '--output' => '/tmp', + '--output' => $target_folder, '--override' => true, 'scaffold-url' => getcwd() . '/assets/scaffold-tests/scaffold-drupal-commerce.yml' )); @@ -51,21 +56,22 @@ public function testAppScaffolder() // the output of the command in the console $output = $commandTester->getDisplay(); - $this->checkFileContent('/tmp/test/.fabfile.yaml', 'name: Test'); - $this->checkFileContent('/tmp/test/.fabfile.yaml', 'key: tst'); - $this->checkFileContent('/tmp/test/.fabfile.yaml', 'host: test.test'); + $this->checkFileContent($target_folder . '/test/.fabfile.yaml', 'name: Test'); + $this->checkFileContent($target_folder . '/test/.fabfile.yaml', 'key: tst'); + $this->checkFileContent($target_folder . '/test/.fabfile.yaml', 'host: test.test'); $this->checkFileContent( - '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', + $target_folder . '/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', 'name: Test deployment module' ); $this->checkFileContent( - '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', + $target_folder . '/test/web/modules/custom/tst_deploy/tst_deploy.info.yml', 'name: Test deployment module' ); $this->checkFileContent( - '/tmp/test/web/modules/custom/tst_deploy/tst_deploy.install', + $target_folder . '/test/web/modules/custom/tst_deploy/tst_deploy.install', 'function tst_deploy_install()' ); + shell_exec(sprintf('rm -rf %s', $target_folder)); } private function checkFileContent($filename, $needle) From 379432cf1e790ff85343da1b4116dd6c78e85d1a Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 27 Nov 2018 21:34:11 +0100 Subject: [PATCH 11/74] Disable scaffold-test for now on circle ci --- tests/AppScaffoldCommandTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/AppScaffoldCommandTest.php b/tests/AppScaffoldCommandTest.php index 2e1c8fda..f1cc8fe2 100644 --- a/tests/AppScaffoldCommandTest.php +++ b/tests/AppScaffoldCommandTest.php @@ -36,6 +36,9 @@ public function setup() $this->application->add(new AppScaffoldCommand($configuration, $method_factory)); } + /** + * @group docker + */ public function testAppScaffolder() { $target_folder = getcwd() . '/tmp'; From 2a7ec204ee40993cb21bf80f42463393a2e45213 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 28 Nov 2018 22:05:04 +0100 Subject: [PATCH 12/74] Fix copySSHKeys for remote instances. Fixes #2 --- src/Configuration/ConfigurationService.php | 4 ++++ src/Method/DockerMethod.php | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Configuration/ConfigurationService.php b/src/Configuration/ConfigurationService.php index ab973410..209d841f 100644 --- a/src/Configuration/ConfigurationService.php +++ b/src/Configuration/ConfigurationService.php @@ -528,6 +528,9 @@ public function getDockerConfig(string $config_name) $data = $this->dockerHosts[$config_name]; $data = $this->resolveInheritance($data, $this->dockerHosts); + $data = $this->applyDefaults($data, [ + 'tmpFolder' => '/tmp', + ]); if (!empty($data['inheritOnly'])) { return $data; } @@ -597,6 +600,7 @@ private function validateDockerConfig(array $data, $config_name) $validation->deprecate(['runLocally']); $validation->hasKey('shellProvider', 'The name of the shell-provider to use'); $validation->hasKey('rootFolder', 'The rootFolder to start with'); + $validation->hasKey('tmpFolder', 'The rootFolder to use'); if ($errors->hasErrors()) { throw new ValidationFailedException($errors); diff --git a/src/Method/DockerMethod.php b/src/Method/DockerMethod.php index 14fbc44e..3006319a 100644 --- a/src/Method/DockerMethod.php +++ b/src/Method/DockerMethod.php @@ -264,6 +264,8 @@ private function copySSHKeys(HostConfig $hostconfig, TaskContextInterface $conte } if (count($files) > 0) { $docker_config = $this->getDockerConfig($hostconfig, $context); + $root_folder = $docker_config['rootFolder'] . '/' . $hostconfig['docker']['projectFolder']; + /** @var ShellProviderInterface $shell */ $shell = $docker_config->shell(); $container_name = $this->getDockerContainerName($hostconfig, $context); @@ -284,15 +286,17 @@ private function copySSHKeys(HostConfig $hostconfig, TaskContextInterface $conte $data['source'] = $temp_file; $temp_files[] = $temp_file; } elseif ($data['source'][0] !== '/') { - $data['source'] = realpath( + $data['source'] = $context->getConfigurationService()->getFabfilePath() . '/' . - $data['source'] - ); + $data['source']; } + $temp_file = $docker_config['tmpFolder'] . '/' . basename($data['source']); + $shell->putFile($data['source'], $temp_file, $context); - $shell->run(sprintf('#!docker cp %s %s:%s', $data['source'], $container_name, $dest)); + $shell->run(sprintf('#!docker cp %s %s:%s', $temp_file, $container_name, $dest)); $shell->run(sprintf('#!docker exec %s #!chmod %s %s', $container_name, $data['permissions'], $dest)); + $shell->run(sprintf('rm %s', $temp_file)); } $shell->run(sprintf('#!docker exec %s #!chmod 700 /root/.ssh', $container_name)); $shell->run(sprintf('#!docker exec %s #!chown -R root /root/.ssh', $container_name)); From c5e181dd6e2f2a023e008fffd313eca9e23f427b Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 14:15:20 +0100 Subject: [PATCH 13/74] Remove duplicate command output --- src/ShellProvider/LocalShellProvider.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ShellProvider/LocalShellProvider.php b/src/ShellProvider/LocalShellProvider.php index 7436507e..ba9579c9 100644 --- a/src/ShellProvider/LocalShellProvider.php +++ b/src/ShellProvider/LocalShellProvider.php @@ -154,13 +154,7 @@ public function run(string $command, $capture_output = false, $throw_exception_o } while (empty($exit_code)); $exit_code = intval(str_replace(self::RESULT_IDENTIFIER, '', $exit_code), 10); - foreach ($lines as $line) { - if (!$capture_output && $this->output) { - $this->output->writeln($line); - } elseif ($capture_output) { - $this->logger->debug($line); - } - } + $cr = new CommandResult($exit_code, $lines); if ($cr->failed() && !$capture_output && $throw_exception_on_error) { $cr->throwException(sprintf('`%s` failed!', $command)); From 59ea68b0a6e6fad706b8d1fc285ce945797ff2cd Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 14:15:35 +0100 Subject: [PATCH 14/74] Fix failing copySSHKeys command --- src/Method/DockerMethod.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Method/DockerMethod.php b/src/Method/DockerMethod.php index 3006319a..6120849d 100644 --- a/src/Method/DockerMethod.php +++ b/src/Method/DockerMethod.php @@ -291,7 +291,7 @@ private function copySSHKeys(HostConfig $hostconfig, TaskContextInterface $conte '/' . $data['source']; } - $temp_file = $docker_config['tmpFolder'] . '/' . basename($data['source']); + $temp_file = $docker_config['tmpFolder'] . '/' . 'phab.tmp.' . basename($data['source']); $shell->putFile($data['source'], $temp_file, $context); $shell->run(sprintf('#!docker cp %s %s:%s', $temp_file, $container_name, $dest)); From ba6d48ff395da0c11c3df2ea4fae18257dc37711 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 16:35:43 +0100 Subject: [PATCH 15/74] Refactor starting an interactive shell --- src/Command/BaseCommand.php | 28 +++++++++++++++++++++++++++- src/Command/ShellCommand.php | 19 ++----------------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Command/BaseCommand.php b/src/Command/BaseCommand.php index 4c8afa79..23093cb1 100644 --- a/src/Command/BaseCommand.php +++ b/src/Command/BaseCommand.php @@ -10,6 +10,7 @@ use Phabalicious\Exception\MismatchedVersionException; use Phabalicious\Exception\ValidationFailedException; use Phabalicious\Exception\MissingHostConfigException; +use Phabalicious\ShellProvider\ShellProviderInterface; use Psr\Log\NullLogger; use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface; use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext; @@ -17,6 +18,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Process; abstract class BaseCommand extends BaseOptionsCommand { @@ -175,4 +177,28 @@ public function runCommand(string $command, array $args, InputInterface $origina return $cmd->run($input, $output); } -} \ No newline at end of file + /** + * @param ShellProviderInterface $shell + * @param array $command + * @return Process + */ + protected function startInteractiveShell(ShellProviderInterface $shell, array $command = []) + { + /** @var Process $process */ + $process = $shell->createShellProcess($command, ['tty' => true]); + $stdin = fopen('php://stdin', 'r'); + $process->setInput($stdin); + $process->setTimeout(0); + $process->setTty(true); + $process->start(); + $process->wait(function ($type, $buffer) { + if ($type == Process::ERR) { + fwrite(STDERR, $buffer); + } else { + fwrite(STDOUT, $buffer); + } + }); + + return $process; + } +} diff --git a/src/Command/ShellCommand.php b/src/Command/ShellCommand.php index 229dbff2..4e447a17 100644 --- a/src/Command/ShellCommand.php +++ b/src/Command/ShellCommand.php @@ -52,22 +52,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln('Starting shell on `' . $host_config['configName'] . '`'); - /** @var Process $process */ - $process = $shell->createShellProcess([], ['tty' => true]); - $stdin = fopen('php://stdin', 'r'); - $process->setInput($stdin); - $process->setTimeout(0); - $process->setTty(true); - $process->start(); - $process->wait(function ($type, $buffer) { - if ($type == Process::ERR) { - fwrite(STDERR, $buffer); - } else { - fwrite(STDOUT, $buffer); - } - }); - + $process = $this->startInteractiveShell($shell); return $process->getExitCode(); } - -} \ No newline at end of file +} From 6a1bf8a1c6ec008908bfca585cbc3ed91228dc64 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 16:36:45 +0100 Subject: [PATCH 16/74] Code-style --- src/ShellProvider/LocalShellProvider.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ShellProvider/LocalShellProvider.php b/src/ShellProvider/LocalShellProvider.php index ba9579c9..daeba8c5 100644 --- a/src/ShellProvider/LocalShellProvider.php +++ b/src/ShellProvider/LocalShellProvider.php @@ -229,5 +229,4 @@ public function createTunnelProcess(HostConfig $target_config, array $prefix = [ { throw new \InvalidArgumentException('Local shells cannot handle tunnels!'); } - -} \ No newline at end of file +} From ba86008215c425d6c7110611cbebf769404948e1 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 16:37:01 +0100 Subject: [PATCH 17/74] Add tty-option to ssh-shell-provider --- src/ShellProvider/ShellProviderInterface.php | 2 +- src/ShellProvider/SshShellProvider.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ShellProvider/ShellProviderInterface.php b/src/ShellProvider/ShellProviderInterface.php index d8311de0..8884622e 100644 --- a/src/ShellProvider/ShellProviderInterface.php +++ b/src/ShellProvider/ShellProviderInterface.php @@ -61,7 +61,7 @@ public function runProcess(array $cmd, TaskContextInterface $context, $interacti public function getShellCommand(array $options = []): array; - public function createShellProcess(array $command = []): Process; + public function createShellProcess(array $command = [], array $options = []): Process; public function createTunnelProcess(HostConfig $target_config, array $prefix = []); diff --git a/src/ShellProvider/SshShellProvider.php b/src/ShellProvider/SshShellProvider.php index a9a7b4f5..2d5f496f 100644 --- a/src/ShellProvider/SshShellProvider.php +++ b/src/ShellProvider/SshShellProvider.php @@ -96,6 +96,9 @@ public function getShellCommand(array $options = []): array $this->hostConfig['port'], ]; $this->addCommandOptions($command); + if (!empty($options['tty'])) { + $command[] = '-t'; + } $command[] = $this->hostConfig['user'] . '@' . $this->hostConfig['host']; return $command; From ab5135298d3ff79d730f37b0fb78e57e05cca506 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 16:37:16 +0100 Subject: [PATCH 18/74] Run drush command in interactive shell (fixes #3) --- src/Command/DrushCommand.php | 22 ++++++++++++---------- src/Method/DrushMethod.php | 13 ++++++------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/Command/DrushCommand.php b/src/Command/DrushCommand.php index b9dbe074..7c2dfed0 100644 --- a/src/Command/DrushCommand.php +++ b/src/Command/DrushCommand.php @@ -2,10 +2,7 @@ namespace Phabalicious\Command; -use Phabalicious\Configuration\HostConfig; -use Phabalicious\Exception\EarlyTaskExitException; use Phabalicious\Method\TaskContext; -use Phabalicious\Method\TaskContextInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -49,14 +46,19 @@ protected function execute(InputInterface $input, OutputInterface $output) $context = new TaskContext($this, $input, $output); $context->set('command', implode(' ', $input->getArgument('drush'))); - try { - $this->getMethods()->runTask('drush', $this->getHostConfig(), $context); - } catch (EarlyTaskExitException $e) { - return 1; - } + // Allow methods to override the used shellProvider: + $host_config = $this->getHostConfig(); + $this->getMethods()->runTask('drush', $host_config, $context); + $shell = $context->getResult('shell', $host_config->shell()); + $command = $context->getResult('command'); - return $context->getResult('exitCode', 0); - } + if (!$command) { + throw new \RuntimeException('No command-arguments returned for drush-command!'); + } + $output->writeln('Starting drush on `' . $host_config['configName'] . '`'); + $process = $this->startInteractiveShell($shell, $command); + return $process->getExitCode(); + } } diff --git a/src/Method/DrushMethod.php b/src/Method/DrushMethod.php index 8ea75ac2..6cf8b5a6 100644 --- a/src/Method/DrushMethod.php +++ b/src/Method/DrushMethod.php @@ -11,7 +11,6 @@ use Phabalicious\Validation\ValidationErrorBag; use Phabalicious\Validation\ValidationErrorBagInterface; use Phabalicious\Validation\ValidationService; -use webignition\ReadableDuration\ReadableDuration; class DrushMethod extends BaseMethod implements MethodInterface { @@ -234,8 +233,12 @@ public function drush(HostConfig $host_config, TaskContextInterface $context) /** @var ShellProviderInterface $shell */ $shell = $this->getShell($host_config, $context); $shell->cd($host_config['siteFolder']); - $result = $shell->run('#!drush ' . $command); - $context->setResult('exitCode', $result->getExitCode()); + $context->setResult('shell', $shell); + $command = sprintf('cd %s; #!drush %s', $host_config['siteFolder'], $command); + $command = $shell->expandCommand($command); + $context->setResult('command', [ + $command + ]); } private function handleModules( @@ -399,7 +402,6 @@ public function listBackups(HostConfig $host_config, TaskContextInterface $conte if ($tokens) { $result[] = $tokens; } - } $existing = $context->getResult('files', []); @@ -612,8 +614,5 @@ private function setupConfigurationManagement(HostConfig $host_config, TaskConte } $shell->cd($cwd); - - - } } From 13f2f2cdc90610a579fc9f5ce10a136207c0c005 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 16:38:34 +0100 Subject: [PATCH 19/74] Fix function declaration --- src/ShellProvider/LocalShellProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ShellProvider/LocalShellProvider.php b/src/ShellProvider/LocalShellProvider.php index daeba8c5..19845e52 100644 --- a/src/ShellProvider/LocalShellProvider.php +++ b/src/ShellProvider/LocalShellProvider.php @@ -54,7 +54,7 @@ public function validateConfig(array $config, ValidationErrorBagInterface $error ); } - public function createShellProcess(array $command = [], $options = []): Process + public function createShellProcess(array $command = [], array $options = []): Process { $shell_command = $this->getShellCommand($options); if (count($command) > 0) { From 5100c1082dd41adfeb4df138a176de4afd9d4775 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 16:40:41 +0100 Subject: [PATCH 20/74] Bump version number --- bin/phab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/phab b/bin/phab index e7b5f917..176ec14c 100755 --- a/bin/phab +++ b/bin/phab @@ -45,7 +45,7 @@ $output = $container->get(ConsoleOutput::class); /** @var Application $application */ $application = $container->get(Application::class); -$application->setVersion('3.0.0-alpha.1'); +$application->setVersion('3.0.0-alpha.2'); $application->setName('phabalicious'); $application->setDefaultCommand('list'); From 331a47626e2f0b464fb7cfdcd36d8b9b5950db21 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 19:23:45 +0100 Subject: [PATCH 21/74] Add preliminary documentation --- Changelog.md | 4 +- docs/docs/Changelog.md | 1 + docs/docs/available-tasks.md | 551 +++++++++++++++++++++++++++++++ docs/docs/configuration.md | 470 ++++++++++++++++++++++++++ docs/docs/contribute.md | 28 ++ docs/docs/css/version-select.css | 5 + docs/docs/docker-integration.md | 3 + docs/docs/index.md | 24 ++ docs/docs/installation.md | 56 ++++ docs/docs/js/version-select.js | 64 ++++ docs/docs/local-overrides.md | 30 ++ docs/docs/usage.md | 48 +++ docs/mkdocs.yml | 26 ++ 13 files changed, 1308 insertions(+), 2 deletions(-) create mode 120000 docs/docs/Changelog.md create mode 100644 docs/docs/available-tasks.md create mode 100644 docs/docs/configuration.md create mode 100644 docs/docs/contribute.md create mode 100644 docs/docs/css/version-select.css create mode 100644 docs/docs/docker-integration.md create mode 100644 docs/docs/index.md create mode 100644 docs/docs/installation.md create mode 100644 docs/docs/js/version-select.js create mode 100644 docs/docs/local-overrides.md create mode 100644 docs/docs/usage.md create mode 100644 docs/mkdocs.yml diff --git a/Changelog.md b/Changelog.md index 22d7204b..cc5b4b60 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,13 +2,13 @@ ## 3.0.0 -Fabalicious is now rewritten in PHP, so we changed then name to make the separation more clear. Phabalicious is now a symfony console app and uses a more unix-style approach to arguments and options. E.g. instead of `config:` use `--config=` +Fabalicious is now rewritten in PHP, so we changed the name to make the separation more clear. Phabalicious is now a symfony console app and uses a more unix-style approach to arguments and options. E.g. instead of `config:` use `--config=` ### Why the rewrite Python on Mac OS X is hard, multiple versions, multiple locations etc. Every machine needed some magic hands to get fabalicious working on it. Fabalicious itself is written in python 2.x, but the world is moving on to python 3. Fabric, the underlying lib we used for fabalicious is also moving forward to version 2 which is not backwards compatible yet with fabric 1. On the other side we are now maintaining more and more containerized setups where you do not need ssh to run commands in. A popular example is docker and its whole universe. Fabric couldn't help us here, and fabric is moving into a different direction. -And as a specialized Drupal boutique we write PHP all day long. To make it easier for our team to improve the toolset by ourselves and get help from the rest of the community using PHP/ Symfony as a base for the rewrite was a no-brainer. +And as a specialized Drupal boutique we write PHP all day long. To make it easier for our team to improve the toolset by ourselves and get help from the rest of the community, using PHP/ Symfony as a base for the rewrite was a no-brainer. Why not use existing tools, like [robo](https://robo.li/), [deployer](https://deployer.org/) or other tools? These tools are valuable instruments in our tool-belt, but none of them fit our requirements completely. We see phabalicious as a meta-tool integrating with all of them in nice and easy way. We need a lot of flexibility as we need to support a lot of different tech- and hosting-stacks, so we decided to port fabalicious to phabalicious. diff --git a/docs/docs/Changelog.md b/docs/docs/Changelog.md new file mode 120000 index 00000000..639240cb --- /dev/null +++ b/docs/docs/Changelog.md @@ -0,0 +1 @@ +../../Changelog.md \ No newline at end of file diff --git a/docs/docs/available-tasks.md b/docs/docs/available-tasks.md new file mode 100644 index 00000000..cce792f8 --- /dev/null +++ b/docs/docs/available-tasks.md @@ -0,0 +1,551 @@ +## --config + +```shell +phab --config= +``` + +Most of the phabalicious tasks need the option `config`. Setting the option will lookup `` in the `hosts`-section of your `fabfile.yaml` and the data will be used to run your task with the correct environment. + +## --offline + +```shell +phab --offline=1 --config= +``` + +This task will disable remote configuration files. As phabalicious keeps copies of remote configuration-files in `~/.phabalicious` it will try to load the configuration-file from there. + +## --fabfile +```shell +Phab --fabfile= --blueprint= +``` + +`blueprint` will try to load a blueprint-template from the fabfile.yaml and apply the input given as `` to the template. This is helpful if you want to create/ use a new configuration which has some dynamic parts like the name of the database, the name of the docker-container, etc. + +The task will look first in the host-config for the property `blueprint`, afterwards in the dockerHost-configuration `` and eventually in the global namespace. If you want to print the generated configuration as yaml, then use the `output`-command. The computed configuration is used as the current configuration, that means, you can run other tasks against the generated configuration. + +**Available replacement-patterns** and what they do. + +_Input is `feature/XY-123-my_Branch-name`, the project-name is `Example project`_ + +| Replacement Pattern | value | +|-----------------------------------------|-------------------------------| +| **%slug.with-hyphens.without-feature%** | xy-123-my-branch-name | +| **%slug.with-hyphens%** | feature-xy-123-my-branch-name | +| **%project-slug.with-hypens%** | example-project | +| **%slug%** | featurexy123mybranchname | +| **%project-slug%** | exampleproject | +| **%project-identifier%** | Example project | +| **%identifier%** | feature/XY-123-my_Branch-name | +| **%slug.without-feature%** | xy123mybranchname | + + +Here's an example blueprint: + +```yaml +blueprint: + inheritsFrom: http://some.host/data.yaml + configName: '%project-slug%-%slug.with-hyphens.without-feature%.some.host.tld' + branch: '%identifier%' + database: + name: '%slug.without-feature%_mysql' + docker: + projectFolder: '%project-slug%--%slug.with-hyphens.without-feature%' + vhost: '%project-slug%-%slug.without-feature%.some.host.tld' + name: '%project-slug%%slug.without-feature%_web_1' +``` + +And the output of `phab blueprint:feature/XY-123-my_Branch-name,configNamy=,output=true` is + +```yaml +hosts: + phbackend-xy-123-my-branch-name.some.host.tld: + branch: feature/XY-123-my_Branch-name + configName: phbackend-xy-123-my-branch-name.some.host.tld + database: + name: xy123mybranchname_mysql + docker: + name: phbackendxy123mybranchname_web_1 + projectFolder: phbackend--xy-123-my-branch-name + vhost: phbackend-xy123mybranchname.some.host.tld + inheritsFrom: http://some.host/data.yaml +``` + +**Note** + +You can create new configurations via the global `blueprints`-settings: + +``` +blueprints: + - configName: mbb + variants: + - de + - en + - it + - fr +``` + +will create 4 new configurations using the blueprint-config `mbb`. + +## list + +```shell +phab list +``` + +This command will list all available tasks. You can get specific help for a task with the next command: + +## help +```shell +phab help: +``` + +Will display all available arguments and options for that given `` and some explanatory text. + +## list:hosts + +```shell +phab list:hosts +``` + +This task will list all your hosts defined in your `hosts`-section of your `fabfile.yaml`. + +## list:blueprints + +```shell +Phab list:blueprints +``` + +This command will list all found blueprint configurations. + +## about + +```shell +phab --config= about +``` + +will display the configuration of host ``. + +## output + +```shell +Phab config= --blueprint= output +``` + +This command will print the computed configuration from a blueprint as yams. You can copy it and paste it back to the fabfile to make it permanent. + +## get:property + +```shell +phab --config= get:property +``` + +This will print the property-value to the console. Suitable if you want to use phabalicious from within other scripts. + +**Examples** + +* `phab --config=mbb get:property host` will print the hostname of configuration `mbb`. +* `phab -cmbb get:property docker.service` will print the service of the docker-configuration of `mbb`. + + +## version + +```shell +phab --config= version +``` + +This command will display the installed version of the code on the installation ``. + +**Available methods**: + +* `git`. The task will get the installed version via `git describe`, so if you tag your source properly (.e.g. by using git flow), you'll get a nice version-number. + +## deploy + +```shell +phab --config= deploy +phab --config= deploy +``` + +This task will deploy the latest code to the given installation. If the installation-type is not `dev` or `test` the `backupDB`-task is run before the deployment starts. If `` is stated the specific branch gets deployed. + +After a successfull deployment the `reset`-task will be run. + +**Available methods:** + +* `git` will deploy to the latest commit for the given branch defined in the host-configuration. Submodules will be synced, and updated. +* `platform` will push the current branch to the `platform` remote, which will start the deployment-process on platform.sh + +**Examples:** + +* `phab --config=mbb deploy` will deploy the app via the config found in `mob` +* `phab --config=mbb deploy feature/some-feature` will deploy the branch `feature/some-feature` regardless the setting in the fabfile. + +## reset + +```shell +phab config= reset +``` + +This task will reset your installation + +**Available methods:** + +* `composer` will run `composer install` to update any dependencies before doing the reset +* `drush` will + * set the site-uuid from fabfile.yaml (drupal 8) + * enable a deployment-module if any stated in the fabfile.yaml + * enable modules listed in file `modules_enabled.txt` + * disable modules listed in file `modules_disabled.txt` + * revert features (drupal 7) if `revertFeatures` is true / import the configuration (drupal 8), + * run update-hooks + * and does a cache-clear. + * if your host-type is `dev` the password gets reset to admin/admin + +**Examples:** + +* `phab --config=mbb reset` will reset the installation and will not reset the password. + +## install + +```shell +phab config= install +``` + +This task will install a new Drupal installation with the minimal-distribution. You can install different distributions, see the examples. + +**Available methods:** + +* `drush` + +**Configuration:** + +You can add a `installOptions`-section to your fabfile.yaml. Here's an example: + +```yaml +installOptions: + distribution: thunder + locale: es +``` + +**Examples:** + +* `phab --config=mbb install` will install a new Drupal installation +* `phab --config=mbb install --skip-reset=1` will install a new Drupal installation and will not run the reset-task afterwards. + + + +## install:from + +```shell +phab --config= install:from +``` + +This task will install a new installation (see the `install`-task) and afterwards will do a `copyFrom`. The `reset`-task after the `install`-task will be skipped and executed after the `copyFrom`-task. You can limit, what should be copied from: `db` or `files`. If `` is omitted, then everything is copied from. + +**See also:** + +* install +* copyFrom + +## backup + +```shell +phab --config= backup +``` + +This command will backup your files and database into the specified `backup`-directory. The file-names will include configuration-name, a timestamp and the git-SHA1. Every backup can be referenced by its filename (w/o extension) or, when git is abailable via the git-commit-hash. + +If `` is omitted, files and db gets backupped, you can limit this by providing `db` and/ or `files`. + +**Available methods:** + +* `git` will prepend the file-names with a hash of the current revision. +* `files` will tar all files in the `filesFolder` and save it into the `backupFolder` +* `drush` will dump the databases and save it to the `backupFolder` + +**Configuration:** + +* your host-configuration will need a `backupFolder` and a `filesFolder` + +**Examples** + +* `phab -cmbb backup` will backup everything +* `phab -cmbb backup files` will backup only public and private files. +* `phan -cmbb backup db` will backup the database only. + + +## list:backups + +```shell +phab --config= list:backups +``` + +This command will print all available backups to the console. + + +## restore + +```shell +phab --config= restore +``` + +This will restore a backup-set. A backup-set consists typically of a database-dump and a gzipped file-archive. You can a list of candidates via `phab --config= list:backups` + +**Available methods** + +* `git` git will checkout the given hash encoded in the filename. +* `files` all files will be restored. An existing files-folder will be renamed for safety reasons. +* `drush` will import the database-dump. + + +## get:backup + +```shell +phab --config: get:backup +``` + +This command will copy a remote backup-set to your local computer into the current working-directory. + +**See also:** + +* restore +* backup + + +## copy-from + +```shell +phab --config= copy-from +``` + +This task will copy all files via rsync from `source-config` to `dest-config` and will dump the database from `source-config` and restore it to `dest-config` when `` is omitted. + +After that the `reset`-task gets executed. This is the ideal task to copy a complete installation from one host to another. + +You can limit what to copy by adding `db` or `files` as arguments. + +**Available methods** + +* `ssh` will create all necessary tunnels to access the hosts. +* `files` will rsync all new and changed files from source to dest +* `drush` will dump the database and restore it on the dest-host. + +**Examples** + +* `phab -cmbb copy-from remote-host` will copy db and files from `remote-host` to `mbb` +* `phab -cmbb copy-from remote-host db` will copy only the db from `remote-host` to `mbb` +* `phab -cmbb copy-from remote-host` will copy only the files from `remote-host` to `mbb` + + +## drush + +```shell +phab --config= drush "" +``` + +This task will execute the `drush-command` on the remote host specified in . Please note, that you'll have to quote the drush-command when it contains spaces. + +**Available methods** + +* Only available for the `drush`-method + +**Examples** + +* `phab --config=staging drush "cc all -y"` +* `phab --config=local drush fra` + + +## drupal + +This task will execute a drupal-console task on the remote host. Please note, that you'll have to quote the command when it contains spaces. + +**Available methods** + +* Only available for the `drupal`-method + +**Examples** + +* `phab --config=local drupal cache:rebuild` +* `phab --config=local drupal "generate:module --module helloworld"` + +## platform + +```shell +phab --config= platform +``` + +Runs a specific platform-command. + +## get:file + +```shell +phab --config= get:file +``` + +Copy a remote file to the current working directory of your current machine. + +## put:file + +```shell +phab --config= put:file +``` + +Copy a local file to the tmp-folder of a remote machine. + +**Configuration** + +* this command will use the `tmpFolder`-host-setting for the destination directory. + + +## get:files-dump + +```shell +phab --config= get:files-dump +``` + +This task will tar all files in `filesFolder` and `privateFilesFolder` and download it to the local computer. + +**Available methods** + +* currently only implemented for the `files`-method + + +## get:sql-dump + +```shell +phab --config= get:sql-dump +``` + +Get a current dump of the remote database and copy it to the local machine into the current working directory. + +**Available methods** + +* currently only implemented for the `drush`-method + + +## restore:sql-from-file + +```shell +phab --config= restore:sql-from-file +``` + +This command will copy the dump-file `path-to-local-sql-dump` to the remote machine and import it into the database. + +**Available methods** + +* currently only implemented for the `drush`-method + + +## script + +```shell +phab --config= script +``` + +This command will run custom scripts on a remote machine. You can declare scripts globally or per host. If the `script-name` can't be found in the fabfile.yaml you'll get a list of all available scripts. + +Additional arguments get passed to the script. See the examples. + +**Examples** + +* `phab --config=mbb script`. List all available scripts for configuration `mbb` +* `phab --config=mbb script behat` Run the `behat`-script +* `phab --config=mbb script behat "--name="Login feature" --format=pretty"` Run the behat-test, apply `--name` and `--format` parameters to the script + +The `script`-command is rather powerful, have a read about it in the extra section. + +## docker + +```shell +phab --config= docker +``` + +The docker command is suitable for orchestrating and administering remote instances of docker-containers. The basic setup is that your host-configuration has a `docker`-section, which contains a `configuration`-key. The `dockerHosts`-section of your fabfile.yaml has a list of tasks which are executed on the "parent-host" of the configuration. Please have a look at the docker-section for more information. + +Most of the time the docker-container do not have a public or known ip-address. phabalicious tries to find out the ip-address of a given instance and use that for communicating with its services. + +There are three implicit tasks available: + +### copySSHKeys + +```shell +phab --config=mbb docker copySSHKeys +``` + +This will copy the ssh-keys into the docker-instance. You'll need to provide the paths to the files via the three configurations: +* `dockerKeyFile`, the path to the private ssh-key to use. +* `dockerAuthorizedKeyFile`, the path to the file for `authoried_keys` or a url. +* `dockerKnownHostsFile`, the path to the file for `known_hosts` + +As docker-container do not have any state, this task is used to copy any necessary ssh-configuration into the docker-container, so communication per ssh does not need any passwords. + +### waitForServices + +This task will try to run `supervisorctl status` in the container and waits until all services are running. This is useful in scripts to wait for any services that need some time to start up. Obviously this task depends on `supervisorctl`. + + +## start-remote-access + +```shell +phab --config= start-remote-access +phab --config= start-remote-access --port= --public-port= --public-ip= +``` + +This task will run a command to forward a local port to a remote port. It starts a new ssh-session which will do the forwarding. When finished, type `exit`. + +**Examples** + +* `phab --config=mbb start-remote-access` will forward `localhost:8888` to port `80` of the docker-container +* `phab --config=mbb start-remote-access --port=3306 --publicPort=33060` will forward `localhost:33060`to port `3306` + +## app:scaffold + +```shell +phab app:scaffold --name= --short-name="short name of app" --output= --override="1|0" +``` + +This command will scaffold a new project from a set of scaffold-files. See the dedicated documentation for how to create these files. + +**Examples** +* `phab app:scaffold path/to/scaffold.yml` will scaffold the app in the current folder. Phab will ask for the name and the short-name +* `phab app:scaffold path/to/scaffold.yml --name="Hello World" --short-name="HW"` will scaffold the app with name "Hello World and short-name "HW" +* `phab app:scaffold https://config.factorial.io/scaffold/drupal/d8.yml` will scaffold a Drupal app from the remote configuration. + +## app:create + +```shell +phab --config= app:create +``` + +This command will create a new app instance from a given config. Most useful with the usage of blueprints. + +The creation is done in several steps which can be customized. For a deeper explanation please have a look into the dedicated documentation + +## app:update + +```shell +phab --config= app:update +``` + +This command will update the code-base to the latest changes. When using the crush-method, drupal core will be updated to the latest version, if using `composer` then composer will be used to update the existing code. + +**Available methods** + +* `drush` will update Drupal-core, but only if `composer` is not used +* `composer` will update the codebase by running `composer update` + +## app:destroy + +```shell +phab --config= app:destroy +``` + +This command will destroy an app from a given configuration. The process has several steps. Caution: there will be no backup! \ No newline at end of file diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md new file mode 100644 index 00000000..44eb06ee --- /dev/null +++ b/docs/docs/configuration.md @@ -0,0 +1,470 @@ +# Structure of the configuration file + +## Overview + +The configuration is fetched from the file `fabfile.yaml` and should have the following structure: + +```yaml +name: + +needs: + - list of methods + +requires: 2.0 + +dockerHosts: + docker1: + ... + +hosts: + host1: + ... +``` + +Here's the documentation of the supported and used keys: + +### name + +The name of the project, it's only used for output. + +### needs + +List here all needed methods for that type of project. Available methods are: + + * `local` runs all commands for that configuration locally. + * `git` for deployments via git + * `ssh` + * `drush` for support of drupal installations + * `files` + * `Mattermost` for slack-notifications + * `docker` for docker-support + * `composer` for composer support + * `drupalconsole` for drupal-concole support + +**Example for drupal 7** + +```yaml +needs: + - ssh + - git + - drush + - files +``` + +**Example for drupal 8 composer based and dockerized** + +```yaml +needs: + - ssh + - git + - drush + - composer + - docker + - files +``` + + +### requires + +The file-format of phabalicious changed over time. Set this to the lowest version of phabalicious which can handle the file. Should bei `2.0` + +### hosts + +Hosts is a list of host-definitions which contain all needed data to connect to a remote host. Here's an example + +```yaml +hosts: + exampleHost: + host: example.host.tld + user: example_user + port: 2233 + type: dev + rootFolder: /var/www/public + gitRootFolder: /var/www + siteFolder: /sites/default + filesFolder: /sites/default/files + backupFolder: /var/www/backups + supportsInstalls: true|false + supportsCopyFrom: true|false + type: dev + branch: develop + docker: + ... + database: + ... + scripts: + ... + sshTunnel: + .. + +``` + +You can get all host-information including the default values using the phabalicious command `about`: + +```shell +phab --config=staging about +``` + +This will print all host configuration for the host `staging`. + +#### General keys + +* `type` defines the type of installation. Currently there are four types available: + * `dev` for dev-installations, they won't backup the databases on deployment + * `test` for test-installations, similar than `dev`, no backups on deployments + * `stage` for staging-installations. + * `prod` for live-installations. Some tasks can not be run on live-installations as `install` or as a target for `copyFrom` + The main use-case is to run different scripts per type, see the `common`-section. +* `rootFolder` the web-root-folder of the installation, typically exposed to the public. +* `needs` a list of needed methods, if not set, the globally set `needs` gets used. +* `configName` is set by phabalicious, it's the name of the configuration +* `supportsInstalls`, default is true for `types` != `prod`. If sent to true you can run the `install`-task +* `supportsCopyFrom`, default is true. If set to true, you can use that configuration as a source for the `copy-from`-task. +* `backupBeforeDeploy` is set to true for `types` `stage` and `prod`, if set to true, a backup of the DB is made before a deployment. +* `tmpFolder`, default is `/tmp`. +* `shellProvider` defines how to run a shell, where commands are executed, current values are + * `local`: all commands are run locally + * `ssh`: all commands are run via a ssh-shell + * `docker-exec` all commands are run via docker-exec. + +#### Configuration for the local-method + +* `shellProvider` default is `local`, see above. +* `shellExecutable` default is `/bin/bash` The executable for running a shell. Please note, that phabalicious requires a sh-compatible shell. +* `shellProviderExecutable`, the command, which will create the process for a shell, here `/bin/bash` + +#### Configuration for the ssh-method + +* `host`, `user`, `port` are used to connect via SSH to the remote machine. Please make sure SSH key forwarding is enabled on your installation. +* `disableKnownHosts`, default is false, set to true to ignore the known_hosts-file. +* `sshTunnel` phabalicious supports SSH-Tunnels, that means it can log in into another machine and forward the access to the real host. This is handy for dockerized installations, where the ssh-port of the docker-instance is not public. `sshTunnel` needs the following informations + * `bridgeHost`: the host acting as a bridge. + * `bridgeUser`: the ssh-user on the bridge-host + * `bridgePort`: the port to connect to on the bridge-host + * `localPort`: the local port which gets forwarded to the `destPort`. If `localPort` is omitted, the ssh-port of the host-configuration is used. If the host-configuration does not have a port-property a random port is used. + * `destHost`: the destination host to forward to + * `destHostFromDockerContainer`: if set, the docker's Ip address is used for destHost. This is automatically set when using a `docker`-configuration, see there. + * `destPort`: the destination port to forward to + * `shellProviderExecutable`, default is `/usr/bin/ssh`, the executable to establish the connection. + + +#### Configuration for the git-method + +* `gitRootFolder` the folder, where the git-repository lies. Defaults to `rootFolder` +* `branch` the name of the branch to use for deployments, they get usually checked out and pulled from origin. +* `ignoreSubmodules` default is false, set to false, if you don't want to update a projects' submodule on deploy. +* `gitOptions` a keyed list of options to apply to a git command. Currently only pull is supported. If your git-version does not support `--rebase` you can disable it via an empty array: `pull: []` + +#### Configuration for the composer-method + +* `composerRootFolder` the folder where the composer.json for the project is stored, defaults to `gitRootFolder`. + +#### Configuration for the crush-method + +* `siteFolder` is a drupal-specific folder, where the settings.php resides for the given installation. This allows to interact with multisites etc. +* `filesFolder` the path to the files-folder, where user-assets get stored and which should be backed up by the `files`-method +* `revertFeatures`, defaults to `True`, when set all features will be reverted when running a reset (drush only) +* `configurationManagement`, an array of configuration-labels to import on `reset`, defaults to `['staging']`. You can add command arguments for drush, e.g. `['staging', 'dev --partial']` +* `database` the database-credentials the `install`-tasks uses when installing a new installation. + * `name` the database name + * `host` the database host + * `user` the database user + * `pass` the password for the database user + * `prefix` the optional table-prefix to use +* `adminUser`, default is `admin`, the name of the admin-user to set when running the reset-task on `dev`-instances +* `replaceSettingsFile`, default is true. If set to false, the settings.php file will not be replaced when running an install. +* `installOptions` default is `distribution: minimal, locale: en, options: ''`. You can change the distribution to install and/ or the locale. +* `drupalVersion` set the drupal-version to use. If not set phabalicious is trying to guess it from the `needs`-configuration. +* `drushVersion` set the used crush-version, default is `8`. Drush is not 100% backwards-compatible, for phabalicious needs to know its version. +* `supportsZippedBackups` default is true, set to false, when zipped backups are not supported +#### Configuration of the docker-method + +* `docker` for all docker-relevant configuration. `configuration` and `name`/`service` are the only required keys, all other are optional and used by the docker-tasks. + * `configuration` should contain the key of the dockerHost-configuration in `dockerHosts` + * `name` contains the name of the docker-container. This is needed to get the IP-address of the particular docker-container when using ssh-tunnels (see above). + * for docker-compose-base setups you can provide the `service` instead the name, phabalicious will get the docker name automatically from the service. + + + + + +### dockerHosts + +`dockerHosts` is similar structured as the `hosts`-entry. It's a keyed lists of hosts containing all necessary information to create a ssh-connection to the host, controlling the docker-instances, and a list of tasks, the user might call via the `docker`-command. See the `docker`-entry for a more birds-eye-view of the concepts. + +Here's an example `dockerHosts`-entry: + +```yaml +dockerHosts: + mbb: + runLocally: false + host: multibasebox.dev + user: vagrant + password: vagrant + port: 22 + rootFolder: /vagrant + environment: + VHOST: %host.host% + WEBROOT: %host.rootFolder% + tasks: + logs: + - docker logs %host.docker.name% +``` + +Here's a list of all possible entries of a dockerHosts-entry: +* `shellProvider`, the shell-provider to use, currently `local` or `ssh`. +* `runLocally`: if set to true, the `local`-shell-provider will be used. +* `host`, `user` and `port`: when using the `ssh`-shell-provicer. +* `environment` a keyed list of environment-variables to set, when running one of the tasks. The replacement-patterns of `scripts` are supported, see there for more information. +* `tasks` a keyed list of commands to run for a given docker-subtask (similar to `scripts`). Note: these commands are running on the docker-host, not on the host. All replacement-patterns do work, and you can call even other tasks via `execute(, )` e.g. `execute(docker, stop)` See the `scripts`-section for more info. + +You can use `inheritsFrom` to base your configuration on an existing one. You can add any configuration you may need and reference to that information from within your tasks via the replacement-pattern `%dockerHost.keyName%` e.g. `%dockerHost.host%`. + +You can reference a specific docker-host-configuration from your host-configuration via + +```yaml +hosts: + test: + docker: + configuration: mbb +``` + +### common + +common contains a list of commands, keyed by task and type which gets executed when the task is executed. + +Example: +```yaml +common: + reset: + dev: + - echo "running reset on a dev-instance" + stage: + - echo "running reset on a stage-instance" + prod: + - echo "running reset on a prod-instance" + deployPrepare: + dev: + - echo "preparing deploy on a dev instance" + deploy: + dev: + - echo "deploying on a dev instance" + deployFinished: + dev: + - echo "finished deployment on a dev instance" +``` + +The first key is the task-name (`reset`, `deploy`, ...), the second key is the type of the installation (`dev`, `stage`, `prod`, `test`). Every task is prepended by a prepare-stage and appended by a finished-stage, so you can call scripts before and after an actual task. You can even run other scripts via the `execute`-command, see the `scripts`-section. + +### scripts + +A keyed list of available scripts. This scripts may be defined globally (on the root level) or on a per host-level. The key is the name of the script and can be executed via + +```shell +phab --config= script +``` + +A script consists of an array of commands which gets executed sequentially. + +An example: + +```yaml +scripts: + test: + - echo "Running script test" + test2: + - echo "Running script test2 on %host.config_name% + - execute(script, test) +``` + +Scripts can be defined on a global level, but also on a per host-level. + +You can declare default-values for arguments via a slightly modified syntax: + +```yaml +scripts: + defaultArgumentTest: + defaults: + name: Bob + script: + - echo "Hello %arguments.name%" +``` + +Running the script via `phab config:mbb script:defaultArgumentTest,name="Julia"` will show `Hello Julia`. Running `phab config:mbb script:defaultArgumentTest` will show `Hello Bob`. + +For more information see the main scripts section below. + +### other + +* `deploymentModule` name of the deployment-module the drush-method enables when doing a deploy +* `sqlSkipTables` a list of table-names drush should omit when doing a backup. +* `configurationManagement` a list of configuration-labels to import on `reset`. This defaults to `['staging']` and may be overridden on a per-host basis. You can add command arguments to the the configuration label. + +Example: +```yaml +deploymentModule: my_deployment_module +usePty: false +useShell: false +gitOptions: + pull: + - --rebase + - --quiet +sqlSkipTables: + - cache + - watchdog + - session +configurationManagement: + staging: + - drush config-import -y staging + dev: + - Drusch config-import -y dev --partial +``` + + +## Inheritance + +Sometimes it make sense to extend an existing configuration or to include configuration from other places from the file-system or from remote locations. There's a special key `inheritsFrom` which will include the yaml found at the location and merge it with the data. This is supported for entries in `hosts` and `dockerHosts` and for the fabfile itself. + +If a `host`, a `dockerHost` or the fabfile itself has the key `inheritsFrom`, then the given key is used as a base-configuration. Here's a simple example: + +```yaml +hosts: + default: + port: 22 + host: localhost + user: default + example1: + inheritsFrom: default + port: 23 + example2: + inheritsFrom: example1 + user: example2 +``` + +`example1` will store the merged configuration from `default` with the configuration of `example1`. `example2` is a merge of all three configurations: `example2` with `example1` with `default`. + +```yaml +hosts: + example1: + port: 23 + host: localhost + user: default + example2: + port: 23 + host: localhost + user: example2 +``` + +You can even reference external files to inherit from: + +```yaml +hosts: + fileExample: + inheritsFrom: ./path/to/config/file.yaml + httpExapme: + inheritsFrom: http://my.tld/path/to/config_file.yaml +``` + +This mechanism works also for the fabfile.yaml / index.yaml itself, and is not limited to one entry: + +```yaml +name: test fabfile + +inheritsFrom: + - ./mbb.yaml + - ./drupal.yaml +``` + + + +# Scripts + +Scripts are a powerful concept of phabalicious. There are a lot of places where scripts can be called. The `common`-section defines common scripts to be run for specific task/installation-type-configurations, docker-tasks are also scripts which you can execute via the docker-command. And you can even script phabalicious tasks and create meta-tasks. + +A script is basically a list of commands which get executed via shell on a remote machine. To stay independent of the host where the script is executed, phabalicious parsed the script before executing it and replaces given variables with their counterpart in the yams file. + +## Replacement-patterns + +Replacement-Patterns are specific strings enclosed in `%`s, e.g. `%host.port%`, `%dockerHost.rootFolder%` or `%arguments.name%`. + +Here's a simple example; + +```yaml +script: + test: + - echo "I am running on %host.config_name%" +``` + +Calling this script via + +```shell +phab config:mbb script:test +``` + +will show `I am running on mbb`. + +* The host-configuration gets exposes via the `host.`-prefix, so `port` maps to `%host.port%`, etc. +* The dockerHost-configuration gets exposed via the `dockerHost`-prefix, so `rootFolder` maps to `%dockerHost.rootFolder%` +* The global configuration of the yams-file gets exposed to the `settings`-prefix, so `uuid` gets mapped to `%settings.uuid% +* Optional arguments to the `script`-taks get the `argument`-prefix, e.g. `%arguments.name%`. You can get all arguments via `%arguments.combined%`. +* You can access hierarchical information via the dot-operator, e.g. `%host.database.name%` + +If phabalicious detects a pattern it can't replace it will abort the execution of the script and displays a list of available replacement-patterns. + +## Internal commands + +There are currently 3 internal commands. These commands control the flow inside phabalicious: + +* `fail_on_error(1|0)` If fail_on_error is set to one, phabalicious will exit if one of the script commands returns a non-zero return-code. When using `fail_on_error(0)` only a warning is displayed, the script will continue. +* `execute(task, subtask, arguments)` execute a phabalicious task. For example you can run a deployment from a script via `execute(deploy)` or stop a docker-container from a script via `execute(docker, stop)` +* `fail_on_missing_directory(directory, message)` will print message `message` if the directory `directory` does not exist. + +## Task-related scripts + +You can add scripts to the `common`-section, which will called for any host. You can differentiate by task-name and host-type, e.g. create a script which gets called for the task `deploy` and type `dev`. + +You can even run scripts before or after a task is executed. Append the task with `Prepare` or `Finished`. + +You can even run scripts for specific tasks and hosts. Just add your script with the task-name as its key. + +```yaml +host: + test: + deployPrepare: + - echo "Preparing deploy for test" + deploy: + - echo "Deploying on test" + deployFinished: + - echo "Deployment finished for test" +``` + +These scripts in the above examples gets executed only for the host `test` and task `deploy`. + +## Examples + +A rather complex example scripting phabalicious. + +```yaml +scripts: + runTests: + defaults: + branch: develop + script: + - execute(docker, start) + - execute(docker, waitForServices) + - execute(deploy, %arguments.branch%) + - execute(script, behatInstall) + - execute(script, behat, --profile=ci --format=junit --format=progress) + - execute(getFile, /var/www/_tools/behat/build/behat/default.xml, ./_tools/behat) + - execute(docker, stop) +``` + +This script will + +* start the docker-container, +* wait for it, +* deploys the given branch, +* run a script which will install behat, +* run behat with some custom arguments, +* gets the result-file and copy it to a location, +* and finally stops the container. diff --git a/docs/docs/contribute.md b/docs/docs/contribute.md new file mode 100644 index 00000000..5d72f6ec --- /dev/null +++ b/docs/docs/contribute.md @@ -0,0 +1,28 @@ +# Contributing to Fabalicious + +If you get stuck at any point you can create a [ticket on GitHub](https://github.com/factorial-io/fabalicious/issues). + +## Contributing to development + +_@TODO_ + +## Improving Documenation + +_@TODO_ + + +!!! tip + To edit existing pages, use the **Edit on GitHub** link on the top right corner of the page. + + To add a new page to documentation please follow [the guideline provided by MKdocs](http://www.mkdocs.org/user-guide/writing-your-docs/#configure-pages-and-navigation) to add new page and link them within the documentation. + +!!! note + This document is build using [MkDocs](http://www.mkdocs.org/) and served using [GitHub Pages](https://pages.github.com/) + + - [Install MkDocs](http://www.mkdocs.org/#installation). + - Clone [the repo](https://github.com/factorial-io/fabalicious) locally and switch to `develop` branch. + - Using Terminal, navigate to `/docs` folder. + - Run `mike deploy ` + +### Resources +* [Writing your docs in MKdocs](http://www.mkdocs.org/user-guide/writing-your-docs/) diff --git a/docs/docs/css/version-select.css b/docs/docs/css/version-select.css new file mode 100644 index 00000000..56e00f2a --- /dev/null +++ b/docs/docs/css/version-select.css @@ -0,0 +1,5 @@ +#version-selector { + display: block; + margin: -10px auto 0.809em; + padding: 2px; +} diff --git a/docs/docs/docker-integration.md b/docs/docs/docker-integration.md new file mode 100644 index 00000000..cb769773 --- /dev/null +++ b/docs/docs/docker-integration.md @@ -0,0 +1,3 @@ +# Docker integration + +TODO \ No newline at end of file diff --git a/docs/docs/index.md b/docs/docs/index.md new file mode 100644 index 00000000..a1f018ee --- /dev/null +++ b/docs/docs/index.md @@ -0,0 +1,24 @@ +# How does phabalicious work in two sentences + +Phabalicious is using configuration stored in a special file in the root of your project (the `fabfile.yaml`) to run tasks in a shell. This shell can be provided by a docker-container, a ssh-connection or a local shell. This means, you can store all your devops-configuration in the fabfile and apply it to a list of configurations. Phabalicious tries to abstract away the inner workings of a host and give the user a handful useful commands to run common tasks, like: + + * deploying new code to a remote installation + * reset a remote installation to its defaults. + * backup/ restore data + * copy data from one installation to another + * scaffold new projects + * run scripts on different local or remote installations. + * handle SSH-tunnels transparently + * optionally work with our docker-based local development-stack [multibasebox](https://github.com/factorial-io/multibasebox) + +## History + +Phabalicious started as a shell-script to reset a Drupal-installation. We used fabric as a base for all the tasks and fabalicious grew to its first official release 1.0. + +But it got unmaintainable, as it was not flexible enough to handle new requirements, so the first rewrite started to get a more modular and extendable version: Fabalicious 2.0. It supported hooks for custom scripts, was extendable by new methods, later on it got a complete plugin-system and what not. + +Meanwhile fabric (the foundation of fabalicious) took a different route. Fabric 2.0 was not compatible anymore with 1.x and so with fabalicious. As most of our users were on OS X, handling the python dependencies got also more complicated. And only a handful devs in our company could write python. Another hurdle was that fabric supports SSH and local connections only, running commands in different ways (like `docker exec`) was cumbersome. + +So the idea was born, to do another rewrite in PHP and use Symfony console as a base for it. + +Phabalicious 3 still supports the fabfile-format from version 2, but the command-line syntax changed a lot, and is now more compliant with posix. diff --git a/docs/docs/installation.md b/docs/docs/installation.md new file mode 100644 index 00000000..5e92372e --- /dev/null +++ b/docs/docs/installation.md @@ -0,0 +1,56 @@ +# Installation of needed dependencies + +Phabalicious needs at least PHP 7.1 with the json- and openss-extensions. The best way is to install it globally. + +## Download phar + +* Download the latest version from [Github](https://github.com/factorial-io/phabalicious/releases) +* copy the phar to a suitable folder, e.g. `/usr/local/bin` and rename it to `phab` +* Make it executable, e.g. `chmod u+x /usr/local/bin/phab` + +## Installation from source + +* Clone the repository via `git clone https://github.com/factorial-io/phabalicious.git` +* cd into the folder +* run `composer install` +* run `composer build-phar` +* run `composer install-phar`, this will copy the phar to `/usr/local/bin` and make it executable. + +## Install it as a project dependency + +* run `composer require factorial-io/phabalicious` + +Note, phabalicious is using Symfony 4 so you might get some unresolvable conflicts (Merge Requests welcome!) + +## and then ... + +1. Run `fab list`, this should give you a list of all available commands. +2. Create a configuration file called `fabfile.yaml` + +# A simple configuration-example + +```yaml +name: My awesome project + +# We'll need phabalicious >= 3.0 +requires: 3.0 + +# We need git and ssh, there are more options +needs: + - ssh + - git + +# Our list of host-configurations +hosts: + dev: + host: myhost.test + user: root + port: 22 + type: dev + branch: develop + rootFolder: /var/www + backupFolder: /var/backups +``` + +For more infos about the file-format have a look at the file-format-section. + diff --git a/docs/docs/js/version-select.js b/docs/docs/js/version-select.js new file mode 100644 index 00000000..3df2a71c --- /dev/null +++ b/docs/docs/js/version-select.js @@ -0,0 +1,64 @@ +window.addEventListener("DOMContentLoaded", function() { + function normalizePath(path) { + var normalized = []; + path.split("/").forEach(function(bit, i) { + if (bit === "." || (bit === "" && i !== 0)) { + return; + } else if (bit === "..") { + if (normalized.length === 1 && normalized[0] === "") { + // We must be trying to .. past the root! + throw new Error("invalid path"); + } else if (normalized.length === 0 || + normalized[normalized.length - 1] === "..") { + normalized.push(".."); + } else { + normalized.pop(); + } + } else { + normalized.push(bit); + } + }); + return normalized.join("/"); + } + + // `base_url` comes from the base.html template for this theme. + var REL_BASE_URL = base_url; + var ABS_BASE_URL = normalizePath(window.location.pathname + "/" + + REL_BASE_URL); + var CURRENT_VERSION = ABS_BASE_URL.split("/").pop(); + + function makeSelect(options, selected) { + var select = document.createElement("select"); + + options.forEach(function(i) { + var option = new Option(i.text, i.value, undefined, + i.value === selected); + select.add(option); + }); + + return select; + } + + var xhr = new XMLHttpRequest(); + xhr.open("GET", REL_BASE_URL + "/../versions.json"); + xhr.onload = function() { + var versions = JSON.parse(this.responseText); + + var realVersion = versions.find(function(i) { + return i.version === CURRENT_VERSION || + i.aliases.includes(CURRENT_VERSION); + }).version; + + var select = makeSelect(versions.map(function(i) { + return {text: i.title, value: i.version}; + }), realVersion); + select.id = "version-selector"; + select.addEventListener("change", function(event) { + window.location.href = REL_BASE_URL + "/../" + this.value; + }); + + var title = document.querySelector("div.wy-side-nav-search"); + title.insertBefore(select, title.querySelector(".icon-home").nextSibling); + }; + xhr.send(); +}); diff --git a/docs/docs/local-overrides.md b/docs/docs/local-overrides.md new file mode 100644 index 00000000..f973bd20 --- /dev/null +++ b/docs/docs/local-overrides.md @@ -0,0 +1,30 @@ +# Local overrides + +`fabfile.local.yaml` is used to override parts of your fabfile-configuration. If you run a fab-command the code will try to find the `fabfile.local.yaml` up to three folder levels up and merge the data with your fabfile.yaml. + +A small example: + +``` +fabfile.local.yaml ++ project + fabfile.yaml +``` + +Contents fo fabfile.yaml +```yaml +hosts: + local: + host: multibasebox.dev + port: 22 + [...] +``` + +Contents of fabfile.local.yaml: +```yaml +hosts: + local: + host: localhost + port: 2222 +``` + +This will override the `host` and `port` settings of the `local`-configuration. With this technique you can alter an existing fabfile.yaml with local overrides. (In this example, `host=localhost` and `port=2222` \ No newline at end of file diff --git a/docs/docs/usage.md b/docs/docs/usage.md new file mode 100644 index 00000000..7a38d37d --- /dev/null +++ b/docs/docs/usage.md @@ -0,0 +1,48 @@ +# Running phabalicious + +To execute a task with the help of phabalicious, just + +```shell +cd +phab --config= +``` + +This will read your fabfile.yaml, look for `` in the host-section and run the task + +# Tasks + +## Some Background + +Phabalicious provides a set of so-called methods which implement all listed functionality. The following methods are available: + +* local +* git +* ssh +* drush +* composer +* files +* docker +* drupalconsole +* mattermost +* platform + +You declare your needs in the fabfile.yaml with the key `needs`, e.g. + +```yaml +needs: + - git + - ssh + - drush + - files +``` + +Have a look at the file-format documentation for more info. + +## List of available tasks + + +You can get a list of available commands with + +```shell +phab list +``` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 00000000..88ed8e4c --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,26 @@ +site_name: Phabalicious +theme: readthedocs +markdown_extensions: + - admonition + +repo_url: https://github.com/factorial-io/phabalicious/ +repo_name: GitHub +edit_uri: edit/develop/docs/docs/ +site_description: Phabalicious Documentation +site_author: Factorial GmbH, Hamburg +copyright: © 2018 Factorial GmbH, Hamburg + +pages: + - index.md + - installation.md + - usage.md + - available-tasks.md + - configuration.md + - docker-integration.md + - local-overrides.md + - contribute.md + - changelog.md +extra_css: + - css/version-select.css +extra_javascript: + - js/version-select.js From 1055b90e5f4897bb1527da905c7025e59de6a8b6 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 20:00:39 +0100 Subject: [PATCH 22/74] Fix some docs --- docs/docs/contribute.md | 13 +++++++------ docs/mkdocs.yml | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/docs/contribute.md b/docs/docs/contribute.md index 5d72f6ec..5a1a8181 100644 --- a/docs/docs/contribute.md +++ b/docs/docs/contribute.md @@ -1,15 +1,16 @@ -# Contributing to Fabalicious +# Contributing to Phabalicious -If you get stuck at any point you can create a [ticket on GitHub](https://github.com/factorial-io/fabalicious/issues). +If you get stuck at any point you can create a [ticket on GitHub](https://github.com/factorial-io/phabalicious/issues). ## Contributing to development -_@TODO_ +It's the usual, fork the repository, create a feature-branch, do your changes and submit a pull-request via Github. If your new feature has test-coverage the better. -## Improving Documenation +We are happy for every contribution. -_@TODO_ +## Improving documenation +The procedure is the same as with contributing code. !!! tip To edit existing pages, use the **Edit on GitHub** link on the top right corner of the page. @@ -20,7 +21,7 @@ _@TODO_ This document is build using [MkDocs](http://www.mkdocs.org/) and served using [GitHub Pages](https://pages.github.com/) - [Install MkDocs](http://www.mkdocs.org/#installation). - - Clone [the repo](https://github.com/factorial-io/fabalicious) locally and switch to `develop` branch. + - Clone [the repo](https://github.com/factorial-io/phabalicious) locally and switch to `develop` branch. - Using Terminal, navigate to `/docs` folder. - Run `mike deploy ` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 88ed8e4c..4eed57a7 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -19,7 +19,7 @@ pages: - docker-integration.md - local-overrides.md - contribute.md - - changelog.md + - Changelog.md extra_css: - css/version-select.css extra_javascript: From ac3aa87ca23b79e86545b9b548cd68ad74ebc93c Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 20:08:56 +0100 Subject: [PATCH 23/74] Update readme.md --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index 8f554e28..be981873 100644 --- a/readme.md +++ b/readme.md @@ -24,3 +24,7 @@ Phabalicious is the successor of the python tool [fabalicious](https://github.co * Run `phab list` to get a list of all available commands. * run `phab help ` to get some help for a given command. + +## Documentation + +You can find an extensive documentation at [https://factorial-io.github.io/phabalicious](https://factorial-io.github.io/phabalicious) From 041747186c7eac8272c000b1c31e26dde7d3fc26 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 20:09:54 +0100 Subject: [PATCH 24/74] Update installation.md --- docs/docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/installation.md b/docs/docs/installation.md index 5e92372e..1d3bd871 100644 --- a/docs/docs/installation.md +++ b/docs/docs/installation.md @@ -1,6 +1,6 @@ # Installation of needed dependencies -Phabalicious needs at least PHP 7.1 with the json- and openss-extensions. The best way is to install it globally. +Phabalicious needs at least PHP 7.1 with the json- and openssl-extensions. The best way is to install it globally by downloading the phar-file: ## Download phar From 8f672900c51c5028a27aa550152047591c36070f Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 20:11:06 +0100 Subject: [PATCH 25/74] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6ca381cc..502dc756 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ /bin/console /bin/phpunit /build/phabalicious.phar +/docs/site From 7bcd2028266329cf0f13a3135c7705f31c2b719f Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 20:14:40 +0100 Subject: [PATCH 26/74] Update contribute.md --- docs/docs/contribute.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/contribute.md b/docs/docs/contribute.md index 5a1a8181..725b403d 100644 --- a/docs/docs/contribute.md +++ b/docs/docs/contribute.md @@ -18,12 +18,12 @@ The procedure is the same as with contributing code. To add a new page to documentation please follow [the guideline provided by MKdocs](http://www.mkdocs.org/user-guide/writing-your-docs/#configure-pages-and-navigation) to add new page and link them within the documentation. !!! note - This document is build using [MkDocs](http://www.mkdocs.org/) and served using [GitHub Pages](https://pages.github.com/) - + This document is build using [MkDocs](http://www.mkdocs.org/), [Mike](https://github.com/jimporter/mike) and served using [GitHub Pages](https://pages.github.com/) - [Install MkDocs](http://www.mkdocs.org/#installation). + - [Install Mike](https://github.com/jimporter/mike) - Clone [the repo](https://github.com/factorial-io/phabalicious) locally and switch to `develop` branch. - Using Terminal, navigate to `/docs` folder. - - Run `mike deploy ` + - Run `mike deploy --push` ### Resources * [Writing your docs in MKdocs](http://www.mkdocs.org/user-guide/writing-your-docs/) From a1ab875b9a24e41c90624c4ae786a780cb178a26 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 20:14:59 +0100 Subject: [PATCH 27/74] Update contribute.md --- docs/docs/contribute.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/contribute.md b/docs/docs/contribute.md index 725b403d..37d9afbb 100644 --- a/docs/docs/contribute.md +++ b/docs/docs/contribute.md @@ -19,6 +19,7 @@ The procedure is the same as with contributing code. !!! note This document is build using [MkDocs](http://www.mkdocs.org/), [Mike](https://github.com/jimporter/mike) and served using [GitHub Pages](https://pages.github.com/) + - [Install MkDocs](http://www.mkdocs.org/#installation). - [Install Mike](https://github.com/jimporter/mike) - Clone [the repo](https://github.com/factorial-io/phabalicious) locally and switch to `develop` branch. From 17335ad324ab1e9b067c305ce1c7fc668f56041c Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 23:43:14 +0100 Subject: [PATCH 28/74] Fix code-style --- .pre-commit-config.yaml | 13 +++++++++++++ src/Configuration/BlueprintTemplate.php | 4 +--- src/Configuration/ConfigurationService.php | 4 +--- 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..4c8edd21 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +- repo: https://github.com/digitalpulp/pre-commit-php.git + sha: 1.3.0 + hooks: + - id: php-lint + files: \.php$ + - id: php-cs + files: \.php$ + args: + - --standard=PSR2 -p + - id: php-cbf + files: \.php$ + args: + - --standard=PSR2 -p diff --git a/src/Configuration/BlueprintTemplate.php b/src/Configuration/BlueprintTemplate.php index 9b1c4e85..34911948 100644 --- a/src/Configuration/BlueprintTemplate.php +++ b/src/Configuration/BlueprintTemplate.php @@ -2,7 +2,6 @@ namespace Phabalicious\Configuration; - use Phabalicious\Utilities\Utilities; class BlueprintTemplate @@ -44,5 +43,4 @@ public function expand($identifier) return Utilities::expandStrings($this->template, $replacements); } - -} \ No newline at end of file +} diff --git a/src/Configuration/ConfigurationService.php b/src/Configuration/ConfigurationService.php index 209d841f..597e233f 100644 --- a/src/Configuration/ConfigurationService.php +++ b/src/Configuration/ConfigurationService.php @@ -134,7 +134,6 @@ public function readConfiguration(string $path, string $override = ''): bool $disallow_deep_merge_for_keys, $method->getKeysForDisallowingDeepMerge() ); - } foreach ($this->methods->all() as $method) { $data = $this->applyDefaults( @@ -617,5 +616,4 @@ public function setOffline($offline) { $this->offlineMode = $offline; } - -} \ No newline at end of file +} From 300090a0f3b405f45adf27ece7c2e1c13227cd24 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 2 Dec 2018 23:53:51 +0100 Subject: [PATCH 29/74] Add php-unit to pre-commit hook, uopdate readme --- .pre-commit-config.yaml | 2 ++ readme.md | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c8edd21..2aec5c81 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,3 +11,5 @@ files: \.php$ args: - --standard=PSR2 -p + - id: php-unit + files: \.php$ diff --git a/readme.md b/readme.md index be981873..2ad5f8e2 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,13 @@ Phabalicious is the successor of the python tool [fabalicious](https://github.co * Run `phab list` to get a list of all available commands. * run `phab help ` to get some help for a given command. +## Enhancing phab, contributing to phab + +We welcome contributions! Please fork the repository, create a feature branch and submit a pull-request. +Please add test-cases for your bug-fixes or new features. We are using [pre-commit](https://pre-commit.com/) to check code-style (PSR2) etc. + +* Run `pre-commit install` to install the pre-commit-hooks. + ## Documentation You can find an extensive documentation at [https://factorial-io.github.io/phabalicious](https://factorial-io.github.io/phabalicious) From a8e0ab6bd95c7214a6db50156b69fdb74b2de992 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 3 Dec 2018 00:28:08 +0100 Subject: [PATCH 30/74] Add more documentation --- docs/docs/app-scaffold.md | 227 +++++++++++++++++++++++++++++++++++ docs/docs/available-tasks.md | 15 +++ docs/mkdocs.yml | 1 + 3 files changed, 243 insertions(+) create mode 100644 docs/docs/app-scaffold.md diff --git a/docs/docs/app-scaffold.md b/docs/docs/app-scaffold.md new file mode 100644 index 00000000..1db48e4a --- /dev/null +++ b/docs/docs/app-scaffold.md @@ -0,0 +1,227 @@ +# Scaffolding a new app + +Phabalicious has a simple but powerful scaffold-command. It will read a yml-file and interpret the contents. It will use the existing pattern-replacement used for scripts and twig for changing file-contents. The scaffolding and fixture-files can live remotely or on your file-system. + +Here's an example of a scaffold-file: + +```yaml +variables: + composerProject: drupal-composer/drupal-project:8.x-dev + webRoot: web + +assets: + - .fabfile.yaml + - docker-compose.yml + - docker-compose-mbb.yml + +deployModuleAssets: + - deployModule/%shortName%_deploy.info.yml + - deployModule/%shortName%_deploy.module + - deployModule/%shortName%_deploy.install + +scaffold: + - rm -rf %rootFolder% + - composer create-project %composerProject% %rootFolder% --stability dev --no-interaction + - cd %rootFolder%; composer require drupal/coffee + - cd %rootFolder%; composer require drupal/devel + - copy_assets(%rootFolder%) + - copy_assets(%rootFolder%/%webRoot%/modules/custom/%shortName%_deploy, deployModuleAssets) + - cd %rootFolder%; git init . + - cd %rootFolder%; git add . + - cd %rootFolder%; git commit -m "Initial commit by phabalicious" +``` + +The fabfile needs at least the `scaffold`-section. The `scaffold`-section is a list of commands, executed by phabalicious one by one. It will use the pattern-replacement known for scripts. + +## The `scaffold`-section +Phabalicious will provide the following replacement-patterns out of the box: + +||Pattern||Value|| +|%rootFolder%|The folder the app will be installed into| +|%name%|The name of the app| +|%projectFolder%|a cleaned version of the app-name, suitable for machine-names.| +|%shortName%|The short-name| +|%uuid|a random-uuid| + +## the `variables`-section +You can add own variables via the `variables`-section. In the above example, the variable `composerProject` will be available in the `scaffold`-section via the pattern `%composerProject%` + +## the `assets`-section +You can have multiple assets-sections, `assets` is a default one. It contains a list if template files which will be processed by twig and placed at a specific location. You'll have all variables available as twig-variables inside the template, to use them, just use `{{ theNameOfVariable }}` e.g. `{{ name }}` +To add a new asset-section, just use a new root-level key (in the above example this would be `deploymentModuleAssets` + +The assets-paths must be relative to the yaml-file containing the scaffold-commands. + +## the internal command `copy_assets` + +`copy_assets` can be used in the scaffold-section to copy assets into a specific location. The syntax is + +``` +copyAssets(, ) +``` + +Phabalicious will load the asset-file, apply the replacement-patterns to the file-name (see the deploymentAssets for an example) and parse the content via twig. The result will bee stored inside the `` + +## Inheritance + +Similar to other parts of Phabalicious, scaffold-files can use inheritance, for example to use the above scaffold-file, but install drupal commerce: + +```yaml +inheritsFrom: + - drupal-8.yml + - +variables: + composerProject: drupalcommerce/project-base +``` + +This will inherit all content from the drupal-8.yml-file and merged with this content. This means, the `composerProject´-variable will be overridden, but everything else will be inherited. This makes it easy to reuse existing scaffold-files + +## Examples + +### Drupal 8 (d8.yml) + +```yaml +variables: + composerProject: drupal-composer/drupal-project:8.x-dev + webRoot: web +assets: + - .fabfile.yaml + - docker-compose.yml + - docker-compose-mbb.yml + +deployModuleAssets: + - deployModule/%shortName%_deploy.info.yml + - deployModule/%shortName%_deploy.module + - deployModule/%shortName%_deploy.install + +sshKeys: + - ssh-keys/docker-root-key + - ssh-keys/docker-root-key.pub + - ssh-keys/known_hosts + +scaffold: + - rm -rf %rootFolder% + - composer create-project %composerProject% %rootFolder% --stability dev --no-interaction + - cd %rootFolder%; composer require drupal/coffee + - cd %rootFolder%; composer require drupal/devel + - copy_assets(%rootFolder%) + - copy_assets(%rootFolder%/%webRoot%/modules/custom/%shortName%_deploy, deployModuleAssets) + - copy_assets(%rootFolder%/ssh-keys, sshKeys) + - cd %rootFolder%; git init . + - cd %rootFolder%; git add . + - cd %rootFolder%; git commit -m "Initial commit by phabalicious" +``` + +### drupal commerce + +```yaml +inheritsFrom: + - d8.yml + +variables: + composerProject: drupalcommerce/project-base +``` + +### thunder + +```yaml +inheritsFrom: + - d8.yml + +variables: + composerProject: burdamagazinorg/thunder-project + webRoot: docroot +``` + +### Laravel + +#### the scaffold-file: +```yaml +variables: + composerProject: laravel/laravel:5.4 + webRoot: public + +assets: + - .fabfile.yaml + - docker-compose.yml + - docker-compose-mbb.yml + +scaffold: + - rm -rf %rootFolder% + - composer create-project %composerProject% %rootFolder% --stability dev --no-interaction + - cd %rootFolder%; composer require factorial-io/fabalicious:dev-develop + - copy_assets(%rootFolder%) + - cd %rootFolder%; git init . + - cd %rootFolder%; git add . + - cd %rootFolder%; git commit -m "Initial commit by phabalicious" +``` + +#### the fabfile-template +```yaml +name: {{ name }} +key: {{ shortName }} +deploymentModule: {{ shortName }}_deploy + +requires: 2.0.0 + +needs: + - ssh + - composer + - docker + - git + - files + +excludeFiles: + backup: + - "styles" + - "tmp" + copyFrom: + - "tmp" + - "styles" + - "php" + - "js" + - "css" + +scripts: + +dockerHosts: + mbb: + environment: + COMPOSE_FILE: 'docker-compose.yml:docker-compose-mbb.yml' + inheritsFrom: + - https://config.factorial.io/mbb/2.0/mbb-docker.yaml + - https://config.factorial.io/docker/2.0/docker-compose.yaml + + clients.factorial.io: + environment: + COMPOSE_HTTP_TIMEOUT: "180" + VHOST: "%host.docker.vhost%" + inheritsFrom: + - https://config.factorial.io/clients.factorial.io/2.0/d8/docker.yaml + +hosts: + mbb: + host: {{ projectFolder }}.test + user: root + password: root + port: {{ 1024 + random(20000) }} + type: dev + rootFolder: /var/www/{{ webRoot }} + gitRootFolder: /var/www + siteFolder: /sites/default + filesFolder: /sites/default/files + backupFolder: /var/www/backups + branch: develop + supportsInstalls: true + docker: + name: {{ projectFolder }}_web_1 + service: web + configuration: mbb + projectFolder: {{ projectFolder }} + database: + name: {{ projectFolder|replace({'-': '_'}) }}_db + user: root + pass: admin + host: mysql + ``` + \ No newline at end of file diff --git a/docs/docs/available-tasks.md b/docs/docs/available-tasks.md index cce792f8..a4cc4d36 100644 --- a/docs/docs/available-tasks.md +++ b/docs/docs/available-tasks.md @@ -1,3 +1,7 @@ +## -v/ -vv/ -vvv/ -vvvv + +Setting this option will increase the verbosity of phabalicious. Without this settings you'll get only warnings and errors and some informational stuff. If you encounter a problem try increasing the verbosity-level. + ## --config ```shell @@ -506,6 +510,17 @@ This task will run a command to forward a local port to a remote port. It starts * `phab --config=mbb start-remote-access` will forward `localhost:8888` to port `80` of the docker-container * `phab --config=mbb start-remote-access --port=3306 --publicPort=33060` will forward `localhost:33060`to port `3306` +## notify + +```shell +phab --config= notify +``` + +This command will send the notification to Mattermosts channel . For a detailed description have a look into the dedicated documentation. + +**Examples** +* `phab config:mbb notify "hello world" "off-topic": sends `hello world` to `#off-topic` + ## app:scaffold ```shell diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 4eed57a7..53bf119c 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -18,6 +18,7 @@ pages: - configuration.md - docker-integration.md - local-overrides.md + - app-scaffold.md - contribute.md - Changelog.md extra_css: From 24451debcaa88ef9d12e12af6a2523ec29e907aa Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 3 Dec 2018 00:32:14 +0100 Subject: [PATCH 31/74] Fix docs --- docs/docs/app-scaffold.md | 43 ++++----------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/docs/docs/app-scaffold.md b/docs/docs/app-scaffold.md index 1db48e4a..5b29a264 100644 --- a/docs/docs/app-scaffold.md +++ b/docs/docs/app-scaffold.md @@ -36,12 +36,13 @@ The fabfile needs at least the `scaffold`-section. The `scaffold`-section is a l ## The `scaffold`-section Phabalicious will provide the following replacement-patterns out of the box: -||Pattern||Value|| +|Pattern|Value| +|--------|-------| |%rootFolder%|The folder the app will be installed into| |%name%|The name of the app| |%projectFolder%|a cleaned version of the app-name, suitable for machine-names.| |%shortName%|The short-name| -|%uuid|a random-uuid| +|%uuid%|a random-uuid| ## the `variables`-section You can add own variables via the `variables`-section. In the above example, the variable `composerProject` will be available in the `scaffold`-section via the pattern `%composerProject%` @@ -157,6 +158,7 @@ scaffold: ``` #### the fabfile-template + ```yaml name: {{ name }} key: {{ shortName }} @@ -171,53 +173,16 @@ needs: - git - files -excludeFiles: - backup: - - "styles" - - "tmp" - copyFrom: - - "tmp" - - "styles" - - "php" - - "js" - - "css" - -scripts: - -dockerHosts: - mbb: - environment: - COMPOSE_FILE: 'docker-compose.yml:docker-compose-mbb.yml' - inheritsFrom: - - https://config.factorial.io/mbb/2.0/mbb-docker.yaml - - https://config.factorial.io/docker/2.0/docker-compose.yaml - - clients.factorial.io: - environment: - COMPOSE_HTTP_TIMEOUT: "180" - VHOST: "%host.docker.vhost%" - inheritsFrom: - - https://config.factorial.io/clients.factorial.io/2.0/d8/docker.yaml - hosts: mbb: host: {{ projectFolder }}.test user: root - password: root port: {{ 1024 + random(20000) }} type: dev rootFolder: /var/www/{{ webRoot }} gitRootFolder: /var/www - siteFolder: /sites/default - filesFolder: /sites/default/files backupFolder: /var/www/backups branch: develop - supportsInstalls: true - docker: - name: {{ projectFolder }}_web_1 - service: web - configuration: mbb - projectFolder: {{ projectFolder }} database: name: {{ projectFolder|replace({'-': '_'}) }}_db user: root From bbcf420ee638b0881cfce8b9e1e744d792e3f1e4 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 3 Dec 2018 00:33:41 +0100 Subject: [PATCH 32/74] FIx docs --- docs/docs/app-scaffold.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/app-scaffold.md b/docs/docs/app-scaffold.md index 5b29a264..38fe6cd6 100644 --- a/docs/docs/app-scaffold.md +++ b/docs/docs/app-scaffold.md @@ -188,5 +188,5 @@ hosts: user: root pass: admin host: mysql - ``` +``` \ No newline at end of file From 66f4d815b54ea481f30904c44b140fefc5cfe46c Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 3 Dec 2018 00:40:42 +0100 Subject: [PATCH 33/74] Move scripts-documentation into separate file --- docs/docs/configuration.md | 91 -------------------------------------- docs/docs/scripts.md | 91 ++++++++++++++++++++++++++++++++++++++ docs/mkdocs.yml | 1 + 3 files changed, 92 insertions(+), 91 deletions(-) create mode 100644 docs/docs/scripts.md diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md index 44eb06ee..f1f83c0c 100644 --- a/docs/docs/configuration.md +++ b/docs/docs/configuration.md @@ -377,94 +377,3 @@ inheritsFrom: -# Scripts - -Scripts are a powerful concept of phabalicious. There are a lot of places where scripts can be called. The `common`-section defines common scripts to be run for specific task/installation-type-configurations, docker-tasks are also scripts which you can execute via the docker-command. And you can even script phabalicious tasks and create meta-tasks. - -A script is basically a list of commands which get executed via shell on a remote machine. To stay independent of the host where the script is executed, phabalicious parsed the script before executing it and replaces given variables with their counterpart in the yams file. - -## Replacement-patterns - -Replacement-Patterns are specific strings enclosed in `%`s, e.g. `%host.port%`, `%dockerHost.rootFolder%` or `%arguments.name%`. - -Here's a simple example; - -```yaml -script: - test: - - echo "I am running on %host.config_name%" -``` - -Calling this script via - -```shell -phab config:mbb script:test -``` - -will show `I am running on mbb`. - -* The host-configuration gets exposes via the `host.`-prefix, so `port` maps to `%host.port%`, etc. -* The dockerHost-configuration gets exposed via the `dockerHost`-prefix, so `rootFolder` maps to `%dockerHost.rootFolder%` -* The global configuration of the yams-file gets exposed to the `settings`-prefix, so `uuid` gets mapped to `%settings.uuid% -* Optional arguments to the `script`-taks get the `argument`-prefix, e.g. `%arguments.name%`. You can get all arguments via `%arguments.combined%`. -* You can access hierarchical information via the dot-operator, e.g. `%host.database.name%` - -If phabalicious detects a pattern it can't replace it will abort the execution of the script and displays a list of available replacement-patterns. - -## Internal commands - -There are currently 3 internal commands. These commands control the flow inside phabalicious: - -* `fail_on_error(1|0)` If fail_on_error is set to one, phabalicious will exit if one of the script commands returns a non-zero return-code. When using `fail_on_error(0)` only a warning is displayed, the script will continue. -* `execute(task, subtask, arguments)` execute a phabalicious task. For example you can run a deployment from a script via `execute(deploy)` or stop a docker-container from a script via `execute(docker, stop)` -* `fail_on_missing_directory(directory, message)` will print message `message` if the directory `directory` does not exist. - -## Task-related scripts - -You can add scripts to the `common`-section, which will called for any host. You can differentiate by task-name and host-type, e.g. create a script which gets called for the task `deploy` and type `dev`. - -You can even run scripts before or after a task is executed. Append the task with `Prepare` or `Finished`. - -You can even run scripts for specific tasks and hosts. Just add your script with the task-name as its key. - -```yaml -host: - test: - deployPrepare: - - echo "Preparing deploy for test" - deploy: - - echo "Deploying on test" - deployFinished: - - echo "Deployment finished for test" -``` - -These scripts in the above examples gets executed only for the host `test` and task `deploy`. - -## Examples - -A rather complex example scripting phabalicious. - -```yaml -scripts: - runTests: - defaults: - branch: develop - script: - - execute(docker, start) - - execute(docker, waitForServices) - - execute(deploy, %arguments.branch%) - - execute(script, behatInstall) - - execute(script, behat, --profile=ci --format=junit --format=progress) - - execute(getFile, /var/www/_tools/behat/build/behat/default.xml, ./_tools/behat) - - execute(docker, stop) -``` - -This script will - -* start the docker-container, -* wait for it, -* deploys the given branch, -* run a script which will install behat, -* run behat with some custom arguments, -* gets the result-file and copy it to a location, -* and finally stops the container. diff --git a/docs/docs/scripts.md b/docs/docs/scripts.md new file mode 100644 index 00000000..d91454c3 --- /dev/null +++ b/docs/docs/scripts.md @@ -0,0 +1,91 @@ +# Scripts + +Scripts are a powerful concept of phabalicious. There are a lot of places where scripts can be called. The `common`-section defines common scripts to be run for specific task/installation-type-configurations, docker-tasks are also scripts which you can execute via the docker-command. And you can even script phabalicious tasks and create meta-tasks. And you can add custom scripts to the general section of a fabfile or to a host-configuration. Scripts can call other scripts. + +A script is basically a list of commands which get executed via shell on a local or remote machine. To stay independent of the host where the script is executed, phabalicious parses the script before executing it and replaces given variables with their counterpart in the yaml file. + +## Replacement-patterns + +Replacement-Patterns are specific strings enclosed in `%`s, e.g. `%host.port%`, `%dockerHost.rootFolder%` or `%arguments.name%`. + +Here's a simple example; + +```yaml +script: + test: + - echo "I am running on %host.config_name%" +``` + +Calling this script via + +```shell +phab config:mbb script:test +``` + +will show `I am running on mbb`. + +* The host-configuration gets exposes via the `host.`-prefix, so `port` maps to `%host.port%`, etc. +* The dockerHost-configuration gets exposed via the `dockerHost`-prefix, so `rootFolder` maps to `%dockerHost.rootFolder%` +* The global configuration of the yams-file gets exposed to the `settings`-prefix, so `uuid` gets mapped to `%settings.uuid% +* Optional arguments to the `script`-taks get the `argument`-prefix, e.g. `%arguments.name%`. You can get all arguments via `%arguments.combined%`. +* You can access hierarchical information via the dot-operator, e.g. `%host.database.name%` + +If phabalicious detects a pattern it can't replace it will abort the execution of the script and displays a list of available replacement-patterns. + +## Internal commands + +There are currently 3 internal commands. These commands control the flow inside phabalicious: + +* `fail_on_error(1|0)` If fail_on_error is set to one, phabalicious will exit if one of the script commands returns a non-zero return-code. When using `fail_on_error(0)` only a warning is displayed, the script will continue. +* `execute(task, subtask, arguments)` execute a phabalicious task. For example you can run a deployment from a script via `execute(deploy)` or stop a docker-container from a script via `execute(docker, stop)` +* `fail_on_missing_directory(directory, message)` will print message `message` if the directory `directory` does not exist. + +## Task-related scripts + +You can add scripts to the `common`-section, which will called for any host. You can differentiate by task-name and host-type, e.g. create a script which gets called for the task `deploy` and type `dev`. + +You can even run scripts before or after a task is executed. Append the task with `Prepare` or `Finished`. + +You can even run scripts for specific tasks and hosts. Just add your script with the task-name as its key. + +```yaml +host: + test: + deployPrepare: + - echo "Preparing deploy for test" + deploy: + - echo "Deploying on test" + deployFinished: + - echo "Deployment finished for test" +``` + +These scripts in the above examples gets executed only for the host `test` and task `deploy`. + +## Examples + +A rather complex example scripting phabalicious. + +```yaml +scripts: + runTests: + defaults: + branch: develop + script: + - execute(docker, start) + - execute(docker, waitForServices) + - execute(deploy, %arguments.branch%) + - execute(script, behatInstall) + - execute(script, behat, --profile=ci --format=junit --format=progress) + - execute(getFile, /var/www/_tools/behat/build/behat/default.xml, ./_tools/behat) + - execute(docker, stop) +``` + +This script will + +* start the docker-container, +* wait for it, +* deploys the given branch, +* run a script which will install behat, +* run behat with some custom arguments, +* gets the result-file and copy it to a location, +* and finally stops the container. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 53bf119c..e796c27f 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -18,6 +18,7 @@ pages: - configuration.md - docker-integration.md - local-overrides.md + - scripts.md - app-scaffold.md - contribute.md - Changelog.md From 62cc04c10941257bb177fb7533698e1f39ea01ea Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 3 Dec 2018 17:50:02 +0100 Subject: [PATCH 34/74] Change order of folder creation --- src/Command/AppScaffoldCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Command/AppScaffoldCommand.php b/src/Command/AppScaffoldCommand.php index 6a71d745..9542abb1 100644 --- a/src/Command/AppScaffoldCommand.php +++ b/src/Command/AppScaffoldCommand.php @@ -171,7 +171,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->twig = new \Twig_Environment($loader, array( )); - $shell->run(sprintf('mkdir -p %s', $tokens['rootFolder'])); if (empty($input->getOption('override')) && is_dir($tokens['rootFolder'])) { $question = new ConfirmationQuestion('Target-folder exists! Continue anyways? ', false); @@ -180,6 +179,8 @@ protected function execute(InputInterface $input, OutputInterface $output) } } + $shell->run(sprintf('mkdir -p %s', $tokens['rootFolder'])); + $script->runScript($host_config, $context); return 0; } From 2acbd137ae11cb1c2939728cedeb753997059b88 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 3 Dec 2018 17:58:35 +0100 Subject: [PATCH 35/74] Better folder handling in app:scaffold --- src/Command/AppScaffoldCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Command/AppScaffoldCommand.php b/src/Command/AppScaffoldCommand.php index 9542abb1..2e685529 100644 --- a/src/Command/AppScaffoldCommand.php +++ b/src/Command/AppScaffoldCommand.php @@ -128,7 +128,7 @@ protected function execute(InputInterface $input, OutputInterface $output) 'name' => trim($name), 'shortName' => trim(strtolower($short_name)), 'projectFolder' => Utilities::cleanupString($name), - 'rootFolder' => $input->getOption('output') . '/' . Utilities::cleanupString($name), + 'rootFolder' => realpath($input->getOption('output') . '/' . Utilities::cleanupString($name)), 'uuid' => $this->fakeUUID(), ]; @@ -153,7 +153,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $script = new ScriptMethod($logger); $host_config = new HostConfig([ - 'rootFolder' => $input->getOption('output'), + 'rootFolder' => realpath($input->getOption('output')), 'shellExecutable' => '/bin/bash' ], $shell); $context = new TaskContext($this, $input, $output); From 5d2a80de00517aa5b9dd96781fe09308f6ac5b5b Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 4 Dec 2018 17:52:02 +0100 Subject: [PATCH 36/74] Call host- and task-specific scripts (fixes #4) --- src/Method/ScriptMethod.php | 20 +++++++++++++++++--- tests/DrushMethodTest.php | 1 - tests/ScriptMethodTest.php | 10 ++++++---- tests/assets/script-tests/fabfile.yaml | 8 +++++++- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/Method/ScriptMethod.php b/src/Method/ScriptMethod.php index e7ab6220..fe86ddc1 100644 --- a/src/Method/ScriptMethod.php +++ b/src/Method/ScriptMethod.php @@ -98,7 +98,6 @@ public function runScript(HostConfig $host_config, TaskContextInterface $context ); $context->setResult('exitCode', $result ? $result->getExitCode() : 0); - } catch (UnknownReplacementPatternException $e) { $context->getOutput() ->writeln('Unknown replacement in line ' . $e->getOffendingLine() . ''); @@ -296,7 +295,22 @@ public function runTaskSpecificScripts(HostConfig $config, string $task, TaskCon if (!empty($common_scripts[$task][$type])) { $script = $common_scripts[$task][$type]; - $this->logger->info('Running common script for task `' . $task . '` and type `' . $type . '`'); + $this->logger->info(sprintf( + 'Running common script for task `%s` and type `%s`', + $task, + $type + )); + $context->set('scriptData', $script); + $this->runScript($config, $context); + } + + if (!empty($config[$task])) { + $script = $config[$task]; + $this->logger->info(sprintf( + 'Running host-specific script for task `%s` and host `%s`', + $task, + $config['configName'] + )); $context->set('scriptData', $script); $this->runScript($config, $context); } @@ -343,4 +357,4 @@ public function postflightTask(string $task, HostConfig $config, TaskContextInte parent::postflightTask($task, $config, $context); $this->runTaskSpecificScripts($config, $task . 'Finished', $context); } -} \ No newline at end of file +} diff --git a/tests/DrushMethodTest.php b/tests/DrushMethodTest.php index ae1f68ed..f738e96c 100644 --- a/tests/DrushMethodTest.php +++ b/tests/DrushMethodTest.php @@ -27,7 +27,6 @@ public function setup() $method_factory->addMethod($this->method); $this->configurationService->readConfiguration(getcwd() . '/assets/drush-tests/fabfile.yaml'); - } public function testGetDefaultConfig() diff --git a/tests/ScriptMethodTest.php b/tests/ScriptMethodTest.php index 6bec760c..4fbe6a83 100644 --- a/tests/ScriptMethodTest.php +++ b/tests/ScriptMethodTest.php @@ -56,7 +56,8 @@ public function setUp() $this->context = new TaskContext( $this->getMockBuilder(BaseCommand::class)->disableOriginalConstructor()->getMock(), $this->getMockBuilder(InputInterface::class)->getMock(), - $this->getMockBuilder(OutputInterface::class)->getMock()); + $this->getMockBuilder(OutputInterface::class)->getMock() + ); $this->context->setConfigurationService($this->configurationService); } @@ -228,10 +229,12 @@ public function testTaskSpecificScripts() $this->assertEquals([ 'deployPrepare on dev', + 'deployPrepare on hostA', 'deploy on dev', - 'deployFinished on dev' + 'deploy on hostA', + 'deployFinished on dev', + 'deployFinished on hostA' ], $this->context->get('debug')); - } public function scriptDebugCallback(TaskContextInterface $context, $message) @@ -243,5 +246,4 @@ public function scriptDebugCallback(TaskContextInterface $context, $message) $debug[] = $message; $context->set('debug', $debug); } - } diff --git a/tests/assets/script-tests/fabfile.yaml b/tests/assets/script-tests/fabfile.yaml index 520b1ebc..adad782a 100644 --- a/tests/assets/script-tests/fabfile.yaml +++ b/tests/assets/script-tests/fabfile.yaml @@ -31,4 +31,10 @@ hosts: scripts: test: - echo "Hello" - - echo "World" \ No newline at end of file + - echo "World" + deployPrepare: + - debug(deployPrepare on hostA) + deploy: + - debug(deploy on hostA) + deployFinished: + - debug(deployFinished on hostA) \ No newline at end of file From 2b95d439311ad85ec022ef83207bd4381283d525 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 4 Dec 2018 17:58:08 +0100 Subject: [PATCH 37/74] Update index.md --- docs/docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/index.md b/docs/docs/index.md index a1f018ee..e7c64e8a 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -1,6 +1,6 @@ # How does phabalicious work in two sentences -Phabalicious is using configuration stored in a special file in the root of your project (the `fabfile.yaml`) to run tasks in a shell. This shell can be provided by a docker-container, a ssh-connection or a local shell. This means, you can store all your devops-configuration in the fabfile and apply it to a list of configurations. Phabalicious tries to abstract away the inner workings of a host and give the user a handful useful commands to run common tasks, like: +Phabalicious is using configuration stored in a special file in the root of your project (the `fabfile.yaml`) to run tasks in a shell. This shell can be provided by a docker-container, a ssh-connection or a local shell. This means, you can store all your devops-scripts in the fabfile and apply it to a list of configurations. Phabalicious tries to abstract away the inner workings of a host and give the user a handful useful commands to run common tasks, like: * deploying new code to a remote installation * reset a remote installation to its defaults. From de36435769766450d4b6e20ace319ad8faf45f91 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 4 Dec 2018 18:00:05 +0100 Subject: [PATCH 38/74] Bump version number --- bin/phab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/phab b/bin/phab index 176ec14c..0aec7a00 100755 --- a/bin/phab +++ b/bin/phab @@ -45,7 +45,7 @@ $output = $container->get(ConsoleOutput::class); /** @var Application $application */ $application = $container->get(Application::class); -$application->setVersion('3.0.0-alpha.2'); +$application->setVersion('3.0.0-alpha.3'); $application->setName('phabalicious'); $application->setDefaultCommand('list'); From cbdcc768d46ba21c1547653c66027ccbf115d1cd Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 4 Dec 2018 20:03:03 +0100 Subject: [PATCH 39/74] Add docker documentation --- docs/docs/docker-integration.md | 123 +++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/docs/docs/docker-integration.md b/docs/docs/docker-integration.md index cb769773..d7459b96 100644 --- a/docs/docs/docker-integration.md +++ b/docs/docs/docker-integration.md @@ -1,3 +1,124 @@ # Docker integration -TODO \ No newline at end of file +The docker-integration is quite simple, but very powerful. In a fabfile, there are host-configuration under the key `hosts` and docker-configs under the key `dockerHosts`. A `host` can reference a docker-configuration, multiple hosts can use one docker-config. + +## A docker-configuration + +A docker configuration must contain these keys: + +* `rootFolder` the rootFolder, where the projectFolder can be found +* `shellProvider`: `local` or `ssh`; in which shell the tasks-commands should be run. The shell-provider might require more information e.g. `user`, `host` and `port`. +* `tasks`: a keyed list of scripts to use. The key is the name of the script, which you can trigger via the `docker command` +* `environment`: a key-value list of environment-variables to set before running a docker-command. This helps to modularize docker-compose-files, for example. + +The tasks can use the pattern-replacement used in other parts of phabalicious to get data from the docker-config or from the host-config into the tasks. Here's a small example: + +```yaml +tasks: + run: + - echo "running container %host.docker.name% for config %host.configName% in %dockerHost.rootFolder% +``` + +If you want to use some host-config, use `host.` as a prefix, if you want to use sth from the docker-config, use `dockerHost.` as prefix. + +## the docker-specific host-configuration + +All docker-configuration is stored inside the `docker`-group. It has only 2 required keys: + + * `configuration` this links to a key under `dockerHosts` + * `projectFolder` the folder, where this project is stored in relation to the `rootFolder` + * `name` or `service`. Some commands need to know with which container you want to interact. Provide the name of the docker-container via the `name`-property, if you are using docker-compose you can set the `service` accordingly, then phabalicious will try to compute the docker-name automatically. + +You can add as many data to the yams file and reference it via the replacement-mechanism described earlier. + +## A simple example: + +```yaml +dockerHosts: + test: + rootFolder: /root/folder + shellProvider: local + environment: + VHOST: %host.configName%.test + tasks: + run: + - echo "docker run" + build: + - echo "docker build" + all: + - echo "current config: %host.configName%" + - execute(docker, build) + - execute(docker, run) + +hosts: + testHostA: + ... + docker: + configuration: test + projectFolder: test-host-a + name: testhosta +``` + +This snippet will expose 3 docker-commands for the host `testHostA`, you can execute them via + +```shell +phab --config=testHostA docker run|build|all +``` + +The output for `phab -ctestHostA docker all` will be: + +``` +current config: testHostA +docker build +docker run +``` + +The inheritance mechanism allows you to store the docker-config in a central location and reuse it in your fabfile: + +```yaml +dockerHosts: + testB: + rootFolder: /some/other/folder + inheritsFrom: + - https://some.host/docker.yml + - https://some.host/docker-compose.yml +``` + +## Built-in docker commands + +There are two commands builtin, because they are hard to implement in a script-only version: + + * waitForServices + * copySSHKeysToDocker + +### waitForServices + +This will try to run `supervisorctl status` every 10 seconds, and wait until all services are up and running. If you want to disable this command, set the executable to false with + +```yaml +executables: + supervisorctl: false +``` + +### copySSHKeysToDocker + +This command will copy the referenced files from your local computer into the docker container and set the permissions so ssh can use the copied data. + +These are the needed global settings in the fabfile: + +* `dockerKeyFile` will copy the referenced private key and its public key into the container +* `dockerAuthorizedKeyFile`, the `authorized_keys`-file, can be a path to a file or an url +* `dockerKnownHostsFile`, the `known_hosts`-file + +Obviously a ssh-demon should be running inside your docker-container. + +## Predefined docker-tasks + +Phabalicious is running some predefined docker-tasks if set in the fabfile and when using the commands `app:create` or `app:destroy` + +* `spinUp`: get all needed container running +* `spinDown`: stop all app-containers +* `deleteContainer`: remove and delete all app container + +If you want to support this in your configuration, add the tasks to the fabfile and its corresponding commands. + From 2afa66d5e9d15aa803e5ea5a4724dcbb08c17a22 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 4 Dec 2018 20:10:12 +0100 Subject: [PATCH 40/74] Update docker docs --- docs/docs/docker-integration.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/docker-integration.md b/docs/docs/docker-integration.md index d7459b96..fd1a1b35 100644 --- a/docs/docs/docker-integration.md +++ b/docs/docs/docker-integration.md @@ -84,6 +84,7 @@ dockerHosts: - https://some.host/docker-compose.yml ``` + ## Built-in docker commands There are two commands builtin, because they are hard to implement in a script-only version: @@ -122,3 +123,6 @@ Phabalicious is running some predefined docker-tasks if set in the fabfile and w If you want to support this in your configuration, add the tasks to the fabfile and its corresponding commands. +## Conclusion + +As you can see, there's not much docker-specific besides the naming. So in theory you can control something else like `rancher` or maybe even `kubectl`. All you have is the referencing between a host and a dockerHost and the possibility to run tasks locally or via SSH on a remote instance, and pass data from the host-config or docker-config to your scripts. \ No newline at end of file From 5c141b5fec24c14c7ba44d87489eccf0f1c19df3 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 16:01:13 +0100 Subject: [PATCH 41/74] Add more config --- docs/docs/app-create-delete.md | 58 ++++++++++++++++++++++++++++++++++ docs/docs/available-tasks.md | 6 ++-- 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 docs/docs/app-create-delete.md diff --git a/docs/docs/app-create-delete.md b/docs/docs/app-create-delete.md new file mode 100644 index 00000000..e02a10e3 --- /dev/null +++ b/docs/docs/app-create-delete.md @@ -0,0 +1,58 @@ +# Creating/ destroying an app from existing configuration + +Phabalicious can create or delete a complete app with two commands: + + * `phab --config= app:create --copy-from=` + * `phab --config= app:destroy` + +Both commands executes a list of stages, which can be influenced via configuration + +## the standard stages + +These are the standard stages. You can override them by adding them to the global section of your fabfile: + +```yaml +appStages: + create: + - stage: installCode + - stage: spinUp + - stage: installDependencies + - stage: install + deploy: + - stage: spinUp + destroy: + - stage: spinDown + - stage: deleteContainers +``` + +## Creating a new app + +Run the phab-command as usual. If you want to copy from an existing installation, add the `--copy-from`-option. + +```shell +phab --config= app:create +``` + +If the app is already created (there's an existing `.projectCreated`-file in the root of the installation), only the `deploy`-stage will be executed, and afterwards the deploy-task will be executed. + +If the app is not created yet, all `create`-stages will be executed. If nothing went wrong you should have a running installation of the given configuration + +## Destroying an app + +```shell +phab --config= app:destroy +``` + +This will execute all `destroy`-stages and delete the project-folder afterwards. + +## Blueprints + +Both commands work best when using blueprints. This will allow to create a config and an app from a single string like a name of a feature. + +Some examples: + +```shell +phab --config=some-config --blueprint=feature/ create:app +``` + +Will create a new app from a blueprinted config. \ No newline at end of file diff --git a/docs/docs/available-tasks.md b/docs/docs/available-tasks.md index a4cc4d36..cad2578c 100644 --- a/docs/docs/available-tasks.md +++ b/docs/docs/available-tasks.md @@ -537,12 +537,14 @@ This command will scaffold a new project from a set of scaffold-files. See the d ## app:create ```shell -phab --config= app:create +phab --config= app:create --config-from= ``` This command will create a new app instance from a given config. Most useful with the usage of blueprints. -The creation is done in several steps which can be customized. For a deeper explanation please have a look into the dedicated documentation +The creation is done in several steps which can be customized. If you apply the `--config-from`-option an additional copyFrom is done afterwards. + +For a deeper explanation please have a look into the dedicated documentation ## app:update From 68c095c34421342eb7119818e89df9262d58f349 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 16:08:42 +0100 Subject: [PATCH 42/74] Update docs --- docs/docs/app-create-destroy.md | 58 +++++++++++++++++++++++++++++++++ docs/mkdocs.yml | 3 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 docs/docs/app-create-destroy.md diff --git a/docs/docs/app-create-destroy.md b/docs/docs/app-create-destroy.md new file mode 100644 index 00000000..e02a10e3 --- /dev/null +++ b/docs/docs/app-create-destroy.md @@ -0,0 +1,58 @@ +# Creating/ destroying an app from existing configuration + +Phabalicious can create or delete a complete app with two commands: + + * `phab --config= app:create --copy-from=` + * `phab --config= app:destroy` + +Both commands executes a list of stages, which can be influenced via configuration + +## the standard stages + +These are the standard stages. You can override them by adding them to the global section of your fabfile: + +```yaml +appStages: + create: + - stage: installCode + - stage: spinUp + - stage: installDependencies + - stage: install + deploy: + - stage: spinUp + destroy: + - stage: spinDown + - stage: deleteContainers +``` + +## Creating a new app + +Run the phab-command as usual. If you want to copy from an existing installation, add the `--copy-from`-option. + +```shell +phab --config= app:create +``` + +If the app is already created (there's an existing `.projectCreated`-file in the root of the installation), only the `deploy`-stage will be executed, and afterwards the deploy-task will be executed. + +If the app is not created yet, all `create`-stages will be executed. If nothing went wrong you should have a running installation of the given configuration + +## Destroying an app + +```shell +phab --config= app:destroy +``` + +This will execute all `destroy`-stages and delete the project-folder afterwards. + +## Blueprints + +Both commands work best when using blueprints. This will allow to create a config and an app from a single string like a name of a feature. + +Some examples: + +```shell +phab --config=some-config --blueprint=feature/ create:app +``` + +Will create a new app from a blueprinted config. \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e796c27f..3ad33233 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -10,7 +10,7 @@ site_description: Phabalicious Documentation site_author: Factorial GmbH, Hamburg copyright: © 2018 Factorial GmbH, Hamburg -pages: +nav: - index.md - installation.md - usage.md @@ -20,6 +20,7 @@ pages: - local-overrides.md - scripts.md - app-scaffold.md + - app-create-destroy.md - contribute.md - Changelog.md extra_css: From 5788e06466e0621abc21a5075ec0bfbaafb2ae57 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 19:17:26 +0100 Subject: [PATCH 43/74] REfactor AppCreation and -destruction, start working on ftp-sync method --- src/Command/AppBaseCommand.php | 14 ++-- src/Command/AppCreateCommand.php | 22 +----- src/Command/AppDestroyCommand.php | 10 +-- src/Method/FtpSyncMethod.php | 109 +++++++++++++++++++++++++++++ src/Method/GitMethod.php | 4 ++ src/Method/MethodFactory.php | 3 + src/Utilities/AppDefaultStages.php | 74 ++++++++++++++++++++ src/Utilities/Utilities.php | 2 - 8 files changed, 204 insertions(+), 34 deletions(-) create mode 100644 src/Method/FtpSyncMethod.php create mode 100644 src/Utilities/AppDefaultStages.php diff --git a/src/Command/AppBaseCommand.php b/src/Command/AppBaseCommand.php index 0995c9bc..2bf6a44e 100644 --- a/src/Command/AppBaseCommand.php +++ b/src/Command/AppBaseCommand.php @@ -5,6 +5,7 @@ use Phabalicious\Exception\EarlyTaskExitException; use Phabalicious\Method\TaskContext; use Phabalicious\Method\TaskContextInterface; +use Phabalicious\Utilities\AppDefaultStages; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -21,11 +22,14 @@ abstract class AppBaseCommand extends BaseCommand */ protected function executeStages(array $stages, string $command, TaskContextInterface $context, string $message) { - foreach ($stages as $stage) { - $context->getOutput()->writeln(sprintf('%s, stage %s', $message, $stage['stage'])); - $context->set('currentStage', $stage); - $this->getMethods()->runTask($command, $this->getHostConfig(), $context); - } + AppDefaultStages::executeStages( + $this->getMethods(), + $this->getHostConfig(), + $stages, + $command, + $context, + $message + ); } diff --git a/src/Command/AppCreateCommand.php b/src/Command/AppCreateCommand.php index ded2b04b..07e0ba3e 100644 --- a/src/Command/AppCreateCommand.php +++ b/src/Command/AppCreateCommand.php @@ -5,6 +5,7 @@ use Phabalicious\Exception\EarlyTaskExitException; use Phabalicious\Method\TaskContext; use Phabalicious\ShellProvider\ShellProviderInterface; +use Phabalicious\Utilities\AppDefaultStages; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -75,31 +76,14 @@ protected function execute(InputInterface $input, OutputInterface $output) $stages = $this->configuration->getSetting( 'appStages.deploy', - [ - [ - 'stage' => 'spinUp', - ] - ] + AppDefaultStages::DEPLOY ); $this->executeStages($stages, 'appCreate', $context, 'Creating app'); $this->runCommand('deploy', [], $input, $output); } else { $stages = $this->configuration->getSetting( 'appStages.create', - [ - [ - 'stage' => 'installCode', - ], - [ - 'stage' => 'spinUp', - ], - [ - 'stage' => 'installDependencies', - ], - [ - 'stage' => 'install', - ], - ] + AppDefaultStages::CREATE ); $this->executeStages($stages, 'appCreate', $context, 'Creating app'); diff --git a/src/Command/AppDestroyCommand.php b/src/Command/AppDestroyCommand.php index 5df276f8..304616ff 100644 --- a/src/Command/AppDestroyCommand.php +++ b/src/Command/AppDestroyCommand.php @@ -5,6 +5,7 @@ use Phabalicious\Exception\EarlyTaskExitException; use Phabalicious\Method\TaskContext; use Phabalicious\ShellProvider\ShellProviderInterface; +use Phabalicious\Utilities\AppDefaultStages; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -60,14 +61,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($app_exists) { $stages = $this->configuration->getSetting( 'appStages.deploy', - [ - [ - 'stage' => 'spinDown', - ], - [ - 'stage' => 'deleteContainer', - ], - ] + AppDefaultStages::DESTROY ); $this->executeStages($stages, 'appDestroy', $context, 'Destroying app'); $outer_shell->run(sprintf('sudo rm -rf %s', $install_dir)); diff --git a/src/Method/FtpSyncMethod.php b/src/Method/FtpSyncMethod.php new file mode 100644 index 00000000..b7243d07 --- /dev/null +++ b/src/Method/FtpSyncMethod.php @@ -0,0 +1,109 @@ + 'filesFolder', + 'private' => 'privateFilesFolder' + ]; + + public function getName(): string + { + return 'ftp-sync'; + } + + public function supports(string $method_name): bool + { + return $method_name === $this->getName(); + } + + public function getDefaultConfig(ConfigurationService $configuration_service, array $host_config): array + { + $return = parent::getDefaultConfig($configuration_service, $host_config); + $return['tmpFolder'] = '/tmp'; + $return['executables'] = [ + 'lftp' => 'lftp', + ]; + + $return['deployMethod'] = 'ftp-sync'; + + return $return; + } + + public function validateConfig(array $config, ValidationErrorBagInterface $errors) + { + parent::validateConfig($config, $errors); // TODO: Change the autogenerated stub + if (in_array('drush', $config['needs'])) { + $errors->addError('needs', 'The method `ftp-sync` is incompatible with the `drush`-method!'); + } + if ($config['deployMethod'] !== 'ftp-sync') { + $errors->addError('deployMethod', 'deployMethod must be `ftp-sync`!'); + } + } + + /** + * @param HostConfig $host_config + * @param TaskContextInterface $context + * @throws \Phabalicious\Exception\MethodNotFoundException + * @throws \Phabalicious\Exception\TaskNotFoundInMethodException + */ + public function deploy(HostConfig $host_config, TaskContextInterface $context) + { + if ($host_config['deployMethod'] !== 'ftp-sync') { + return; + } + + // First, create an app in a temporary-folder. + $stages = $context->getConfigurationService()->getSetting( + 'appStages.createCode', + AppDefaultStages::CREATE_CODE + ); + $install_dir = $host_config['tmpFolder'] . '/' . $host_config['configName'] . '-' . time(); + $context->set('installDir', $install_dir); + $cloned_host_config = clone $host_config; + $keys = ['rootFolder', 'composerRootFolder', 'gitRootFolder']; + foreach ($keys as $key) { + $cloned_host_config[$key] = $install_dir; + } + $shell = $this->getShell($cloned_host_config, $context); + $shell->cd($cloned_host_config['tmpFolder']); + $context->set('outerShell', $shell); + + AppDefaultStages::executeStages( + $context->getConfigurationService()->getMethodFactory(), + $cloned_host_config, + $stages, + 'appCreate', + $context, + 'Creating code' + ); + + // Run deploy scripts + /** @var ScriptMethod $script_method */ + $script_method = $context->getConfigurationService()->getMethodFactory()->getMethod('script'); + $script_method->runTaskSpecificScripts($host_config, 'reset', $context); + + $context->setResult('skipResetStep', true); + + // Now we can sync the files via FTP. + // TODO + + // Cleanup. + $shell->run(sprintf('rm -rf %s', $install_dir)); + + // Do not run any next tasks. + $context->setResult('runNextTasks', []); + } + + +} diff --git a/src/Method/GitMethod.php b/src/Method/GitMethod.php index 4e979846..364e03ed 100644 --- a/src/Method/GitMethod.php +++ b/src/Method/GitMethod.php @@ -45,6 +45,7 @@ public function getDefaultConfig(ConfigurationService $configuration_service, ar 'gitRootFolder' => $host_config['rootFolder'], 'ignoreSubmodules' => false, 'gitOptions' => $configuration_service->getSetting('gitOptions', []), + 'deployMethod' => 'git', ]; } @@ -88,6 +89,9 @@ public function version(HostConfig $host_config, TaskContextInterface $context) */ public function deploy(HostConfig $host_config, TaskContextInterface $context) { + if ($host_config['deployMethod'] !== 'git') { + return ; + } $shell = $this->getShell($host_config, $context); $shell->cd($host_config['gitRootFolder']); if (!$this->isWorkingcopyClean($host_config, $context)) { diff --git a/src/Method/MethodFactory.php b/src/Method/MethodFactory.php index 3bbd845d..4d625ebd 100644 --- a/src/Method/MethodFactory.php +++ b/src/Method/MethodFactory.php @@ -94,9 +94,12 @@ public function runTask( TaskContextInterface $context = null, $nextTasks = [] ) { + $context->setResult('runNextTasks', $nextTasks); $this->preflight('preflight', $task_name, $configuration, $context); $this->runTaskImpl($task_name . 'Prepare', $configuration, $context, false); $this->runTaskImpl($task_name, $configuration, $context, true); + + $nextTasks = $context->getResult('runNextTasks', []); if (!empty($nextTasks)) { foreach ($nextTasks as $next_task_name) { $this->runTask($next_task_name, $configuration, $context); diff --git a/src/Utilities/AppDefaultStages.php b/src/Utilities/AppDefaultStages.php new file mode 100644 index 00000000..4cfec1a0 --- /dev/null +++ b/src/Utilities/AppDefaultStages.php @@ -0,0 +1,74 @@ + 'installCode', + ], + [ + 'stage' => 'spinUp', + ], + [ + 'stage' => 'installDependencies', + ], + [ + 'stage' => 'install', + ], + ]; + + const DEPLOY = [ + [ + 'stage' => 'spinUp', + ] + ]; + + const DESTROY = [ + [ + 'stage' => 'spinDown', + ], + [ + 'stage' => 'deleteContainer', + ], + ]; + + const CREATE_CODE = [ + [ + 'stage' => 'installCode', + ], + [ + 'stage' => 'installDependencies', + ], + ]; + + + /** + * @param MethodFactory $method_factory + * @param HostConfig $host_config + * @param array $stages + * @param string $command + * @param TaskContextInterface $context + * @param string $message + * @throws \Phabalicious\Exception\MethodNotFoundException + * @throws \Phabalicious\Exception\TaskNotFoundInMethodException + */ + public static function executeStages( + MethodFactory $method_factory, + HostConfig $host_config, + array $stages, + string $command, + TaskContextInterface $context, + string $message + ) { + foreach ($stages as $stage) { + $context->getOutput()->writeln(sprintf('%s, stage %s', $message, $stage['stage'])); + $context->set('currentStage', $stage); + $method_factory->runTask($command, $host_config, $context); + } + } +} diff --git a/src/Utilities/Utilities.php b/src/Utilities/Utilities.php index 39f4141c..ef997f89 100644 --- a/src/Utilities/Utilities.php +++ b/src/Utilities/Utilities.php @@ -2,8 +2,6 @@ namespace Phabalicious\Utilities; -use Wikimedia\Composer\Merge\NestedArray; - class Utilities { From 7a57e9c88dfe0eb72e4f141d09b72ad004151b7b Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 23:15:34 +0100 Subject: [PATCH 44/74] Finish FTP-deployment --- Changelog.md | 42 +++++++++++---- src/Method/FtpSyncMethod.php | 99 ++++++++++++++++++++++++++++++++---- src/Method/GitMethod.php | 12 +++-- 3 files changed, 129 insertions(+), 24 deletions(-) diff --git a/Changelog.md b/Changelog.md index cc5b4b60..7cba0680 100644 --- a/Changelog.md +++ b/Changelog.md @@ -55,19 +55,41 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav * new shell-provider `dockerExec` which will start a shell with the help of `docker exec` instead of ssh. * new config-option `shellProvider`, where you can override the shell-provider to your liking. - hosts: - mbb: - shellProvider: docker-exec + hosts: + mbb: + shellProvider: docker-exec * You can get help for a specific task via `phab help `. It will show all possible options and some help. * docker-compose version 23 changes the schema how names of docker-containers are constructed. To support this change we can now declare the needed service to compute the correct container-name from. - hosts: - testHost: - docker: - service: web - - The `name` will be discarded, if a `service`-entry is set. - + hosts: + testHost: + docker: + service: web + The `name` will be discarded, if a `service`-entry is set. + +* new method `ftp-sync`, it's a bit special. This method creates the app into a temporary folder, and syncs it via `lftp` to a remote instance. Here's a complete example: + + excludeFiles: + ftp-sync: + - .git/ + - node_modules + hosts: + ftpSyncSample: + needs: + - git + - ftp-sync + - local + ftp: + user: + password: + host: + port: 21 + lftpOptions: + - --ignoreTime + - --verbose=3 + - --no-perms + + ### Changed diff --git a/src/Method/FtpSyncMethod.php b/src/Method/FtpSyncMethod.php index b7243d07..4bff1059 100644 --- a/src/Method/FtpSyncMethod.php +++ b/src/Method/FtpSyncMethod.php @@ -8,6 +8,7 @@ use Phabalicious\ShellProvider\ShellProviderInterface; use Phabalicious\Utilities\AppDefaultStages; use Phabalicious\Validation\ValidationErrorBagInterface; +use Phabalicious\Validation\ValidationService; class FtpSyncMethod extends BaseMethod implements MethodInterface { @@ -27,6 +28,17 @@ public function supports(string $method_name): bool return $method_name === $this->getName(); } + public function getGlobalSettings(): array + { + $defaults = parent::getGlobalSettings(); // TODO: Change the autogenerated stub + $defaults['excludeFiles']['ftpSync'] = [ + '.git/', + 'node_modules/' + ]; + + return $defaults; + } + public function getDefaultConfig(ConfigurationService $configuration_service, array $host_config): array { $return = parent::getDefaultConfig($configuration_service, $host_config); @@ -36,6 +48,14 @@ public function getDefaultConfig(ConfigurationService $configuration_service, ar ]; $return['deployMethod'] = 'ftp-sync'; + $return['ftp'] = [ + 'port' => 21, + 'lftpOptions' => [ + '--ignore-time', + '--verbose=2', + '--no-perms' + ] + ]; return $return; } @@ -49,33 +69,46 @@ public function validateConfig(array $config, ValidationErrorBagInterface $error if ($config['deployMethod'] !== 'ftp-sync') { $errors->addError('deployMethod', 'deployMethod must be `ftp-sync`!'); } + $service = new ValidationService($config, $errors, 'Host-config '. $config['configName']); + $service->isArray('ftp', 'Please provide ftp-credentials!'); + if (!empty($config['ftp'])) { + $service = new ValidationService($config['ftp'], $errors, 'host-config.ftp '. $config['configName']); + $service->hasKeys([ + 'user' => 'the ftp user-name', + 'password' => 'the ftp password', + 'host' => 'the ftp host to connect to', + 'port' => 'the port to connect to', + 'rootFolder' => 'the rootfolder of your app on the remote file-system', + ]); + } } /** * @param HostConfig $host_config * @param TaskContextInterface $context + * @param ShellProviderInterface $shell + * @param string $install_dir * @throws \Phabalicious\Exception\MethodNotFoundException + * @throws \Phabalicious\Exception\MissingScriptCallbackImplementation * @throws \Phabalicious\Exception\TaskNotFoundInMethodException */ - public function deploy(HostConfig $host_config, TaskContextInterface $context) - { - if ($host_config['deployMethod'] !== 'ftp-sync') { - return; - } - + protected function createAppCode( + HostConfig $host_config, + TaskContextInterface $context, + ShellProviderInterface $shell, + string $install_dir + ) { // First, create an app in a temporary-folder. $stages = $context->getConfigurationService()->getSetting( 'appStages.createCode', AppDefaultStages::CREATE_CODE ); - $install_dir = $host_config['tmpFolder'] . '/' . $host_config['configName'] . '-' . time(); - $context->set('installDir', $install_dir); + $cloned_host_config = clone $host_config; $keys = ['rootFolder', 'composerRootFolder', 'gitRootFolder']; foreach ($keys as $key) { $cloned_host_config[$key] = $install_dir; } - $shell = $this->getShell($cloned_host_config, $context); $shell->cd($cloned_host_config['tmpFolder']); $context->set('outerShell', $shell); @@ -94,9 +127,55 @@ public function deploy(HostConfig $host_config, TaskContextInterface $context) $script_method->runTaskSpecificScripts($host_config, 'reset', $context); $context->setResult('skipResetStep', true); + } + /** + * @param HostConfig $host_config + * @param TaskContextInterface $context + * @throws \Phabalicious\Exception\MethodNotFoundException + * @throws \Phabalicious\Exception\MissingScriptCallbackImplementation + * @throws \Phabalicious\Exception\TaskNotFoundInMethodException + */ + public function deploy(HostConfig $host_config, TaskContextInterface $context) + { + if ($host_config['deployMethod'] !== 'ftp-sync') { + return; + } + + $install_dir = $host_config['tmpFolder'] . '/' . $host_config['configName'] . '-' . time(); + $context->set('installDir', $install_dir); + + $shell = $this->getShell($host_config, $context); + $this->createAppCode($host_config, $context, $shell, $install_dir); + + $exclude = $context->getConfigurationService()->getSetting('excludeFiles.ftpSync', []); + $options = implode(' ', $host_config['ftp']['lftpOptions']); + if (count($exclude)) { + $options .= ' --exclude ' . implode(' --exclude ', $exclude); + } // Now we can sync the files via FTP. // TODO + $command_file = $host_config['tmpFolder'] . '/lftp_commands_' . time() . '.x'; + $shell->run(sprintf('touch %s', $command_file)); + $shell->run(sprintf( + 'echo "open -u %s,%s -p%s %s" >> %s', + $host_config['ftp']['user'], + $host_config['ftp']['password'], + $host_config['ftp']['port'], + $host_config['ftp']['host'], + $command_file + )); + $shell->run(sprintf( + 'echo "mirror %s -c -e -RL %s %s" >> %s', + $options, + $install_dir, + $host_config['ftp']['rootFolder'], + $command_file + )); + + $shell->run(sprintf('echo "exit" >> %s', $command_file)); + + $shell->run(sprintf('#!lftp -f %s', $command_file)); // Cleanup. $shell->run(sprintf('rm -rf %s', $install_dir)); @@ -104,6 +183,4 @@ public function deploy(HostConfig $host_config, TaskContextInterface $context) // Do not run any next tasks. $context->setResult('runNextTasks', []); } - - } diff --git a/src/Method/GitMethod.php b/src/Method/GitMethod.php index 364e03ed..8249af16 100644 --- a/src/Method/GitMethod.php +++ b/src/Method/GitMethod.php @@ -45,7 +45,6 @@ public function getDefaultConfig(ConfigurationService $configuration_service, ar 'gitRootFolder' => $host_config['rootFolder'], 'ignoreSubmodules' => false, 'gitOptions' => $configuration_service->getSetting('gitOptions', []), - 'deployMethod' => 'git', ]; } @@ -56,6 +55,14 @@ public function validateConfig(array $config, ValidationErrorBagInterface $error $validation->hasKey('branch', 'git needs a branch-name so it can run deployments.'); } + public function alterConfig(ConfigurationService $configuration_service, array &$data) + { + parent::alterConfig($configuration_service, $data); // TODO: Change the autogenerated stub + if (empty($data['deployMethod'])) { + $data['deployMethod'] = 'git'; + } + } + public function getVersion(HostConfig $host_config, TaskContextInterface $context) { $host_config->shell()->cd($host_config['gitRootFolder']); @@ -176,5 +183,4 @@ public function appCreate(HostConfig $host_config, TaskContextInterface $context $shell->run('touch .projectCreated'); $shell->cd($cwd); } - -} \ No newline at end of file +} From 7ceda4aec273d9b67ef39eab6d136d5d1657c1ed Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 23:17:42 +0100 Subject: [PATCH 45/74] Update changelog --- Changelog.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Changelog.md b/Changelog.md index 7cba0680..4f2218a9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -67,27 +67,27 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav service: web The `name` will be discarded, if a `service`-entry is set. -* new method `ftp-sync`, it's a bit special. This method creates the app into a temporary folder, and syncs it via `lftp` to a remote instance. Here's a complete example: +* new method `ftp-sync`, it's a bit special. This method creates the app into a temporary folder, and syncs it via `lftp` to a remote instance. Here's a complete example (most of them are provided via sensible defaults): excludeFiles: ftp-sync: - .git/ - node_modules - hosts: - ftpSyncSample: - needs: - - git - - ftp-sync - - local - ftp: - user: - password: - host: - port: 21 - lftpOptions: - - --ignoreTime - - --verbose=3 - - --no-perms + hosts: + ftpSyncSample: + needs: + - git + - ftp-sync + - local + ftp: + user: + password: + host: + port: 21 + lftpOptions: + - --ignoreTime + - --verbose=3 + - --no-perms From 9f2b6338d62f4fd931877548989bed207686288b Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 23:27:49 +0100 Subject: [PATCH 46/74] Add documentation for ftp-sync --- docs/docs/app-create-destroy.md | 5 +++++ docs/docs/available-tasks.md | 1 + docs/docs/configuration.md | 21 +++++++++++++++------ docs/docs/usage.md | 1 + 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/docs/app-create-destroy.md b/docs/docs/app-create-destroy.md index e02a10e3..c0e946fd 100644 --- a/docs/docs/app-create-destroy.md +++ b/docs/docs/app-create-destroy.md @@ -18,6 +18,9 @@ appStages: - stage: spinUp - stage: installDependencies - stage: install + createCode: + - stage: installCode + - stage: installDependencies deploy: - stage: spinUp destroy: @@ -25,6 +28,8 @@ appStages: - stage: deleteContainers ``` +`createCode` is only used by the `ftp-sync`-method, to create a complete code version of an app. + ## Creating a new app Run the phab-command as usual. If you want to copy from an existing installation, add the `--copy-from`-option. diff --git a/docs/docs/available-tasks.md b/docs/docs/available-tasks.md index cad2578c..74461a1f 100644 --- a/docs/docs/available-tasks.md +++ b/docs/docs/available-tasks.md @@ -186,6 +186,7 @@ After a successfull deployment the `reset`-task will be run. * `git` will deploy to the latest commit for the given branch defined in the host-configuration. Submodules will be synced, and updated. * `platform` will push the current branch to the `platform` remote, which will start the deployment-process on platform.sh +* `ftp-sync` will create a copy of the app in a temporary folder and syncs this folder with the help of `lftp` with a remote-ftp-server. **Examples:** diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md index f1f83c0c..69abd351 100644 --- a/docs/docs/configuration.md +++ b/docs/docs/configuration.md @@ -36,10 +36,12 @@ List here all needed methods for that type of project. Available methods are: * `ssh` * `drush` for support of drupal installations * `files` - * `Mattermost` for slack-notifications + * `mattermost` for slack-notifications * `docker` for docker-support * `composer` for composer support * `drupalconsole` for drupal-concole support + * `platform` for deploying to platform.sh + * `ftp-sync` to deploy to a ftp-server **Example for drupal 7** @@ -159,7 +161,7 @@ This will print all host configuration for the host `staging`. * `composerRootFolder` the folder where the composer.json for the project is stored, defaults to `gitRootFolder`. -#### Configuration for the crush-method +#### Configuration for the drush-method * `siteFolder` is a drupal-specific folder, where the settings.php resides for the given installation. This allows to interact with multisites etc. * `filesFolder` the path to the files-folder, where user-assets get stored and which should be backed up by the `files`-method @@ -177,6 +179,17 @@ This will print all host configuration for the host `staging`. * `drupalVersion` set the drupal-version to use. If not set phabalicious is trying to guess it from the `needs`-configuration. * `drushVersion` set the used crush-version, default is `8`. Drush is not 100% backwards-compatible, for phabalicious needs to know its version. * `supportsZippedBackups` default is true, set to false, when zipped backups are not supported + +#### Configuration of the ftp-sync-method + +* `ftp` keeps all configuration bundled: + * `user` the ftp-user + * `password` the ftp password + * `host` the ftp host + * `port`, default is 21, the port to connect to + * `rootFolder` the folder to copy the app into on the ftp-host. + * `lftpOptions`, an array of options to pass when executing `lftp` + #### Configuration of the docker-method * `docker` for all docker-relevant configuration. `configuration` and `name`/`service` are the only required keys, all other are optional and used by the docker-tasks. @@ -184,10 +197,6 @@ This will print all host configuration for the host `staging`. * `name` contains the name of the docker-container. This is needed to get the IP-address of the particular docker-container when using ssh-tunnels (see above). * for docker-compose-base setups you can provide the `service` instead the name, phabalicious will get the docker name automatically from the service. - - - - ### dockerHosts `dockerHosts` is similar structured as the `hosts`-entry. It's a keyed lists of hosts containing all necessary information to create a ssh-connection to the host, controlling the docker-instances, and a list of tasks, the user might call via the `docker`-command. See the `docker`-entry for a more birds-eye-view of the concepts. diff --git a/docs/docs/usage.md b/docs/docs/usage.md index 7a38d37d..5af9d52b 100644 --- a/docs/docs/usage.md +++ b/docs/docs/usage.md @@ -25,6 +25,7 @@ Phabalicious provides a set of so-called methods which implement all listed func * drupalconsole * mattermost * platform +* ftp-sync You declare your needs in the fabfile.yaml with the key `needs`, e.g. From 9bb7d7d7375cd9c03b4155606f4220ad5e3ec972 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 23:30:46 +0100 Subject: [PATCH 47/74] Remove duplicate file --- docs/docs/app-create-delete.md | 58 ---------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 docs/docs/app-create-delete.md diff --git a/docs/docs/app-create-delete.md b/docs/docs/app-create-delete.md deleted file mode 100644 index e02a10e3..00000000 --- a/docs/docs/app-create-delete.md +++ /dev/null @@ -1,58 +0,0 @@ -# Creating/ destroying an app from existing configuration - -Phabalicious can create or delete a complete app with two commands: - - * `phab --config= app:create --copy-from=` - * `phab --config= app:destroy` - -Both commands executes a list of stages, which can be influenced via configuration - -## the standard stages - -These are the standard stages. You can override them by adding them to the global section of your fabfile: - -```yaml -appStages: - create: - - stage: installCode - - stage: spinUp - - stage: installDependencies - - stage: install - deploy: - - stage: spinUp - destroy: - - stage: spinDown - - stage: deleteContainers -``` - -## Creating a new app - -Run the phab-command as usual. If you want to copy from an existing installation, add the `--copy-from`-option. - -```shell -phab --config= app:create -``` - -If the app is already created (there's an existing `.projectCreated`-file in the root of the installation), only the `deploy`-stage will be executed, and afterwards the deploy-task will be executed. - -If the app is not created yet, all `create`-stages will be executed. If nothing went wrong you should have a running installation of the given configuration - -## Destroying an app - -```shell -phab --config= app:destroy -``` - -This will execute all `destroy`-stages and delete the project-folder afterwards. - -## Blueprints - -Both commands work best when using blueprints. This will allow to create a config and an app from a single string like a name of a feature. - -Some examples: - -```shell -phab --config=some-config --blueprint=feature/ create:app -``` - -Will create a new app from a blueprinted config. \ No newline at end of file From e33b98b1efb3134a68b48eef8859a6645230c15f Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Wed, 5 Dec 2018 23:32:32 +0100 Subject: [PATCH 48/74] Remove obsolete comments --- src/Method/FtpSyncMethod.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Method/FtpSyncMethod.php b/src/Method/FtpSyncMethod.php index 4bff1059..6069f29c 100644 --- a/src/Method/FtpSyncMethod.php +++ b/src/Method/FtpSyncMethod.php @@ -30,7 +30,7 @@ public function supports(string $method_name): bool public function getGlobalSettings(): array { - $defaults = parent::getGlobalSettings(); // TODO: Change the autogenerated stub + $defaults = parent::getGlobalSettings(); $defaults['excludeFiles']['ftpSync'] = [ '.git/', 'node_modules/' @@ -62,7 +62,7 @@ public function getDefaultConfig(ConfigurationService $configuration_service, ar public function validateConfig(array $config, ValidationErrorBagInterface $errors) { - parent::validateConfig($config, $errors); // TODO: Change the autogenerated stub + parent::validateConfig($config, $errors); if (in_array('drush', $config['needs'])) { $errors->addError('needs', 'The method `ftp-sync` is incompatible with the `drush`-method!'); } @@ -154,7 +154,6 @@ public function deploy(HostConfig $host_config, TaskContextInterface $context) } // Now we can sync the files via FTP. - // TODO $command_file = $host_config['tmpFolder'] . '/lftp_commands_' . time() . '.x'; $shell->run(sprintf('touch %s', $command_file)); $shell->run(sprintf( From aacc140a4b2b704c3c89fb5cf860fbc2686706fd Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Thu, 6 Dec 2018 15:33:52 +0100 Subject: [PATCH 49/74] Support legacy host-types --- src/Configuration/ConfigurationService.php | 3 +++ src/Configuration/HostType.php | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/Configuration/ConfigurationService.php b/src/Configuration/ConfigurationService.php index 597e233f..29bc0c1c 100644 --- a/src/Configuration/ConfigurationService.php +++ b/src/Configuration/ConfigurationService.php @@ -411,6 +411,9 @@ private function validateHostConfig($config_name, $data) { $data = $this->resolveInheritance($data, $this->hosts); $type = isset($data['type']) ? $data['type'] : false; + $type = HostType::convertLegacyTypes($type); + $data['type'] = $type; + $defaults = [ 'type' => $type ? $type : 'dev', 'config_name' => $config_name, // For backwards compatibility diff --git a/src/Configuration/HostType.php b/src/Configuration/HostType.php index 7a19ef76..012ec789 100644 --- a/src/Configuration/HostType.php +++ b/src/Configuration/HostType.php @@ -25,4 +25,13 @@ public static function getAll() ]; } + public static function convertLegacyTypes($type) + { + if ($type == 'live') { + return self::PROD; + } + + return $type; + } + } \ No newline at end of file From 448635688e0d573fedbbe9aa8a19387c89a4a5b9 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Thu, 6 Dec 2018 19:04:00 +0100 Subject: [PATCH 50/74] Ask for password when necessary, or get it from ~/.phabalicious-credentials --- src/Configuration/ConfigurationService.php | 4 +- src/Method/FtpSyncMethod.php | 9 +++- src/Method/TaskContext.php | 22 +++++++++ src/Method/TaskContextInterface.php | 7 +++ src/Utilities/PasswordManager.php | 57 ++++++++++++++++++++++ src/Utilities/PasswordManagerInterface.php | 10 ++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 src/Utilities/PasswordManager.php create mode 100644 src/Utilities/PasswordManagerInterface.php diff --git a/src/Configuration/ConfigurationService.php b/src/Configuration/ConfigurationService.php index 29bc0c1c..f8928475 100644 --- a/src/Configuration/ConfigurationService.php +++ b/src/Configuration/ConfigurationService.php @@ -412,7 +412,9 @@ private function validateHostConfig($config_name, $data) $data = $this->resolveInheritance($data, $this->hosts); $type = isset($data['type']) ? $data['type'] : false; $type = HostType::convertLegacyTypes($type); - $data['type'] = $type; + if (!empty($type)) { + $data['type'] = $type; + } $defaults = [ 'type' => $type ? $type : 'dev', diff --git a/src/Method/FtpSyncMethod.php b/src/Method/FtpSyncMethod.php index 4bff1059..ca4ff0d1 100644 --- a/src/Method/FtpSyncMethod.php +++ b/src/Method/FtpSyncMethod.php @@ -9,6 +9,7 @@ use Phabalicious\Utilities\AppDefaultStages; use Phabalicious\Validation\ValidationErrorBagInterface; use Phabalicious\Validation\ValidationService; +use Symfony\Component\Console\Helper\QuestionHelper; class FtpSyncMethod extends BaseMethod implements MethodInterface { @@ -75,7 +76,6 @@ public function validateConfig(array $config, ValidationErrorBagInterface $error $service = new ValidationService($config['ftp'], $errors, 'host-config.ftp '. $config['configName']); $service->hasKeys([ 'user' => 'the ftp user-name', - 'password' => 'the ftp password', 'host' => 'the ftp host to connect to', 'port' => 'the port to connect to', 'rootFolder' => 'the rootfolder of your app on the remote file-system', @@ -141,6 +141,12 @@ public function deploy(HostConfig $host_config, TaskContextInterface $context) return; } + if (empty($host_config['ftp']['password'])) { + $ftp = $host_config['ftp']; + $ftp['password'] = $context->getPasswordManager()->getPasswordFor($ftp['host'], $ftp['port'], $ftp['user']); + $host_config['ftp'] = $ftp; + } + $install_dir = $host_config['tmpFolder'] . '/' . $host_config['configName'] . '-' . time(); $context->set('installDir', $install_dir); @@ -178,6 +184,7 @@ public function deploy(HostConfig $host_config, TaskContextInterface $context) $shell->run(sprintf('#!lftp -f %s', $command_file)); // Cleanup. + $shell->run(sprintf('rm %s', $command_file)); $shell->run(sprintf('rm -rf %s', $install_dir)); // Do not run any next tasks. diff --git a/src/Method/TaskContext.php b/src/Method/TaskContext.php index eae382d1..b40dba29 100644 --- a/src/Method/TaskContext.php +++ b/src/Method/TaskContext.php @@ -7,10 +7,14 @@ use Phabalicious\Configuration\ConfigurationService; use Phabalicious\ShellProvider\CommandResult; use Phabalicious\ShellProvider\ShellProviderInterface; +use Phabalicious\Utilities\PasswordManager; use Phabalicious\Utilities\Utilities; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; class TaskContext implements TaskContextInterface { @@ -30,6 +34,8 @@ class TaskContext implements TaskContextInterface private $shell; + private $passwordManager; + public function __construct(BaseOptionsCommand $command, InputInterface $input, OutputInterface $output) { $this->setInput($input); @@ -144,4 +150,20 @@ public function clearResults() { $this->result = []; } + + public function askQuestion(string $question) + { + $question = new Question($question); + $question_helper = new QuestionHelper(); + return $question_helper->ask($this->input, $this->output, $question); + } + + public function getPasswordManager() + { + if (!$this->passwordManager) { + $this->passwordManager = new PasswordManager($this); + } + + return $this->passwordManager; + } } \ No newline at end of file diff --git a/src/Method/TaskContextInterface.php b/src/Method/TaskContextInterface.php index d9307609..512150d4 100644 --- a/src/Method/TaskContextInterface.php +++ b/src/Method/TaskContextInterface.php @@ -7,6 +7,7 @@ use Phabalicious\Configuration\ConfigurationService; use Phabalicious\ShellProvider\CommandResult; use Phabalicious\ShellProvider\ShellProviderInterface; +use Phabalicious\Utilities\PasswordManagerInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -55,6 +56,12 @@ public function setShell(ShellProviderInterface $shell); public function mergeResults(TaskContextInterface $context); + public function askQuestion(string $string); + + /** + * @return PasswordManagerInterface + */ + public function getPasswordManager(); } diff --git a/src/Utilities/PasswordManager.php b/src/Utilities/PasswordManager.php new file mode 100644 index 00000000..86d23eca --- /dev/null +++ b/src/Utilities/PasswordManager.php @@ -0,0 +1,57 @@ +context = $context; + $this->readPasswords(); + } + + public function getPasswordFor(string $host, int $port, string $user) + { + $key = $this->getKey($host, $port, $user); + if (!empty($this->passwords[$key])) { + return $this->passwords[$key]; + } + + $pw = $this->context->askQuestion(sprintf('Please provide a password for `%s@%s`: ', $user, $host)); + $this->passwords[$key] = $pw; + return $pw; + } + + private function getKey($host, $port, $user) + { + return sprintf('%s@%s:%s', $user, $host, $port); + } + + private function readPasswords() + { + $file = getenv("HOME"). '/.phabalicious-credentials'; + if (!file_exists($file)) { + return; + } + + $data = Yaml::parseFile($file); + + if (!is_array($data)) { + throw new \RuntimeException(sprintf('Could not parse %s', $file)); + } + + $this->passwords = $data; + } + +} \ No newline at end of file diff --git a/src/Utilities/PasswordManagerInterface.php b/src/Utilities/PasswordManagerInterface.php new file mode 100644 index 00000000..89eb6d6c --- /dev/null +++ b/src/Utilities/PasswordManagerInterface.php @@ -0,0 +1,10 @@ + Date: Thu, 6 Dec 2018 22:03:24 +0100 Subject: [PATCH 51/74] Set rootFolder fot task-specific scripts --- src/Method/DrushMethod.php | 1 + src/Method/ScriptMethod.php | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Method/DrushMethod.php b/src/Method/DrushMethod.php index 6cf8b5a6..7e6d198c 100644 --- a/src/Method/DrushMethod.php +++ b/src/Method/DrushMethod.php @@ -216,6 +216,7 @@ public function reset(HostConfig $host_config, TaskContextInterface $context) } } + $context->set('rootFolder', $host_config['siteFolder']); $script_method->runTaskSpecificScripts($host_config, 'reset', $context); // Keep calm and clear the cache. diff --git a/src/Method/ScriptMethod.php b/src/Method/ScriptMethod.php index fe86ddc1..f7c2086f 100644 --- a/src/Method/ScriptMethod.php +++ b/src/Method/ScriptMethod.php @@ -56,9 +56,7 @@ public function runScript(HostConfig $host_config, TaskContextInterface $context $context->setShell($host_config->shell()); } - $root_folder = isset($host_config['siteFolder']) - ? $host_config['siteFolder'] - : isset($host_config['rootFolder']) + $root_folder = isset($host_config['rootFolder']) ? $host_config['rootFolder'] : '.'; $root_folder = $context->get('rootFolder', $root_folder); From 4fccd9fec19c6d55c64a0e77551e7c63c2722b39 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Thu, 6 Dec 2018 22:22:18 +0100 Subject: [PATCH 52/74] Update docs --- Changelog.md | 7 ++++--- docs/docs/passwords.md | 14 ++++++++++++++ docs/mkdocs.yml | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 docs/docs/passwords.md diff --git a/Changelog.md b/Changelog.md index 4f2218a9..867e5ca1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -81,15 +81,16 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav - local ftp: user: - password: + password: # host: port: 21 lftpOptions: - --ignoreTime - --verbose=3 - --no-perms - - + + You can add your password to the file `.phabalicious-credentials` (see passwords.md) so phabalicious pick it up. + ### Changed diff --git a/docs/docs/passwords.md b/docs/docs/passwords.md new file mode 100644 index 00000000..0b1c6269 --- /dev/null +++ b/docs/docs/passwords.md @@ -0,0 +1,14 @@ +# Passwords + +You should not store any sensitive passwords in the fabfile. It's a possible security risk, as the file is part of your repository. + +That's why phabalicious is heavily relying on key-forwarding for ssh-connections. If key-forwarding does not work, you might get a native ssh-password-prompt. + +If you are using the method `ftp-sync` you can add the password to the fabfile, but we strongly discourage this. If you want to store the password permanently so that phabalicious can pick them up, store them in your user-folder in a yml-file called `.phabalicious-credentials`. The format is as follows + +```yaml +"@:": +"stephan@localhost:21": 123456 +``` + +If no password is available, phabalicious will prompt for one. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 3ad33233..fbf34636 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -21,6 +21,7 @@ nav: - scripts.md - app-scaffold.md - app-create-destroy.md + - passwords.md - contribute.md - Changelog.md extra_css: From e94543c5c2842d94cf63cec0c41d3effd0abcc1d Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Thu, 6 Dec 2018 22:22:40 +0100 Subject: [PATCH 53/74] Set folder for script-phase --- src/Method/FtpSyncMethod.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Method/FtpSyncMethod.php b/src/Method/FtpSyncMethod.php index 245af6b2..91b525b3 100644 --- a/src/Method/FtpSyncMethod.php +++ b/src/Method/FtpSyncMethod.php @@ -124,7 +124,11 @@ protected function createAppCode( // Run deploy scripts /** @var ScriptMethod $script_method */ $script_method = $context->getConfigurationService()->getMethodFactory()->getMethod('script'); - $script_method->runTaskSpecificScripts($host_config, 'reset', $context); + $context->set('variables', [ + 'installFolder' => $install_dir + ]); + $context->set('rootFolder', $install_dir); + $script_method->runTaskSpecificScripts($host_config, 'deploy', $context); $context->setResult('skipResetStep', true); } From a21affa5bae8636729b496c670bf537598c984e1 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Fri, 7 Dec 2018 09:31:57 +0100 Subject: [PATCH 54/74] Initial work on self-update-command --- composer.json | 3 +- composer.lock | 179 +++++++++++++++++++++++++++++- src/Command/SelfUpdateCommand.php | 58 ++++++++++ symfony.lock | 9 ++ 4 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 src/Command/SelfUpdateCommand.php diff --git a/composer.json b/composer.json index 9ad65792..16b8f893 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "thibaud-dauce/mattermost-php": "^1.2", "twig/twig": "^2.5", "ext-openssl": "*", - "jakeasmith/http_build_url": "^1.0" + "jakeasmith/http_build_url": "^1.0", + "padraic/phar-updater": "^1.0" }, "require-dev": { "symfony/phpunit-bridge": "^2.8|^3|^4.1", diff --git a/composer.lock b/composer.lock index 4253cb12..fb1c5273 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,64 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0a7e621832339106f83ee1b5614ed19a", + "content-hash": "0deb5f27b10066b4dc9222e5f22b5e08", "packages": [ + { + "name": "composer/ca-bundle", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "8afa52cd417f4ec417b4bfe86b68106538a87660" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/8afa52cd417f4ec417b4bfe86b68106538a87660", + "reference": "8afa52cd417f4ec417b4bfe86b68106538a87660", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", + "psr/log": "^1.0", + "symfony/process": "^2.5 || ^3.0 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "time": "2018-10-18T06:09:13+00:00" + }, { "name": "composer/semver", "version": "1.4.2", @@ -282,6 +338,127 @@ "description": "Provides functionality for http_build_url() to environments without pecl_http.", "time": "2017-05-01T15:36:40+00:00" }, + { + "name": "padraic/humbug_get_contents", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/humbug/file_get_contents.git", + "reference": "dcb086060c9dd6b2f51d8f7a895500307110b7a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/file_get_contents/zipball/dcb086060c9dd6b2f51d8f7a895500307110b7a7", + "reference": "dcb086060c9dd6b2f51d8f7a895500307110b7a7", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "ext-openssl": "*", + "php": "^5.3 || ^7.0 || ^7.1 || ^7.2" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.1", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false + }, + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Humbug\\": "src/" + }, + "files": [ + "src/function.php", + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Théo Fidry", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Secure wrapper for accessing HTTPS resources with file_get_contents for PHP 5.3+", + "homepage": "https://github.com/padraic/file_get_contents", + "keywords": [ + "download", + "file_get_contents", + "http", + "https", + "ssl", + "tls" + ], + "time": "2018-02-12T18:47:17+00:00" + }, + { + "name": "padraic/phar-updater", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/humbug/phar-updater.git", + "reference": "d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/phar-updater/zipball/d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1", + "reference": "d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1", + "shasum": "" + }, + "require": { + "padraic/humbug_get_contents": "^1.0", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Humbug\\SelfUpdate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + } + ], + "description": "A thing to make PHAR self-updating easy and secure.", + "keywords": [ + "humbug", + "phar", + "self-update", + "update" + ], + "time": "2018-03-30T12:52:15+00:00" + }, { "name": "psr/container", "version": "1.0.0", diff --git a/src/Command/SelfUpdateCommand.php b/src/Command/SelfUpdateCommand.php new file mode 100644 index 00000000..ed9913ba --- /dev/null +++ b/src/Command/SelfUpdateCommand.php @@ -0,0 +1,58 @@ +setName('self-update') + ->setDescription('Installs the latest version') + ->setHelp('Downloads and install the latest version from github.'); + + $this->addOption( + 'allow-unstable', + null, + InputOption::VALUE_OPTIONAL, + 'Allow updating to unstable versions', + false + ); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $helper = new SymfonyStyle($input, $output); + $helper->text('Looking for a new version ...'); + + $result = $this->runSelfUpdate($input->getOption('allow-unstable')); + + if ($result) { + $helper->success('Updated phabalicious sucessfuly'); + } else { + $helper->note('No newer version found!'); + } + } + + private function runSelfUpdate($allow_unstable) + { + $updater = new Updater(null, false); + $updater->setStrategy(Updater::STRATEGY_GITHUB); + + $updater->getStrategy()->setPackageName('factorial-io/phabalicious'); + $updater->getStrategy()->setPharName('phabalicious.phar'); + $updater->getStrategy()->setCurrentLocalVersion($this->getApplication()->getVersion()); + $updater->getStrategy()->setCurrentLocalVersion('3.0.0-alpha.1'); + $updater->getStrategy()->setStability($allow_unstable ? 'unstable' : 'stable'); + $result = $updater->update(); + + return $result; + } +} diff --git a/symfony.lock b/symfony.lock index ee77f1ce..a31744fe 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,4 +1,7 @@ { + "composer/ca-bundle": { + "version": "1.1.3" + }, "composer/semver": { "version": "1.4.2" }, @@ -53,6 +56,12 @@ "neutron/signal-handler": { "version": "1.0.1" }, + "padraic/humbug_get_contents": { + "version": "1.1.2" + }, + "padraic/phar-updater": { + "version": "v1.0.6" + }, "phar-io/manifest": { "version": "1.0.3" }, From b13f3609cb87a3b2b95b1b04b6cd88d144afced4 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Fri, 7 Dec 2018 16:47:06 +0100 Subject: [PATCH 55/74] Do not run empty script lines (Fixes #8) --- src/Method/ScriptMethod.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Method/ScriptMethod.php b/src/Method/ScriptMethod.php index fe86ddc1..8545deef 100644 --- a/src/Method/ScriptMethod.php +++ b/src/Method/ScriptMethod.php @@ -152,6 +152,10 @@ private function runScriptImpl( } foreach ($commands as $line) { + $line = trim($line); + if (empty($line)) { + continue; + } $result = Utilities::extractCallback($line); $callback_handled = false; if ($result) { From 61c94d3c9432de01ef4344485027ea2d4f2dac2b Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 15:45:59 +0100 Subject: [PATCH 56/74] Continue work on self-updater --- src/Command/SelfUpdateCommand.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Command/SelfUpdateCommand.php b/src/Command/SelfUpdateCommand.php index ed9913ba..ec1aaf94 100644 --- a/src/Command/SelfUpdateCommand.php +++ b/src/Command/SelfUpdateCommand.php @@ -30,12 +30,15 @@ protected function configure() public function execute(InputInterface $input, OutputInterface $output) { $helper = new SymfonyStyle($input, $output); - $helper->text('Looking for a new version ...'); + $helper->text(sprintf( + 'Current version is %s, looking for a new version ...', + $this->getApplication()->getVersion() + )); - $result = $this->runSelfUpdate($input->getOption('allow-unstable')); + $new_version = $this->runSelfUpdate($input->getOption('allow-unstable')); - if ($result) { - $helper->success('Updated phabalicious sucessfuly'); + if ($new_version) { + $helper->success(sprintf('Updated phabalicious successfully to %s', $new_version)); } else { $helper->note('No newer version found!'); } @@ -53,6 +56,6 @@ private function runSelfUpdate($allow_unstable) $updater->getStrategy()->setStability($allow_unstable ? 'unstable' : 'stable'); $result = $updater->update(); - return $result; + return $result ? $updater->getNewVersion() : false; } } From 91f131789e343b9706d604f9f70bb7a937196127 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 17:20:08 +0100 Subject: [PATCH 57/74] Switch to box for building phars --- bin/phab | 2 +- box.json | 6 + composer.json | 7 +- composer.lock | 711 +------------------------------------------------- symfony.lock | 39 --- 5 files changed, 12 insertions(+), 753 deletions(-) create mode 100644 box.json diff --git a/bin/phab b/bin/phab index 0aec7a00..43ce0d64 100755 --- a/bin/phab +++ b/bin/phab @@ -45,7 +45,7 @@ $output = $container->get(ConsoleOutput::class); /** @var Application $application */ $application = $container->get(Application::class); -$application->setVersion('3.0.0-alpha.3'); +$application->setVersion('@git_tag@'); $application->setName('phabalicious'); $application->setDefaultCommand('list'); diff --git a/box.json b/box.json new file mode 100644 index 00000000..b7e9ea09 --- /dev/null +++ b/box.json @@ -0,0 +1,6 @@ +{ + "main": "bin/phab", + "git-tag": "git_tag", + "output": "build/phabalicious.phar", + "compression": "GZ" +} diff --git a/composer.json b/composer.json index 16b8f893..09a4ffee 100644 --- a/composer.json +++ b/composer.json @@ -21,14 +21,13 @@ "symfony/finder": "^4.1", "thibaud-dauce/mattermost-php": "^1.2", "twig/twig": "^2.5", - "ext-openssl": "*", + "ext-openssl": "*", "jakeasmith/http_build_url": "^1.0", "padraic/phar-updater": "^1.0" }, "require-dev": { "symfony/phpunit-bridge": "^2.8|^3|^4.1", - "phpunit/phpunit": "^7.3", - "macfja/phar-builder": "dev-sf4-compatibility" + "phpunit/phpunit": "^7.3" }, "autoload": { "psr-4": {"Phabalicious\\": "src/"} @@ -43,7 +42,7 @@ "auto-scripts": { }, - "build-phar": "php -d phar.readonly=0 vendor/bin/phar-builder package", + "build-phar": "box build", "install-phar": "cp ./build/phabalicious.phar /usr/local/bin/phab; chmod u+x /usr/local/bin/phab" }, "extra": { diff --git a/composer.lock b/composer.lock index fb1c5273..f652681c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0deb5f27b10066b4dc9222e5f22b5e08", + "content-hash": "9bbcaac27573c8bb1c358baf775fce0a", "packages": [ { "name": "composer/ca-bundle", @@ -1750,580 +1750,6 @@ ], "time": "2017-07-22T11:58:36+00:00" }, - { - "name": "hoa/consistency", - "version": "1.17.05.02", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Consistency.git", - "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", - "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", - "shasum": "" - }, - "require": { - "hoa/exception": "~1.0", - "php": ">=5.5.0" - }, - "require-dev": { - "hoa/stream": "~1.0", - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Consistency\\": "." - }, - "files": [ - "Prelude.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Consistency library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "autoloader", - "callable", - "consistency", - "entity", - "flex", - "keyword", - "library" - ], - "time": "2017-05-02T12:18:12+00:00" - }, - { - "name": "hoa/event", - "version": "1.17.01.13", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Event.git", - "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", - "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/exception": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Event\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Event library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "event", - "library", - "listener", - "observer" - ], - "time": "2017-01-13T15:30:50+00:00" - }, - { - "name": "hoa/exception", - "version": "1.17.01.16", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Exception.git", - "reference": "091727d46420a3d7468ef0595651488bfc3a458f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", - "reference": "091727d46420a3d7468ef0595651488bfc3a458f", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/event": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Exception\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Exception library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "exception", - "library" - ], - "time": "2017-01-16T07:53:27+00:00" - }, - { - "name": "hoa/file", - "version": "1.17.07.11", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/File.git", - "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/File/zipball/35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", - "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/event": "~1.0", - "hoa/exception": "~1.0", - "hoa/iterator": "~2.0", - "hoa/stream": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\File\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\File library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "Socket", - "directory", - "file", - "finder", - "library", - "link", - "temporary" - ], - "time": "2017-07-11T07:42:15+00:00" - }, - { - "name": "hoa/iterator", - "version": "2.17.01.10", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Iterator.git", - "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Iterator/zipball/d1120ba09cb4ccd049c86d10058ab94af245f0cc", - "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/exception": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Iterator\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Iterator library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "iterator", - "library" - ], - "time": "2017-01-10T10:34:47+00:00" - }, - { - "name": "hoa/protocol", - "version": "1.17.01.14", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Protocol.git", - "reference": "5c2cf972151c45f373230da170ea015deecf19e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Protocol/zipball/5c2cf972151c45f373230da170ea015deecf19e2", - "reference": "5c2cf972151c45f373230da170ea015deecf19e2", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/exception": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Protocol\\": "." - }, - "files": [ - "Wrapper.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Protocol library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "library", - "protocol", - "resource", - "stream", - "wrapper" - ], - "time": "2017-01-14T12:26:10+00:00" - }, - { - "name": "hoa/stream", - "version": "1.17.02.21", - "source": { - "type": "git", - "url": "https://github.com/hoaproject/Stream.git", - "reference": "3293cfffca2de10525df51436adf88a559151d82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hoaproject/Stream/zipball/3293cfffca2de10525df51436adf88a559151d82", - "reference": "3293cfffca2de10525df51436adf88a559151d82", - "shasum": "" - }, - "require": { - "hoa/consistency": "~1.0", - "hoa/event": "~1.0", - "hoa/exception": "~1.0", - "hoa/protocol": "~1.0" - }, - "require-dev": { - "hoa/test": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Hoa\\Stream\\": "." - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Ivan Enderlin", - "email": "ivan.enderlin@hoa-project.net" - }, - { - "name": "Hoa community", - "homepage": "https://hoa-project.net/" - } - ], - "description": "The Hoa\\Stream library.", - "homepage": "https://hoa-project.net/", - "keywords": [ - "Context", - "bucket", - "composite", - "filter", - "in", - "library", - "out", - "protocol", - "stream", - "wrapper" - ], - "time": "2017-02-21T16:01:06+00:00" - }, - { - "name": "league/event", - "version": "2.1.2", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/event.git", - "reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd", - "reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "henrikbjorn/phpspec-code-coverage": "~1.0.1", - "phpspec/phpspec": "~2.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Event\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frenky.net" - } - ], - "description": "Event package", - "keywords": [ - "emitter", - "event", - "listener" - ], - "time": "2015-05-21T12:24:47+00:00" - }, - { - "name": "macfja/phar-builder", - "version": "dev-sf4-compatibility", - "source": { - "type": "git", - "url": "https://github.com/MacFJA/PharBuilder.git", - "reference": "97f6f22408c4381c3a9570ca626bec105e6dccda" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MacFJA/PharBuilder/zipball/97f6f22408c4381c3a9570ca626bec105e6dccda", - "reference": "97f6f22408c4381c3a9570ca626bec105e6dccda", - "shasum": "" - }, - "require": { - "league/event": "^2.1", - "macfja/symfony-console-filechooser": "~0.2 || ~1", - "neutron/signal-handler": "^1.0", - "php": ">=5.4.0", - "rych/bytesize": "~1.0", - "symfony/console": "~2.7 || ^3.0 || ^4.0", - "symfony/finder": "^4.0", - "symfony/process": "^2.7 || ^3.0 || ^4.0", - "webignition/readable-duration": "^0.2" - }, - "require-dev": { - "phpmd/phpmd": "^2.4", - "sebastian/phpcpd": "^2.0", - "squizlabs/php_codesniffer": "^2.5" - }, - "bin": [ - "bin/phar-builder", - "bin/phar-builder.php" - ], - "type": "library", - "extra": { - "phar-builder": { - "skip-shebang": false, - "include-dev": false, - "entry-point": "bin/phar-builder.php", - "compression": "None", - "name": "phar-builder.phar", - "output-dir": "./", - "include": [ - "bin" - ] - } - }, - "autoload": { - "psr-4": { - "MacFJA\\PharBuilder\\": "app/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "MacFJA" - } - ], - "description": "CLI tool for create phar of your composer based project", - "time": "2018-10-28T11:59:57+00:00" - }, - { - "name": "macfja/symfony-console-filechooser", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/MacFJA/Symfony-Console-Filechooser.git", - "reference": "f27248a6993718fcc469d442e305e1d83f5e1eb5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MacFJA/Symfony-Console-Filechooser/zipball/f27248a6993718fcc469d442e305e1d83f5e1eb5", - "reference": "f27248a6993718fcc469d442e305e1d83f5e1eb5", - "shasum": "" - }, - "require": { - "hoa/file": "~1", - "symfony/console": "~2.6 || ^3.0 || ^4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "MacFJA\\Symfony\\Console\\Filechooser\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "MacFJA" - } - ], - "description": "Filechooser Helper for Symfony console (with autocompletion support)", - "keywords": [ - "autocomplete", - "autocompletion", - "chooser", - "console", - "file", - "filesystem", - "interactive", - "symfony" - ], - "time": "2018-10-21T12:14:48+00:00" - }, { "name": "myclabs/deep-copy", "version": "1.8.1", @@ -2372,49 +1798,6 @@ ], "time": "2018-06-11T23:09:50+00:00" }, - { - "name": "neutron/signal-handler", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/romainneutron/signal-handler.git", - "reference": "5f2069bf4a5901a65be51f57ea60779a279564c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/romainneutron/signal-handler/zipball/5f2069bf4a5901a65be51f57ea60779a279564c1", - "reference": "5f2069bf4a5901a65be51f57ea60779a279564c1", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~3.7" - }, - "type": "library", - "autoload": { - "psr-0": { - "Neutron": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Romain Neutron", - "email": "imprec@gmail.com", - "homepage": "http://www.lickmychip.com/" - } - ], - "description": "A library to ease the use of signal handling.", - "keywords": [ - "signal" - ], - "time": "2014-01-15T17:24:13+00:00" - }, { "name": "phar-io/manifest", "version": "1.0.3", @@ -3068,51 +2451,6 @@ ], "time": "2018-10-23T05:57:41+00:00" }, - { - "name": "rych/bytesize", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/rchouinard/bytesize.git", - "reference": "297e16ea047461b91e8d7eb90aa46aaa52917824" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rchouinard/bytesize/zipball/297e16ea047461b91e8d7eb90aa46aaa52917824", - "reference": "297e16ea047461b91e8d7eb90aa46aaa52917824", - "shasum": "" - }, - "require": { - "ext-bcmath": "*", - "php": ">=5.3.4" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "Rych\\ByteSize\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ryan Chouinard", - "email": "rchouinard@gmail.com", - "homepage": "http://ryanchouinard.com" - } - ], - "description": "Utility component for nicely formatted file sizes.", - "homepage": "https://github.com/rchouinard/bytesize", - "keywords": [ - "filesize" - ], - "time": "2014-04-04T18:06:18+00:00" - }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -3782,49 +3120,6 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "time": "2017-04-07T12:08:54+00:00" }, - { - "name": "webignition/readable-duration", - "version": "0.2", - "source": { - "type": "git", - "url": "https://github.com/webignition/readable-duration.git", - "reference": "fe7c33e259f82a015db69272e4eaa53c3f394230" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webignition/readable-duration/zipball/fe7c33e259f82a015db69272e4eaa53c3f394230", - "reference": "fe7c33e259f82a015db69272e4eaa53c3f394230", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jon Cram", - "email": "jon@webignition.net" - } - ], - "description": "Convert a value in seconds into a human-readable convenience duration", - "homepage": "https://github.com/webignition/readable-duration", - "keywords": [ - "duration", - "humand-readable", - "readable", - "time" - ], - "time": "2013-03-28T15:26:25+00:00" - }, { "name": "webmozart/assert", "version": "1.3.0", @@ -3878,9 +3173,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "macfja/phar-builder": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/symfony.lock b/symfony.lock index a31744fe..aed49cf6 100644 --- a/symfony.lock +++ b/symfony.lock @@ -17,45 +17,12 @@ "guzzlehttp/psr7": { "version": "1.4.2" }, - "hoa/consistency": { - "version": "1.17.05.02" - }, - "hoa/event": { - "version": "1.17.01.13" - }, - "hoa/exception": { - "version": "1.17.01.16" - }, - "hoa/file": { - "version": "1.17.07.11" - }, - "hoa/iterator": { - "version": "2.17.01.10" - }, - "hoa/protocol": { - "version": "1.17.01.14" - }, - "hoa/stream": { - "version": "1.17.02.21" - }, "jakeasmith/http_build_url": { "version": "1.0.1" }, - "league/event": { - "version": "2.1.2" - }, - "macfja/phar-builder": { - "version": "dev-sf4-compatibility" - }, - "macfja/symfony-console-filechooser": { - "version": "1.0.0" - }, "myclabs/deep-copy": { "version": "1.8.1" }, - "neutron/signal-handler": { - "version": "1.0.1" - }, "padraic/humbug_get_contents": { "version": "1.1.2" }, @@ -113,9 +80,6 @@ "psr/log": { "version": "1.0.2" }, - "rych/bytesize": { - "version": "v1.0.0" - }, "sebastian/code-unit-reverse-lookup": { "version": "1.0.1" }, @@ -227,9 +191,6 @@ "twig/twig": { "version": "v2.5.0" }, - "webignition/readable-duration": { - "version": "0.2" - }, "webmozart/assert": { "version": "1.3.0" }, From ecd104df3d3420e771767634deab57ff67c2edd9 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 17:22:18 +0100 Subject: [PATCH 58/74] Release start --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 867e5ca1..9a4b06c8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,6 @@ # Changelog -## 3.0.0 +## 3.0.0-alpha.1 Fabalicious is now rewritten in PHP, so we changed the name to make the separation more clear. Phabalicious is now a symfony console app and uses a more unix-style approach to arguments and options. E.g. instead of `config:` use `--config=` From 84ecb9d3b556e14ed42d5fcfdbfd54cab13bf641 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 17:28:28 +0100 Subject: [PATCH 59/74] Update docs --- docs/docs/available-tasks.md | 11 ++++++++++- readme.md | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/docs/available-tasks.md b/docs/docs/available-tasks.md index 74461a1f..43533645 100644 --- a/docs/docs/available-tasks.md +++ b/docs/docs/available-tasks.md @@ -566,4 +566,13 @@ This command will update the code-base to the latest changes. When using the cru phab --config= app:destroy ``` -This command will destroy an app from a given configuration. The process has several steps. Caution: there will be no backup! \ No newline at end of file +This command will destroy an app from a given configuration. The process has several steps. Caution: there will be no backup! + +## self-update + +```shell +phab self-update +Phan self-update --allow-unstable=1 +``` + +This will download the latest version of phab and replace the current installed one with the downloaded version. If `allow-unstable` is set, the latest-dev-version will be downloaded. \ No newline at end of file diff --git a/readme.md b/readme.md index 2ad5f8e2..5cc689d4 100644 --- a/readme.md +++ b/readme.md @@ -4,12 +4,14 @@ Phabalicious is the successor of the python tool [fabalicious](https://github.co ## Installation -* Download the `phabalicious.phar` +* Download the `phabalicious.phar` from https://github.com/factorial-io/phabalicious/releases * `cp phabalicious.phar /phab` * `chmod +x /phab` ## Build from source +You'll need [box](https://github.com/humbug/box) for building the phar-file. + * Clone the repository * run `composer install` * run `composer build-phar` @@ -25,6 +27,12 @@ Phabalicious is the successor of the python tool [fabalicious](https://github.co * Run `phab list` to get a list of all available commands. * run `phab help ` to get some help for a given command. +## Updating phab + +* Run `phab self-update`, this will download the latest release from GitHub. + +If you want to get the latest dev-version, add `--allow-unstable=1` + ## Enhancing phab, contributing to phab We welcome contributions! Please fork the repository, create a feature branch and submit a pull-request. From 7979db625a6201ab645471205fdbd7aad7b3e9d6 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 17:32:42 +0100 Subject: [PATCH 60/74] Increment circle-ci cache --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0da41d07..216f1625 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,16 +22,16 @@ jobs: # Download and cache dependencies - restore_cache: keys: - - v1-dependencies-{{ checksum "composer.json" }} + - v2-dependencies-{{ checksum "composer.json" }} # fallback to using the latest cache if no exact match is found - - v1-dependencies- + - v2-dependencies- - run: php /composer.phar install - save_cache: paths: - ./vendor - key: v1-dependencies-{{ checksum "composer.json" }} + key: v2-dependencies-{{ checksum "composer.json" }} # run tests! - run: cd tests; ../vendor/bin/phpunit --exclude-group docker . From 2513aacbbfbaf041f612ad1e5f285e90aa1fc959 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 17:38:16 +0100 Subject: [PATCH 61/74] Update changelog --- Changelog.md | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9a4b06c8..be98ef7e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,25 @@ # Changelog -## 3.0.0-alpha.1 +## 3.0.0-alpha.4 / 2018-12-08 + +### new + + * New command `self-update`, will download and install the latest available version + * New method `ftp-sync` to deploy code-bases to a remote ftp-instance + * Introduction of a password-manager for retrieving passwords from the user or a special file + +### changed + + * Switch to box for building phars + +### fixed + + * Do not run empty script lines (Fixes #8) + * Set folder for script-phase + * Set rootFolder fot task-specific scripts + * Support legacy host-types + +## 3.0.0 develop Fabalicious is now rewritten in PHP, so we changed the name to make the separation more clear. Phabalicious is now a symfony console app and uses a more unix-style approach to arguments and options. E.g. instead of `config:` use `--config=` @@ -59,7 +78,7 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav mbb: shellProvider: docker-exec * You can get help for a specific task via `phab help `. It will show all possible options and some help. -* docker-compose version 23 changes the schema how names of docker-containers are constructed. To support this change we can now declare the needed service to compute the correct container-name from. +* docker-compose version 23 changes the schema how names of docker-containers are constructed. To support this change we can now declare the needed service to compute the correct container-name from. hosts: testHost: @@ -80,7 +99,7 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav - ftp-sync - local ftp: - user: + user: password: # host: port: 21 @@ -89,9 +108,9 @@ Most notably the handling of arguments and options has changed a lot. Fabric gav - --verbose=3 - --no-perms - You can add your password to the file `.phabalicious-credentials` (see passwords.md) so phabalicious pick it up. - - + You can add your password to the file `.phabalicious-credentials` (see passwords.md) so phabalicious pick it up. + + ### Changed * `docker:startRemoteAccess` is now the task `start-remote-access` as it makes more sense. From baa13966a9db3528757ee50ae9edabb25416837b Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 18:14:05 +0100 Subject: [PATCH 62/74] Fix phar-build --- box.json | 4 ++++ build/create-release.sh | 6 +++--- composer.json | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/box.json b/box.json index b7e9ea09..9c8a0911 100644 --- a/box.json +++ b/box.json @@ -1,5 +1,9 @@ { "main": "bin/phab", + "files": [ + ".env", + "config/services.yml" + ], "git-tag": "git_tag", "output": "build/phabalicious.phar", "compression": "GZ" diff --git a/build/create-release.sh b/build/create-release.sh index cabb9ac4..e0178356 100644 --- a/build/create-release.sh +++ b/build/create-release.sh @@ -12,16 +12,16 @@ cd build res=`curl --user "$GH_USER:$GH_PATH" -X POST https://api.github.com/repos/${GH_USER}/${GH_REPO}/releases \ -d " { - \"tag_name\": \"v$VERSION\", + \"tag_name\": \"$VERSION\", \"target_commitish\": \"$GH_TARGET\", - \"name\": \"v$VERSION\", + \"name\": \"$VERSION\", \"body\": \"new version $VERSION\", \"draft\": false, \"prerelease\": false }"` echo Create release result: ${res} rel_id=`echo ${res} | python -c 'import json,sys;print(json.load(sys.stdin)["id"])'` -file_name=phabalicious-${VERSION}.phar +file_name=phabalicious.phar curl --user "$GH_USER:$GH_PATH" -X POST https://uploads.github.com/repos/${GH_USER}/${GH_REPO}/releases/${rel_id}/assets?name=${file_name}\ --header 'Content-Type: text/javascript ' --upload-file ${ASSETS_PATH}/phabalicious.phar diff --git a/composer.json b/composer.json index 09a4ffee..18448d38 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ "auto-scripts": { }, - "build-phar": "box build", + "build-phar": "box compile", "install-phar": "cp ./build/phabalicious.phar /usr/local/bin/phab; chmod u+x /usr/local/bin/phab" }, "extra": { From ca30860afb21bc7d3855696e547e4da816e77ffb Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 18:14:23 +0100 Subject: [PATCH 63/74] Use real version number --- src/Command/SelfUpdateCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Command/SelfUpdateCommand.php b/src/Command/SelfUpdateCommand.php index ec1aaf94..4a20193f 100644 --- a/src/Command/SelfUpdateCommand.php +++ b/src/Command/SelfUpdateCommand.php @@ -52,7 +52,6 @@ private function runSelfUpdate($allow_unstable) $updater->getStrategy()->setPackageName('factorial-io/phabalicious'); $updater->getStrategy()->setPharName('phabalicious.phar'); $updater->getStrategy()->setCurrentLocalVersion($this->getApplication()->getVersion()); - $updater->getStrategy()->setCurrentLocalVersion('3.0.0-alpha.1'); $updater->getStrategy()->setStability($allow_unstable ? 'unstable' : 'stable'); $result = $updater->update(); From 2a249f9e536afd4bf93ea271e8a297cafd789a5d Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sat, 8 Dec 2018 18:16:49 +0100 Subject: [PATCH 64/74] Update changelog --- Changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Changelog.md b/Changelog.md index be98ef7e..bb842c66 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,12 @@ # Changelog +## 3.0.0-alpha.5 / 2018-12-08 + +### fixed + + * Use real version number + * Fix phar-build + ## 3.0.0-alpha.4 / 2018-12-08 ### new From 4eddf131155f24b352a45d179a46a3f0770ef454 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 13:17:26 +0100 Subject: [PATCH 65/74] Fix fish completion --- .../FishShellCompletionDescriptor.php | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/ShellCompletion/FishShellCompletionDescriptor.php b/src/ShellCompletion/FishShellCompletionDescriptor.php index f0d269d7..e4b6cfe8 100644 --- a/src/ShellCompletion/FishShellCompletionDescriptor.php +++ b/src/ShellCompletion/FishShellCompletionDescriptor.php @@ -31,18 +31,19 @@ public function __construct() */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { + global $argv; $command = $options['command']; if (!$command instanceof CompletionAwareInterface) { return; } $this->output->write( - "complete -c pha -n '__fish_seen_subcommand_from " . $command->getName() . + "complete -c ' . $argv[0] . ' -n '__fish_seen_subcommand_from " . $command->getName() . "' -f" ); global $argv; $this->output->write( - " -a '(__fish_pha_get_arguments " . + " -a '(__fish_phab_get_arguments " . $command->getName() . ' ' . $argument->getName() . ")'" @@ -63,9 +64,10 @@ protected function describeInputArgument(InputArgument $argument, array $options */ protected function describeInputOption(InputOption $option, array $options = array()) { + global $argv; $command = $options['command']; $this->output->write( - "complete -c pha -n '__fish_seen_subcommand_from " . $command->getName() . + "complete -c ' . $argv[0] . ' -n '__fish_seen_subcommand_from " . $command->getName() . "' -f" ); @@ -91,7 +93,7 @@ protected function describeInputOption(InputOption $option, array $options = arr if ($command instanceof CompletionAwareInterface) { global $argv; $this->output->write( - "complete -c pha -n '__fish_seen_subcommand_from " . + "complete -c ' . $argv[0] . ' -n '__fish_seen_subcommand_from " . $command->getName() . " and __fish_seen_argument --" . $option->getName() . @@ -103,7 +105,7 @@ protected function describeInputOption(InputOption $option, array $options = arr } $this->output->writeln( - " -a '(__fish_pha_get_options " . + " -a '(__fish_phab_get_options " . $command->getName() . ' ' . $option->getName() . ")'" @@ -131,8 +133,10 @@ protected function describeInputDefinition(InputDefinition $definition, array $o */ protected function describeCommand(Command $command, array $options = array()) { + global $argv; + $this->output->writeln( - "complete -c pha -n '__fish_use_subcommand' -f -a " . + "complete -c ' . $argv[0] . ' -n '__fish_use_subcommand' -f -a " . $command->getName() . " -d '" . $command->getDescription() . @@ -156,15 +160,17 @@ protected function describeCommand(Command $command, array $options = array()) protected function describeApplication(Application $application, array $options = array()) { global $argv; - $this->output->writeln('complete -c pha -e'); - $this->output->writeln('function __fish_pha_get_options'); + $this->output->writeln('complete -c ' . $argv[0] . ' -e'); + $this->output->writeln('function __fish_phab_get_options'); $this->output->writeln(' set -l CMD (commandline -ocp)'); - $this->output->writeln( ' ' . $argv[0] . ' _completion --complete-command $argv[1] --complete-option $argv[2] --command-line "$CMD" '); + $this->output->writeln(' ' . $argv[0] . + ' _completion --complete-command $argv[1] --complete-option $argv[2] --command-line "$CMD" '); $this->output->writeln('end'); - $this->output->writeln('function __fish_pha_get_arguments'); + $this->output->writeln('function __fish_phab_get_arguments'); $this->output->writeln(' set -l CMD (commandline -ocp)'); - $this->output->writeln( ' ' . $argv[0] . ' _completion --complete-command $argv[1] --complete-argument $argv[2] --command-line "$CMD" '); + $this->output->writeln(' ' . $argv[0] . + ' _completion --complete-command $argv[1] --complete-argument $argv[2] --command-line "$CMD" '); $this->output->writeln('end'); From 8d04c8fd40a3527847560490e1bcb6fdbd70738c Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 14:50:18 +0100 Subject: [PATCH 66/74] Set version number, when not bundling as phar --- bin/phab | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/phab b/bin/phab index 43ce0d64..efb8efce 100755 --- a/bin/phab +++ b/bin/phab @@ -45,7 +45,11 @@ $output = $container->get(ConsoleOutput::class); /** @var Application $application */ $application = $container->get(Application::class); -$application->setVersion('@git_tag@'); +$version = '@git_tag@'; +if ($version[0] == '@') { + $version = '3.0.0'; +} +$application->setVersion($version); $application->setName('phabalicious'); $application->setDefaultCommand('list'); From 1207536c80289e82427f25e209926c46cb97b970 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 14:50:26 +0100 Subject: [PATCH 67/74] Update dependencies --- composer.lock | 354 +++++++++++++++++++++++++++++++++----------------- symfony.lock | 6 + 2 files changed, 241 insertions(+), 119 deletions(-) diff --git a/composer.lock b/composer.lock index f652681c..56bdcdd2 100644 --- a/composer.lock +++ b/composer.lock @@ -242,32 +242,33 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "9f83dded91781a01c63574e387eaa769be769115" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", "shasum": "" }, "require": { "php": ">=5.4.0", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" }, "provide": { "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -297,13 +298,14 @@ "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", "uri", "url" ], - "time": "2017-03-20T17:10:46+00:00" + "time": "2018-12-04T20:46:45+00:00" }, { "name": "jakeasmith/http_build_url", @@ -560,16 +562,16 @@ }, { "name": "psr/log", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { @@ -603,7 +605,47 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2018-11-20T15:27:04+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" }, { "name": "stecman/symfony-console-completion", @@ -652,16 +694,16 @@ }, { "name": "symfony/config", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238" + "reference": "005d9a083d03f588677d15391a716b1ac9b887c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238", - "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238", + "url": "https://api.github.com/repos/symfony/config/zipball/005d9a083d03f588677d15391a716b1ac9b887c0", + "reference": "005d9a083d03f588677d15391a716b1ac9b887c0", "shasum": "" }, "require": { @@ -684,7 +726,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -711,24 +753,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:09:42+00:00" + "time": "2018-11-30T22:21:14+00:00" }, { "name": "symfony/console", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "432122af37d8cd52fba1b294b11976e0d20df595" + "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595", - "reference": "432122af37d8cd52fba1b294b11976e0d20df595", + "url": "https://api.github.com/repos/symfony/console/zipball/4dff24e5d01e713818805c1862d2e3f901ee7dd0", + "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0", "shasum": "" }, "require": { "php": "^7.1.3", + "symfony/contracts": "^1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -752,7 +795,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -779,20 +822,88 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:30:44+00:00" + "time": "2018-11-27T07:40:44+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" }, { "name": "symfony/debug", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "19090917b848a799cbae4800abf740fe4eb71c1d" + "reference": "e0a2b92ee0b5b934f973d90c2f58e18af109d276" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/19090917b848a799cbae4800abf740fe4eb71c1d", - "reference": "19090917b848a799cbae4800abf740fe4eb71c1d", + "url": "https://api.github.com/repos/symfony/debug/zipball/e0a2b92ee0b5b934f973d90c2f58e18af109d276", + "reference": "e0a2b92ee0b5b934f973d90c2f58e18af109d276", "shasum": "" }, "require": { @@ -808,7 +919,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -835,37 +946,39 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:09:42+00:00" + "time": "2018-11-28T18:24:18+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483" + "reference": "e4adc57a48d3fa7f394edfffa9e954086d7740e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483", - "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e4adc57a48d3fa7f394edfffa9e954086d7740e5", + "reference": "e4adc57a48d3fa7f394edfffa9e954086d7740e5", "shasum": "" }, "require": { "php": "^7.1.3", - "psr/container": "^1.0" + "psr/container": "^1.0", + "symfony/contracts": "^1.0" }, "conflict": { - "symfony/config": "<4.1.1", + "symfony/config": "<4.2", "symfony/finder": "<3.4", "symfony/proxy-manager-bridge": "<3.4", "symfony/yaml": "<3.4" }, "provide": { - "psr/container-implementation": "1.0" + "psr/container-implementation": "1.0", + "symfony/service-contracts-implementation": "1.0" }, "require-dev": { - "symfony/config": "~4.1", + "symfony/config": "~4.2", "symfony/expression-language": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, @@ -879,7 +992,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -906,20 +1019,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2018-10-31T10:54:16+00:00" + "time": "2018-12-02T15:59:36+00:00" }, { "name": "symfony/dotenv", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "9f3074b55bc56627f61fb2c17d573ee7df8e1319" + "reference": "97f135ab40f969cbeae27d482ff63acbc33dbe2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/9f3074b55bc56627f61fb2c17d573ee7df8e1319", - "reference": "9f3074b55bc56627f61fb2c17d573ee7df8e1319", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/97f135ab40f969cbeae27d482ff63acbc33dbe2a", + "reference": "97f135ab40f969cbeae27d482ff63acbc33dbe2a", "shasum": "" }, "require": { @@ -931,7 +1044,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -963,24 +1076,25 @@ "env", "environment" ], - "time": "2018-10-12T12:56:03+00:00" + "time": "2018-11-26T10:55:26+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "552541dad078c85d9414b09c041ede488b456cd5" + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5", - "reference": "552541dad078c85d9414b09c041ede488b456cd5", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328", + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3", + "symfony/contracts": "^1.0" }, "conflict": { "symfony/dependency-injection": "<3.4" @@ -999,7 +1113,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1026,20 +1140,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-10-10T13:52:42+00:00" + "time": "2018-12-01T08:52:38+00:00" }, { "name": "symfony/filesystem", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981" + "reference": "2f4c8b999b3b7cadb2a69390b01af70886753710" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981", - "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/2f4c8b999b3b7cadb2a69390b01af70886753710", + "reference": "2f4c8b999b3b7cadb2a69390b01af70886753710", "shasum": "" }, "require": { @@ -1049,7 +1163,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1076,20 +1190,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-10-30T13:18:25+00:00" + "time": "2018-11-11T19:52:12+00:00" }, { "name": "symfony/finder", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1f17195b44543017a9c9b2d437c670627e96ad06" + "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1f17195b44543017a9c9b2d437c670627e96ad06", - "reference": "1f17195b44543017a9c9b2d437c670627e96ad06", + "url": "https://api.github.com/repos/symfony/finder/zipball/e53d477d7b5c4982d0e1bfd2298dbee63d01441d", + "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d", "shasum": "" }, "require": { @@ -1098,7 +1212,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1125,20 +1239,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-10-03T08:47:56+00:00" + "time": "2018-11-11T19:52:12+00:00" }, { "name": "symfony/flex", - "version": "v1.1.7", + "version": "v1.1.8", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "803c49664ddc7cbc4be02f41491766be32c90a7f" + "reference": "955774ecf07b10230bb5b44e150ba078b45f68fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/803c49664ddc7cbc4be02f41491766be32c90a7f", - "reference": "803c49664ddc7cbc4be02f41491766be32c90a7f", + "url": "https://api.github.com/repos/symfony/flex/zipball/955774ecf07b10230bb5b44e150ba078b45f68fa", + "reference": "955774ecf07b10230bb5b44e150ba078b45f68fa", "shasum": "" }, "require": { @@ -1172,20 +1286,20 @@ } ], "description": "Composer plugin for Symfony", - "time": "2018-11-12T12:25:13+00:00" + "time": "2018-11-15T06:11:38+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "82d494c1492b0dd24bbc5c2d963fb02eb44491af" + "reference": "1b31f3017fadd8cb05cf2c8aebdbf3b12a943851" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/82d494c1492b0dd24bbc5c2d963fb02eb44491af", - "reference": "82d494c1492b0dd24bbc5c2d963fb02eb44491af", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1b31f3017fadd8cb05cf2c8aebdbf3b12a943851", + "reference": "1b31f3017fadd8cb05cf2c8aebdbf3b12a943851", "shasum": "" }, "require": { @@ -1199,7 +1313,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1226,25 +1340,26 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-10-31T09:09:42+00:00" + "time": "2018-11-26T10:55:26+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "958be64ab13b65172ad646ef5ae20364c2305fae" + "reference": "b39ceffc0388232c309cbde3a7c3685f2ec0a624" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/958be64ab13b65172ad646ef5ae20364c2305fae", - "reference": "958be64ab13b65172ad646ef5ae20364c2305fae", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b39ceffc0388232c309cbde3a7c3685f2ec0a624", + "reference": "b39ceffc0388232c309cbde3a7c3685f2ec0a624", "shasum": "" }, "require": { "php": "^7.1.3", "psr/log": "~1.0", + "symfony/contracts": "^1.0.2", "symfony/debug": "~3.4|~4.0", "symfony/event-dispatcher": "~4.1", "symfony/http-foundation": "^4.1.1", @@ -1252,7 +1367,8 @@ }, "conflict": { "symfony/config": "<3.4", - "symfony/dependency-injection": "<4.1", + "symfony/dependency-injection": "<4.2", + "symfony/translation": "<4.2", "symfony/var-dumper": "<4.1.1", "twig/twig": "<1.34|<2.4,>=2" }, @@ -1265,7 +1381,7 @@ "symfony/config": "~3.4|~4.0", "symfony/console": "~3.4|~4.0", "symfony/css-selector": "~3.4|~4.0", - "symfony/dependency-injection": "^4.1", + "symfony/dependency-injection": "^4.2", "symfony/dom-crawler": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0", @@ -1273,7 +1389,7 @@ "symfony/routing": "~3.4|~4.0", "symfony/stopwatch": "~3.4|~4.0", "symfony/templating": "~3.4|~4.0", - "symfony/translation": "~3.4|~4.0", + "symfony/translation": "~4.2", "symfony/var-dumper": "^4.1.1" }, "suggest": { @@ -1286,7 +1402,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1313,7 +1429,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-11-03T11:11:23+00:00" + "time": "2018-12-06T17:39:52+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1434,16 +1550,16 @@ }, { "name": "symfony/process", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "3e83acef94d979b1de946599ef86b3a352abcdc9" + "reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/3e83acef94d979b1de946599ef86b3a352abcdc9", - "reference": "3e83acef94d979b1de946599ef86b3a352abcdc9", + "url": "https://api.github.com/repos/symfony/process/zipball/2b341009ccec76837a7f46f59641b431e4d4c2b0", + "reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0", "shasum": "" }, "require": { @@ -1452,7 +1568,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1479,20 +1595,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-10-14T20:48:13+00:00" + "time": "2018-11-20T16:22:05+00:00" }, { "name": "symfony/yaml", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "367e689b2fdc19965be435337b50bc8adf2746c9" + "reference": "c41175c801e3edfda90f32e292619d10c27103d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9", - "reference": "367e689b2fdc19965be435337b50bc8adf2746c9", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c41175c801e3edfda90f32e292619d10c27103d7", + "reference": "c41175c801e3edfda90f32e292619d10c27103d7", "shasum": "" }, "require": { @@ -1511,7 +1627,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -1538,7 +1654,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:36:10+00:00" + "time": "2018-11-11T19:52:12+00:00" }, { "name": "thibaud-dauce/mattermost-php", @@ -2369,16 +2485,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.4.3", + "version": "7.5.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c151651fb6ed264038d486ea262e243af72e5e64" + "reference": "520723129e2b3fc1dc4c0953e43c9d40e1ecb352" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c151651fb6ed264038d486ea262e243af72e5e64", - "reference": "c151651fb6ed264038d486ea262e243af72e5e64", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/520723129e2b3fc1dc4c0953e43c9d40e1ecb352", + "reference": "520723129e2b3fc1dc4c0953e43c9d40e1ecb352", "shasum": "" }, "require": { @@ -2399,7 +2515,7 @@ "phpunit/php-timer": "^2.0", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", - "sebastian/environment": "^3.1 || ^4.0", + "sebastian/environment": "^4.0", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", "sebastian/object-enumerator": "^3.0.3", @@ -2423,7 +2539,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.4-dev" + "dev-master": "7.5-dev" } }, "autoload": { @@ -2449,7 +2565,7 @@ "testing", "xunit" ], - "time": "2018-10-23T05:57:41+00:00" + "time": "2018-12-07T07:08:12+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -2618,28 +2734,28 @@ }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/febd209a219cea7b56ad799b30ebbea34b71eb8f", + "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^7.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2664,7 +2780,7 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "time": "2018-11-25T09:31:21+00:00" }, { "name": "sebastian/exporter", @@ -3016,16 +3132,16 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v4.1.7", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "2474c5d4a5e3431fee2f6f0dddde9d34983d9ceb" + "reference": "3f03b625710f24071e2937e88112e9a19099c9eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2474c5d4a5e3431fee2f6f0dddde9d34983d9ceb", - "reference": "2474c5d4a5e3431fee2f6f0dddde9d34983d9ceb", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/3f03b625710f24071e2937e88112e9a19099c9eb", + "reference": "3f03b625710f24071e2937e88112e9a19099c9eb", "shasum": "" }, "require": { @@ -3044,7 +3160,7 @@ "type": "symfony-bridge", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" }, "thanks": { "name": "phpunit/phpunit", @@ -3078,7 +3194,7 @@ ], "description": "Symfony PHPUnit Bridge", "homepage": "https://symfony.com", - "time": "2018-10-02T12:40:59+00:00" + "time": "2018-11-26T10:55:26+00:00" }, { "name": "theseer/tokenizer", diff --git a/symfony.lock b/symfony.lock index aed49cf6..87a344cf 100644 --- a/symfony.lock +++ b/symfony.lock @@ -80,6 +80,9 @@ "psr/log": { "version": "1.0.2" }, + "ralouphie/getallheaders": { + "version": "2.0.5" + }, "sebastian/code-unit-reverse-lookup": { "version": "1.0.1" }, @@ -128,6 +131,9 @@ "ref": "e3868d2f4a5104f19f844fe551099a00c6562527" } }, + "symfony/contracts": { + "version": "v1.0.2" + }, "symfony/debug": { "version": "v4.1.6" }, From 20b8bb1f8a0be9966707b7dd48ed1271b2f7d6cc Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 14:51:07 +0100 Subject: [PATCH 68/74] Fix fish autocompletion (sort of) --- .../FishShellCompletionDescriptor.php | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/ShellCompletion/FishShellCompletionDescriptor.php b/src/ShellCompletion/FishShellCompletionDescriptor.php index e4b6cfe8..e245c8bb 100644 --- a/src/ShellCompletion/FishShellCompletionDescriptor.php +++ b/src/ShellCompletion/FishShellCompletionDescriptor.php @@ -37,7 +37,7 @@ protected function describeInputArgument(InputArgument $argument, array $options return; } $this->output->write( - "complete -c ' . $argv[0] . ' -n '__fish_seen_subcommand_from " . $command->getName() . + "complete -c phab -n '__fish_seen_subcommand_from " . $command->getName() . "' -f" ); global $argv; @@ -67,7 +67,7 @@ protected function describeInputOption(InputOption $option, array $options = arr global $argv; $command = $options['command']; $this->output->write( - "complete -c ' . $argv[0] . ' -n '__fish_seen_subcommand_from " . $command->getName() . + "complete -c phab -n '__fish_seen_subcommand_from " . $command->getName() . "' -f" ); @@ -93,9 +93,9 @@ protected function describeInputOption(InputOption $option, array $options = arr if ($command instanceof CompletionAwareInterface) { global $argv; $this->output->write( - "complete -c ' . $argv[0] . ' -n '__fish_seen_subcommand_from " . + "complete -c phab -n '__fish_seen_subcommand_from " . $command->getName() . - " and __fish_seen_argument --" . + "; and __fish_phab_seen_argument -l " . $option->getName() . "' -f" ); @@ -136,7 +136,7 @@ protected function describeCommand(Command $command, array $options = array()) global $argv; $this->output->writeln( - "complete -c ' . $argv[0] . ' -n '__fish_use_subcommand' -f -a " . + "complete -c phab -n '__fish_use_subcommand' -f -a " . $command->getName() . " -d '" . $command->getDescription() . @@ -160,7 +160,7 @@ protected function describeCommand(Command $command, array $options = array()) protected function describeApplication(Application $application, array $options = array()) { global $argv; - $this->output->writeln('complete -c ' . $argv[0] . ' -e'); + $this->output->writeln('complete -c phab -e'); $this->output->writeln('function __fish_phab_get_options'); $this->output->writeln(' set -l CMD (commandline -ocp)'); $this->output->writeln(' ' . $argv[0] . @@ -172,7 +172,27 @@ protected function describeApplication(Application $application, array $options $this->output->writeln(' ' . $argv[0] . ' _completion --complete-command $argv[1] --complete-argument $argv[2] --command-line "$CMD" '); $this->output->writeln('end'); - + $this->output->writeln('function __fish_phab_seen_argument'); + $this->output->writeln(' argparse \'s/short=+\' \'l/long=+\' -- $argv'); + + $this->output->writeln(' set cmd (commandline -co)'); + $this->output->writeln(' set -e cmd[1]'); + $this->output->writeln(' for t in $cmd'); + $this->output->writeln(' for s in $_flag_s'); + $this->output->writeln(' if string match -qr "^-[A-z0-9]*"$s"[A-z0-9]*\$" -- $t'); + $this->output->writeln(' return 0'); + $this->output->writeln(' end'); + $this->output->writeln(' end'); + $this->output->writeln(''); + $this->output->writeln(' for l in $_flag_l'); + $this->output->writeln(' if string match -q -- "--$l" $t'); + $this->output->writeln(' return 0'); + $this->output->writeln(' end'); + $this->output->writeln(' end'); + $this->output->writeln(' end'); + $this->output->writeln(''); + $this->output->writeln(' return 1'); + $this->output->writeln('end'); $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); From ea84809358ff04b2e5ff924c75ff20ec1571b149 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 14:51:55 +0100 Subject: [PATCH 69/74] Remove fabfile --- .fabfile.yaml | 325 -------------------------------------------------- 1 file changed, 325 deletions(-) delete mode 100644 .fabfile.yaml diff --git a/.fabfile.yaml b/.fabfile.yaml deleted file mode 100644 index f6d0406e..00000000 --- a/.fabfile.yaml +++ /dev/null @@ -1,325 +0,0 @@ -name: bi-france -deploymentModule: bif_deploy - -requires: 2.0.0 -needs: - - ssh - - docker - - drush7 - - git - - files - -dockerKeyFile: ./ssh-keys/docker-root-key -dockerAuthorizedKeyFile: https://keys.factorial.io/keys/f5eca34f-f857-4e7b-829d-08f85244dd77 -dockerKnownHostsFile: ./ssh-keys/known_hosts - -# BI Repo. -# repository: https://stephan@bitbucket.bi-scrum.com/scm/fr012/site-code.git - -# Gitlab Repo. -repository: ssh://git@source.factorial.io:2222/BI/fr012/site-code.git - -inheritsFrom: - - https://config.factorial.io/docker/2.0/xdebug.yaml - - -excludeFiles: - backup: - - "styles" - - "tmp" - copyFrom: - - "tmp" - - "styles" - - "php" - - "js" - - "css" - - "twig_cache" - - "xmlsitemap" - -scripts: - behatInstall: - - cd %host.gitRootFolder% && composer install --ignore-platform-reqs - behat: - - fail_on_error(0) - - cd %host.gitRootFolder%.tools/behat && %host.gitRootFolder%/vendor/bin/behat %arguments.combined% - - fail_on_error(1) - copyHtAccess: - - cd %host.gitRootFolder% && cp .tools/htaccess .htaccess - reindex-content: - - cd %host.siteFolder% && drush solr-delete-index; drush solr-mark-all; drush solr-index; - patternlab: - - cd %host.rootFolder%/sites/all/themes/custom/bif_frontend && php core/console --generate - setSolrUrlForDev: - - "drush vset apachesolr_default_environment solr" - - > - drush vset apachesolr_environments - --format=json - '{"solr": {"url": "http://solr:8983/solr/mycore" } }' - resetAdminUser: - - cd %host.siteFolder%; drush sql-query "update users set name='admin' where uid=1" - -common: - resetPrepare: - dev: - - execute(script, resetAdminUser) - - copyDBFromFinished: - dev: - - execute(script, reindex-content) - stage: - - execute(script, reindex-content) - test: - - execute(script, reindex-content) - prod: - - execute(script, reindex-content) - - reset: - dev: - - "drush vset devel_rebuild_theme_registry FALSE" - - "drush vdel -y googleanalytics_account" - - "drush vset -y --exact cache 0" - - "drush vset -y --exact preprocess_css 0" - - "drush vset -y --exact preprocess_js 0" - - "drush en shield -y" - - "drush vset -y shield_user rmh" - - "drush vset -y shield_pass rmh" - - "drush vset -y shield_print 'Enter security credentials to access'" - - "drush vset admin_menu_tweak_modules 1" - - "drush vset admin_menu_tweak_permissions 1" - - execute(script, patternlab) - - execute(script, setSolrUrlForDev) - test: - - execute(script, patternlab) - prod: - - execute(script, patternlab) - -dockerHosts: - default: - tasks: - start: - - docker start %name% - stop: - - docker stop %name% - logs: - - docker logs %name% - ps: - - docker ps - mbb: - environment: - VHOST: "%host.docker.vhost%" - COMPOSE_FILE: "docker-compose.yml:docker-compose-mbb.yml" - inheritsFrom: - - https://config.factorial.io/mbb/2.0/mbb-docker.yaml - - https://config.factorial.io/docker/2.0/docker-compose.yaml - - clients.factorial.io: - environment: - VHOST: "%host.docker.vhost%" - inheritsFrom: - - https://config.factorial.io/clients.factorial.io/2.0/d8/docker.yaml - -hosts: - mbb: - adminUser: admin - host: bi-france.test - user: root - password: root - port: 36997 - type: dev - rootFolder: /var/www/ - gitRootFolder: /var/www/ - siteFolder: /sites/default - filesFolder: /sites/default/files - backupFolder: /var/www/backups - branch: int - supportsInstalls: true - scripts: - test: - - echo "Test" - - cd %host.rootFolder%; echo "hello" - test2: - - echo "Test2" - - execute(script, test) - docker: - name: fr012-bi-france_web_1 - configuration: mbb - vhost: >- - bi-france.test - cardiocity.bi-france.test - oncocity.bi-france.test - pneumocity.bi-france.test - spiolto.bi-france.test - pradaxa.bi-france.test - pradaxa-praxbind.bi-france.test - ofev-pharmacist.bi-france.test - ofev-pneumolog.bi-france.test - projectFolder: fr012-bi-france - database: - name: bifrance - user: root - pass: admin - host: mysql - reset: - - "drush vset -y error_level 2" - - "execute(script, copyHtAccess)" - - "drush vset -y file_public_path 'sites/default/files'" - - "drush vset -y file_private_path 'sites/default/files/private'" - - "drush vset -y file_temporary_path 'sites/default/files/private/tmp'" - xdebug: - php_version: 5 - blueprint: - database: - name: bifrance_%slug% - inheritsFrom: mbb - configName: "mbb-%slug%" - siteFolder: /sites/%slug% - filesFolder: /sites/%slug%/files - reset: - - drush vset -y error_level 2 - - execute(script, copyHtAccess) - - drush vset -y file_public_path 'sites/%slug%/files' - - drush vset -y file_private_path 'sites/%slug%/files/private' - - drush vset -y file_temporary_path 'sites/%slug%/files/private/tmp' - - bi-france-int: - port: 22 - branch: int - host: int-fr012.bi-customerhub.com - user: fr012d - type: stage - ignoreSubmodules: true - supportsInstalls: false - supportsCopyFrom: false - rootFolder: /home/fr012d/public_html - gitRootFolder: /home/fr012d/public_html - siteFolder: /sites/default - filesFolder: /sites/default/files - backupFolder: /home/fr012d/backups - gitOptions: - pull: [] - needs: - - ssh - - drush7 - - git - - files - - - bi-france-int-cardiocity: - # Do chmod -R 775 sites/fr012_j4x8/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_j4x8 - filesFolder: /sites/fr012_j4x8/files - - bi-france-int-pneumocity: - # Do chmod -R 775 sites/fr012_nnrs/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_nnrs - filesFolder: /sites/fr012_nnrs/files - - bi-france-int-oncocity: - # Do chmod -R 775 sites/fr012_5i2p/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_5i2p - filesFolder: /sites/fr012_5i2p/files - - bi-france-int-spiolto: - # Do chmod -R 775 sites/fr012_cwxy/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_cwxy - filesFolder: /sites/fr012_cwxy/files - - bi-france-int-ofev-pneumo: - # Do chmod -R 775 sites/fr012_ssd8/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_ssd8 - filesFolder: /sites/fr012_ssd8/files - - bi-france-int-ofev-pharma: - # Do chmod -R 775 sites/fr012_veuy/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_veuy - filesFolder: /sites/fr012_veuy/files - - bi-france-int-pradaxa: - # Do chmod -R 775 sites/fr012_e3zm/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_e3zm - filesFolder: /sites/fr012_e3zm/files - - bi-france-int-pradaxa-praxabind: - # Do chmod -R 775 sites/fr012_d3e5/files when doing first time install. - inheritsFrom: bi-france-int - siteFolder: /sites/fr012_d3e5 - filesFolder: /sites/fr012_d3e5/files - - int.bifrance.hub-staging.hh.rmh.de: - branch: int - configName: int.bifrance.hub-staging.hh.rmh.de - ignoreSubmodules: true - database: - name: bifrance_int_mysql - host: mysql - docker: - configuration: clients.factorial.io - name: bifrancemultisiteint_web_1 - projectFolder: bifrance-multisite--int - vhost: >- - int.bifrance.cardiocity.hub-staging.hh.rmh.de - int.bifrance.oncocity.hub-staging.hh.rmh.de - int.bifrance.pneumocity.hub-staging.hh.rmh.de - int.bifrance.spiolto.hub-staging.hh.rmh.de - int.bifrance.pradaxa.hub-staging.hh.rmh.de - int.bifrance.pradaxa-praxbind.hub-staging.hh.rmh.de - int.bifrance.ofev-pharmacist.hub-staging.hh.rmh.de - int.bifrance.ofev-pneumolog.hub-staging.hh.rmh.de - gitRootFolder: /var/www - inheritsFrom: http://config.factorial.io/clients.factorial.io/2.0/host.yaml - reset: - - "drush vset -y error_level 0" - - "execute(script, copyHtAccess)" - - "drush vset -y file_public_path 'sites/default/files'" - - "drush vset -y file_private_path 'sites/default/files/private'" - - "drush vset -y file_temporary_path 'sites/default/files/private/tmp'" - blueprint: - inheritsFrom: int.bifrance.hub-staging.hh.rmh.de - configName: int.bifrance.%slug%.hub-staging.hh.rmh.de - database: - name: bifrance%slug%_int_mysql - host: mysql - siteFolder: /sites/%slug% - filesFolder: /sites/%slug%/files - reset: - - "drush vset -y error_level 0" - - "execute(script, copyHtAccess)" - - "drush vset -y rmh_config_domain %slug%" - - "drush vset -y file_public_path 'sites/%slug%/files'" - - "drush vset -y file_private_path 'sites/%slug%/files/private'" - - "drush vset -y file_temporary_path 'sites/%slug%/files/private/tmp'" - -blueprints: - - configName: mbb - variants: - - pneumocity - - spiolto - - pradaxapraxbind - - cardiocity - - oncocity - - pradaxa - - ofevpharmacist - - ofevpneumolog - - configName: int.bifrance.hub-staging.hh.rmh.de - variants: - - pneumocity - - spiolto - - pradaxapraxbind - - cardiocity - - oncocity - - pradaxa - - ofevpharmacist - - ofevpneumolog - - -# Currently installed: -# Url : http://int.bifrance.pneumocity.hub-staging.hh.rmh.de/ -# Url : http://int.bifrance.spiolto.hub-staging.hh.rmh.de/ -# Url : http://int.bifrance.pradaxa-praxbind.hub-staging.hh.rmh.de/ From ab7f8d364787dc19fc335e062abb7e5fa7f17028 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 14:55:42 +0100 Subject: [PATCH 70/74] Add docs for shell-autcompletion --- readme.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/readme.md b/readme.md index 5cc689d4..d69e26d7 100644 --- a/readme.md +++ b/readme.md @@ -27,6 +27,18 @@ You'll need [box](https://github.com/humbug/box) for building the phar-file. * Run `phab list` to get a list of all available commands. * run `phab help ` to get some help for a given command. +## Shell autocompletion + +Add this to your shell-startup script: + +* for fish-shells + + phab _completion --generate-hook --shell-type fish | source + + * for zsh/bash-shells + + source <(phab _completion --generate-hook) + ## Updating phab * Run `phab self-update`, this will download the latest release from GitHub. From 5562e560f5568374b7735cf982d9a468d329c150 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 9 Dec 2018 14:58:35 +0100 Subject: [PATCH 71/74] Fix formatting --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d69e26d7..08b7904e 100644 --- a/readme.md +++ b/readme.md @@ -35,7 +35,7 @@ Add this to your shell-startup script: phab _completion --generate-hook --shell-type fish | source - * for zsh/bash-shells +* for zsh/bash-shells source <(phab _completion --generate-hook) From 842489b2de59a86427821931613469e9393452bb Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Mon, 10 Dec 2018 18:17:10 +0100 Subject: [PATCH 72/74] Nicer output --- src/Method/DockerMethod.php | 6 ++++-- src/Method/ScriptMethod.php | 6 ++---- src/Method/TaskContext.php | 16 +++++++++++++++- src/Method/TaskContextInterface.php | 7 +++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Method/DockerMethod.php b/src/Method/DockerMethod.php index 6120849d..cf61ba60 100644 --- a/src/Method/DockerMethod.php +++ b/src/Method/DockerMethod.php @@ -108,6 +108,8 @@ public function docker(HostConfig $host_config, TaskContextInterface $context) $this->runTaskImpl($host_config, $context, $task . 'Prepare', true); $this->runTaskImpl($host_config, $context, $task, false); $this->runTaskImpl($host_config, $context, $task . 'Finished', true); + + $context->getStyle()->success(sprintf('Task `%s` executed successfully!', $task)); } /** @@ -213,7 +215,7 @@ public function waitForServices(HostConfig $hostconfig, TaskContextInterface $co $this->logger->notice('Error running supervisorctl, check the logs'); } if ($result->getExitCode() == 0 && ($count_running == $count_services)) { - $this->logger->notice('Services up and running!'); + $context->getStyle()->comment('Services up and running!'); return; } $tries++; @@ -297,6 +299,7 @@ private function copySSHKeys(HostConfig $hostconfig, TaskContextInterface $conte $shell->run(sprintf('#!docker cp %s %s:%s', $temp_file, $container_name, $dest)); $shell->run(sprintf('#!docker exec %s #!chmod %s %s', $container_name, $data['permissions'], $dest)); $shell->run(sprintf('rm %s', $temp_file)); + $context->getStyle()->comment(sprintf('Handled %s successfully!', $dest)); } $shell->run(sprintf('#!docker exec %s #!chmod 700 /root/.ssh', $container_name)); $shell->run(sprintf('#!docker exec %s #!chown -R root /root/.ssh', $container_name)); @@ -487,5 +490,4 @@ private function getDockerContainerName(HostConfig $host_config, TaskContextInte )); } } - } diff --git a/src/Method/ScriptMethod.php b/src/Method/ScriptMethod.php index 41772198..d95da6ab 100644 --- a/src/Method/ScriptMethod.php +++ b/src/Method/ScriptMethod.php @@ -97,8 +97,7 @@ public function runScript(HostConfig $host_config, TaskContextInterface $context $context->setResult('exitCode', $result ? $result->getExitCode() : 0); } catch (UnknownReplacementPatternException $e) { - $context->getOutput() - ->writeln('Unknown replacement in line ' . $e->getOffendingLine() . ''); + $context->getStyle()->error('Unknown replacement in line ' . $e->getOffendingLine()); $printed_replacements = array_map(function ($key) use ($replacements) { $value = $replacements[$key]; @@ -107,8 +106,7 @@ public function runScript(HostConfig $host_config, TaskContextInterface $context } return [$key, $value]; }, array_keys($replacements)); - $style = new SymfonyStyle($context->getInput(), $context->getOutput()); - $style->table(['Key', 'Replacement'], $printed_replacements); + $context->getStyle()->table(['Key', 'Replacement'], $printed_replacements); } } diff --git a/src/Method/TaskContext.php b/src/Method/TaskContext.php index b40dba29..1ec438cc 100644 --- a/src/Method/TaskContext.php +++ b/src/Method/TaskContext.php @@ -14,6 +14,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; class TaskContext implements TaskContextInterface @@ -36,6 +37,8 @@ class TaskContext implements TaskContextInterface private $passwordManager; + private $io; + public function __construct(BaseOptionsCommand $command, InputInterface $input, OutputInterface $output) { $this->setInput($input); @@ -166,4 +169,15 @@ public function getPasswordManager() return $this->passwordManager; } -} \ No newline at end of file + + /** + * @return SymfonyStyle + */ + public function getStyle() + { + if (!$this->io) { + $this->io = new SymfonyStyle($this->getInput(), $this->getOutput()); + } + return $this->io; + } +} diff --git a/src/Method/TaskContextInterface.php b/src/Method/TaskContextInterface.php index 512150d4..6d41c239 100644 --- a/src/Method/TaskContextInterface.php +++ b/src/Method/TaskContextInterface.php @@ -10,6 +10,7 @@ use Phabalicious\Utilities\PasswordManagerInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; interface TaskContextInterface { @@ -63,6 +64,8 @@ public function askQuestion(string $string); */ public function getPasswordManager(); - + /** + * @return SymfonyStyle + */ + public function getStyle(); } - From b9f20e00e68088b3ed8195dfd19de1fa6b6b7446 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 11 Dec 2018 13:19:51 +0100 Subject: [PATCH 73/74] Some bugfixes for ftp-deployments --- src/Command/BackupCommand.php | 16 ++++++++++------ src/Method/FtpSyncMethod.php | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Command/BackupCommand.php b/src/Command/BackupCommand.php index 2d5ab800..c8a0ac55 100644 --- a/src/Command/BackupCommand.php +++ b/src/Command/BackupCommand.php @@ -64,12 +64,16 @@ protected function execute(InputInterface $input, OutputInterface $output) $files = $context->getResult('files', []); - $io = new SymfonyStyle($input, $output); - $io->title('Created backup files'); - $io->table( - ['Type', 'File'], - $files - ); + if (count($files)) { + $io = new SymfonyStyle($input, $output); + $io->title('Created backup files'); + $io->table( + ['Type', 'File'], + $files + ); + + $context->getStyle()->success('Backups created successfully!'); + } return $context->getResult('exitCode', 0); } diff --git a/src/Method/FtpSyncMethod.php b/src/Method/FtpSyncMethod.php index 91b525b3..5285028e 100644 --- a/src/Method/FtpSyncMethod.php +++ b/src/Method/FtpSyncMethod.php @@ -128,7 +128,7 @@ protected function createAppCode( 'installFolder' => $install_dir ]); $context->set('rootFolder', $install_dir); - $script_method->runTaskSpecificScripts($host_config, 'deploy', $context); + $script_method->runTaskSpecificScripts($cloned_host_config, 'deploy', $context); $context->setResult('skipResetStep', true); } From c4d44565ddc6a78449f5a065e18fa0147da39412 Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Tue, 11 Dec 2018 14:42:36 +0100 Subject: [PATCH 74/74] Update changelog --- Changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Changelog.md b/Changelog.md index bb842c66..314935c9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ # Changelog +## 3.0.0-alpha.6 / 2018-12-11 + + * Some bugfixes for ftp-deployments + * Nicer output + * Add docs for shell-autcompletion + * Fix fish autocompletion (sort of) + * Set version number, when not bundling as phar + ## 3.0.0-alpha.5 / 2018-12-08 ### fixed