Hello community, here is the log from the commit of package platformsh-cli for openSUSE:Factory checked in at 2017-12-22 12:20:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/platformsh-cli (Old) and /work/SRC/openSUSE:Factory/.platformsh-cli.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "platformsh-cli" Fri Dec 22 12:20:48 2017 rev:29 rq:559101 version:3.26.0 Changes: -------- --- /work/SRC/openSUSE:Factory/platformsh-cli/platformsh-cli.changes 2017-12-18 08:58:31.993622083 +0100 +++ /work/SRC/openSUSE:Factory/.platformsh-cli.new/platformsh-cli.changes 2017-12-22 12:21:27.204147020 +0100 @@ -1,0 +2,26 @@ +Thu Dec 21 13:35:07 UTC 2017 - [email protected] + +- Update to version 3.26.0: + * Release v3.26.0 + * Remove extra quotes from git changelog + * Fix config normalization when there is an empty locations array + * Skip updates check if the Phar file is not writable + * Remove different coloration for local commands (there are so few listed) + * Recommend --no-wait if snapshot:create is run in a non-TTY + * Support remote envs in app:list + * Remove unused LocalApplication::getApplication() + * Suggest project:set-remote in RootNotFoundException + * Add app names from cached SSH URLs for autocompletion + * Refactor to dedupe getDocumentRoot() methods + * Update CHANGELOG.md for v3.25.1 + * Generate changelog based on master + * Show worker commands + * Use PLATFORM_DOCUMENT_ROOT if available + * Cache the current deployment + * Add worker:list command + * Use deployments API for remote app information + * Auto-ensure webhooks on GitHub and GitLab integrations (#665) + * Be stricter about when to use $_ENV, when getting parent variables for PHP <7.1 + * The default CWD for a Git repository should be null, not . + +------------------------------------------------------------------- Old: ---- platformsh-cli-3.25.1.tar.xz New: ---- platformsh-cli-3.26.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ platformsh-cli.spec ++++++ --- /var/tmp/diff_new_pack.n7vHab/_old 2017-12-22 12:21:28.164100213 +0100 +++ /var/tmp/diff_new_pack.n7vHab/_new 2017-12-22 12:21:28.168100018 +0100 @@ -17,7 +17,7 @@ Name: platformsh-cli -Version: 3.25.1 +Version: 3.26.0 Release: 0 Summary: Tool for managing Platform.sh services from the command line # See licenses.txt for dependency licenses. ++++++ _service ++++++ --- /var/tmp/diff_new_pack.n7vHab/_old 2017-12-22 12:21:28.204098262 +0100 +++ /var/tmp/diff_new_pack.n7vHab/_new 2017-12-22 12:21:28.204098262 +0100 @@ -2,7 +2,7 @@ <service name="tar_scm" mode="disabled"> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> - <param name="revision">refs/tags/v3.25.1</param> + <param name="revision">refs/tags/v3.26.0</param> <param name="url">git://github.com/platformsh/platformsh-cli.git</param> <param name="scm">git</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.n7vHab/_old 2017-12-22 12:21:28.224097287 +0100 +++ /var/tmp/diff_new_pack.n7vHab/_new 2017-12-22 12:21:28.224097287 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">git://github.com/platformsh/platformsh-cli.git</param> - <param name="changesrevision">86aa5331daf2797f9c9fdcacf5fa3b2843fe65f1</param> + <param name="changesrevision">c610714bfa603427bd701b12eedb8e1d6be0f75f</param> </service> </servicedata> ++++++ licenses.txt ++++++ --- /var/tmp/diff_new_pack.n7vHab/_old 2017-12-22 12:21:28.264095337 +0100 +++ /var/tmp/diff_new_pack.n7vHab/_new 2017-12-22 12:21:28.264095337 +0100 @@ -15,7 +15,7 @@ guzzlehttp/streams 3.0.0 MIT padraic/humbug_get_contents 1.0.4 BSD-3-Clause padraic/phar-updater 1.0.4 BSD-3-Clause -platformsh/client v0.13.7 MIT +platformsh/client v0.14.0 MIT platformsh/console-form v0.0.15 MIT psr/container 1.0.0 MIT psr/log 1.0.2 MIT ++++++ platformsh-cli-3.25.1.tar.xz -> platformsh-cli-3.26.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/CHANGELOG.md new/platformsh-cli-3.26.0/CHANGELOG.md --- old/platformsh-cli-3.25.1/CHANGELOG.md 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/CHANGELOG.md 2017-12-21 12:52:01.000000000 +0100 @@ -4,9 +4,19 @@ More readable, curated release notes can be found at: https://github.com/platformsh/platformsh-cli/releases -## [Unreleased](https://github.com/platformsh/platformsh-cli/tree/HEAD) +## [v3.25.1](https://github.com/platformsh/platformsh-cli/tree/v3.25.1) (2017-12-14) +[Full Changelog](https://github.com/platformsh/platformsh-cli/compare/v3.25.0...v3.25.1) -[Full Changelog](https://github.com/platformsh/platformsh-cli/compare/v3.24.1...HEAD) +**Closed issues:** + +- RuntimeException: The provided cwd does not exist [\#664](https://github.com/platformsh/platformsh-cli/issues/664) + +## [v3.25.0](https://github.com/platformsh/platformsh-cli/tree/v3.25.0) (2017-12-13) +[Full Changelog](https://github.com/platformsh/platformsh-cli/compare/v3.24.1...v3.25.0) + +**Closed issues:** + +- Support for drush 9.0.0-rc1 \(changed alias file naming convention again\) [\#655](https://github.com/platformsh/platformsh-cli/issues/655) **Merged pull requests:** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/composer.json new/platformsh-cli-3.26.0/composer.json --- old/platformsh-cli-3.25.1/composer.json 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/composer.json 2017-12-21 12:52:01.000000000 +0100 @@ -8,7 +8,7 @@ "guzzlehttp/guzzle": "^5.3", "guzzlehttp/ringphp": "^1.1", "platformsh/console-form": ">=0.0.14 <2.0", - "platformsh/client": ">=0.13.7 <2.0", + "platformsh/client": ">=0.14.0 <2.0", "symfony/console": "^3.0 !=3.2.5 !=3.2.6", "symfony/yaml": "^3.0 || ^2.6", "symfony/finder": "^3.0", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/composer.lock new/platformsh-cli-3.26.0/composer.lock --- old/platformsh-cli-3.25.1/composer.lock 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/composer.lock 2017-12-21 12:52:01.000000000 +0100 @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "c5179c347a499d3085bc709d941b45e9", + "content-hash": "00feafcacf6d78fd54fd285c9da507b1", "packages": [ { "name": "cocur/slugify", @@ -594,16 +594,16 @@ }, { "name": "platformsh/client", - "version": "v0.13.7", + "version": "v0.14.0", "source": { "type": "git", "url": "https://github.com/platformsh/platformsh-client-php.git", - "reference": "62f990120e9c8dd386aca1abcd0fe2e92e1a1b43" + "reference": "47013df77c5ac9d1cea32fd4caa3999ecca150ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/62f990120e9c8dd386aca1abcd0fe2e92e1a1b43", - "reference": "62f990120e9c8dd386aca1abcd0fe2e92e1a1b43", + "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/47013df77c5ac9d1cea32fd4caa3999ecca150ca", + "reference": "47013df77c5ac9d1cea32fd4caa3999ecca150ca", "shasum": "" }, "require": { @@ -639,7 +639,7 @@ } ], "description": "Platform.sh API client", - "time": "2017-12-12T16:46:08+00:00" + "time": "2017-12-20T12:45:06+00:00" }, { "name": "platformsh/console-form", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/config.yaml new/platformsh-cli-3.26.0/config.yaml --- old/platformsh-cli-3.25.1/config.yaml 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/config.yaml 2017-12-21 12:52:01.000000000 +0100 @@ -1,7 +1,7 @@ # Metadata about the CLI application itself. application: name: 'Platform.sh CLI' - version: '3.25.1' + version: '3.26.0' executable: 'platform' package_name: 'platformsh/cli' installer_url: 'https://platform.sh/cli/installer' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/dist/manifest.json new/platformsh-cli-3.26.0/dist/manifest.json --- old/platformsh-cli-3.25.1/dist/manifest.json 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/dist/manifest.json 2017-12-21 12:52:01.000000000 +0100 @@ -1,10 +1,10 @@ [ { "name": "platform.phar", - "sha1": "f9db4be41db6d96d8163603c4d8083168e1e472f", - "sha256": "aa8c294dcb85e16b5382407d162e22008f8a574acb186f29d7277d24232526c7", - "url": "https://github.com/platformsh/platformsh-cli/releases/download/v3.25.1/platform.phar", - "version": "3.25.1", + "sha1": "b5ec20dec29842693d000adefd64e46abb2bdc56", + "sha256": "8343ce8235535f2c388a5ed0f0a321debc9a1838fd53c006c75445b2e099cbe9", + "url": "https://github.com/platformsh/platformsh-cli/releases/download/v3.26.0/platform.phar", + "version": "3.26.0", "php": { "min": "5.5.9" }, @@ -88,6 +88,11 @@ "notes": "* Extends interactive question text in `integration:add` command, to clarify the meaning of options, their defaults, and their syntax\n* Adds support for the \"Enabled\" (`is_enabled`) flag on environment variables.\n* Adds `--no-expired` and `--only-expired` options to `certificate:list`\n* Improves the \"project not found\" message, to suggest other project IDs\n* Implements omitting non-required empty fields when adding an integration (allows earlier support for new integration options without breaking older projects)\n* Adds the SSH_AGENT_PID to auto inherited environment variables (fixes using an SSH agent to manage keys when used with the CLI's Git commands)\n* Adds an experimental `redis` command to connect to a Redis container (hidden from the command list for now)\n* Adds experimental OS X Keychain support (enabled via `experimental.use_keychain`)", "show from": "3.24.0", "hide from": "3.25.0" + }, + { + "notes": "New features:\n* Support remote projects/environments in app:list command.\n* Add worker:list (workers) command.\n* Use \"deployments\" HTTP API (instead of SSH) in app:config command.\n* Auto-ensure webhooks on GitHub and GitLab integrations, where possible.\n\nOther changes:\n* Skip updates check if the Phar file is not writable.\n* Remove different coloration for local commands in `list` (there are so few listed).\n* Recommend --no-wait if snapshot:create is run in a non-TTY.\n* Suggest project:set-remote in RootNotFoundException.\n* Fix environment:drush (drush) command to use configured document root, or PLATFORM_DOCUMENT_ROOT where available.\n* Be stricter about when to use $_ENV, when getting parent variables for PHP <7.1.", + "show from": "v3.26.0", + "hide from": "v3.27.0" } ] }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Application.php new/platformsh-cli-3.26.0/src/Application.php --- old/platformsh-cli-3.25.1/src/Application.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Application.php 2017-12-21 12:52:01.000000000 +0100 @@ -181,6 +181,7 @@ $commands[] = new Command\Variable\VariableSetCommand(); $commands[] = new Command\WelcomeCommand(); $commands[] = new Command\WebCommand(); + $commands[] = new Command\Worker\WorkerListCommand(); return $commands; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/App/AppConfigGetCommand.php new/platformsh-cli-3.26.0/src/Command/App/AppConfigGetCommand.php --- old/platformsh-cli-3.25.1/src/Command/App/AppConfigGetCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/App/AppConfigGetCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -2,7 +2,6 @@ namespace Platformsh\Cli\Command\App; use Platformsh\Cli\Command\CommandBase; -use Platformsh\Cli\Service\Ssh; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -22,7 +21,7 @@ $this->addProjectOption(); $this->addEnvironmentOption(); $this->addAppOption(); - Ssh::configureInput($this->getDefinition()); + $this->addOption('identity-file', 'i', InputOption::VALUE_REQUIRED, '[Deprecated option, no longer used]'); } /** @@ -31,15 +30,12 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); + $this->warnAboutDeprecatedOptions(['identity-file']); - /** @var \Platformsh\Cli\Service\RemoteEnvVars $envVarService */ - $envVarService = $this->getService('remote_env_vars'); - - $sshUrl = $this->getSelectedEnvironment() - ->getSshUrl($this->selectApp($input)); - - $result = $envVarService->getEnvVar('APPLICATION', $sshUrl, $input->getOption('refresh')); - $appConfig = json_decode(base64_decode($result), true); + $appConfig = $this->api() + ->getCurrentDeployment($this->getSelectedEnvironment(), $input->getOption('refresh')) + ->getWebApp($this->selectApp($input)) + ->getProperties(); /** @var \Platformsh\Cli\Service\PropertyFormatter $formatter */ $formatter = $this->getService('property_formatter'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/App/AppListCommand.php new/platformsh-cli-3.26.0/src/Command/App/AppListCommand.php --- old/platformsh-cli-3.25.1/src/Command/App/AppListCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/App/AppListCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -2,15 +2,14 @@ namespace Platformsh\Cli\Command\App; use Platformsh\Cli\Command\CommandBase; -use Platformsh\Cli\Exception\RootNotFoundException; use Platformsh\Cli\Local\LocalApplication; use Platformsh\Cli\Service\Table; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class AppListCommand extends CommandBase { - protected $local = true; /** * {@inheritdoc} @@ -19,7 +18,10 @@ { $this->setName('app:list') ->setAliases(['apps']) - ->setDescription('Get a list of all apps in the local repository'); + ->setDescription('List apps in the project') + ->addOption('refresh', null, InputOption::VALUE_NONE, 'Whether to refresh the cache'); + $this->addProjectOption() + ->addEnvironmentOption(); Table::configureInput($this->getDefinition()); } @@ -28,21 +30,51 @@ */ protected function execute(InputInterface $input, OutputInterface $output) { - if (!$projectRoot = $this->getProjectRoot()) { - throw new RootNotFoundException(); - } + $this->validateInput($input); - $apps = LocalApplication::getApplications($projectRoot, $this->config()); + // Find a list of deployed web apps. + $apps = $this->api() + ->getCurrentDeployment($this->getSelectedEnvironment(), $input->getOption('refresh')) + ->webapps; + + // Determine whether to show the "Local path" of the app. This will be + // found via matching the remote, deployed app with one in the local + // project. + // @todo The "Local path" column is mainly here for legacy reasons, and can be removed in a future version. + $showLocalPath = false; + $localApps = []; + if (($projectRoot = $this->getProjectRoot()) && $this->selectedProjectIsCurrent()) { + $localApps = LocalApplication::getApplications($projectRoot, $this->config()); + $showLocalPath = true; + } + // Get the local path for a given application. + $getLocalPath = function ($appName) use ($localApps) { + foreach ($localApps as $localApp) { + if ($localApp->getName() === $appName) { + return $localApp->getRoot(); + break; + } + } + + return ''; + }; + + $headers = ['Name', 'Type']; + if ($showLocalPath) { + $headers[] = 'Path'; + } $rows = []; foreach ($apps as $app) { - $config = $app->getConfig(); - $type = isset($config['type']) ? $config['type'] : null; - $rows[] = [$app->getName(), $type, $app->getRoot()]; + $row = [$app->name, $app->type]; + if ($showLocalPath) { + $row[] = $getLocalPath($app->name); + } + $rows[] = $row; } /** @var \Platformsh\Cli\Service\Table $table */ $table = $this->getService('table'); - $table->render($rows, ['Name', 'Type', 'Path']); + $table->render($rows, $headers); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/CommandBase.php new/platformsh-cli-3.26.0/src/Command/CommandBase.php --- old/platformsh-cli-3.25.1/src/Command/CommandBase.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/CommandBase.php 2017-12-21 12:52:01.000000000 +0100 @@ -610,7 +610,7 @@ if (!$project) { throw new RootNotFoundException( "Could not determine the current project." - . "\nSpecify it manually using --project or go to a project directory." + . "\n\nSpecify it using --project, or go to a project directory." ); } } @@ -1001,8 +1001,41 @@ */ protected function debug($message) { + $this->labeledMessage('DEBUG', $message, OutputInterface::VERBOSITY_DEBUG); + } + + /** + * Print a warning about an deprecated option. + * + * @param string[] $options + */ + protected function warnAboutDeprecatedOptions(array $options) + { + if (!isset($this->input)) { + return; + } + foreach ($options as $option) { + if ($this->input->hasOption($option) && $this->input->getOption($option)) { + $this->labeledMessage( + 'DEPRECATED', + 'The option --' . $option . ' is deprecated and no longer used. It will be removed in a future version.', + OutputInterface::VERBOSITY_VERBOSE + ); + } + } + } + + /** + * Print a message with a label. + * + * @param string $label + * @param string $message + * @param int $options + */ + private function labeledMessage($label, $message, $options = 0) + { if (isset($this->stdErr)) { - $this->stdErr->writeln('<options=reverse>DEBUG</> ' . $message, OutputInterface::VERBOSITY_DEBUG); + $this->stdErr->writeln('<options=reverse>' . strtoupper($label) . '</> ' . $message, $options); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/CompletionCommand.php new/platformsh-cli-3.26.0/src/Command/CompletionCommand.php --- old/platformsh-cli-3.25.1/src/Command/CompletionCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/CompletionCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -230,6 +230,10 @@ $apps[] = $name; } } + } elseif ($project = $this->getProject()) { + if ($environment = $this->api->getEnvironment('master', $project, false)) { + $apps = array_keys($environment->getSshUrls()); + } } return $apps; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Environment/EnvironmentDrushCommand.php new/platformsh-cli-3.26.0/src/Command/Environment/EnvironmentDrushCommand.php --- old/platformsh-cli-3.25.1/src/Command/Environment/EnvironmentDrushCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Environment/EnvironmentDrushCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -2,8 +2,8 @@ namespace Platformsh\Cli\Command\Environment; use Platformsh\Cli\Command\CommandBase; -use Platformsh\Cli\Local\LocalApplication; use Platformsh\Cli\Local\BuildFlavor\Drupal; +use Platformsh\Cli\Model\AppConfig; use Platformsh\Cli\Service\Ssh; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -66,26 +66,18 @@ $selectedEnvironment = $this->getSelectedEnvironment(); $sshUrl = $selectedEnvironment->getSshUrl($appName); - // Get the LocalApplication object for the specified application, if - // available. - $projectRoot = $this->getProjectRoot(); - if ($projectRoot && $this->selectedProjectIsCurrent()) { - $app = LocalApplication::getApplication($appName, $projectRoot, $this->config()); - } - - // Use the local application configuration (if available) to determine - // the correct Drupal root. - if (isset($app)) { - $drupalRoot = '/app/' . $app->getDocumentRoot(); - } else { - // Fall back to the PLATFORM_DOCUMENT_ROOT environment variable, - // which is usually correct, except where the document_root was - // specified as '/'. - $documentRootEnvVar = $this->config()->get('service.env_prefix') . 'DOCUMENT_ROOT'; - $drupalRoot = '${' . $documentRootEnvVar . ':-/app/public}'; - - $this->debug('<comment>Warning:</comment> using $' . $documentRootEnvVar . ' for the Drupal root. This fails in cases where the document_root is /.'); - } + // Get the document root for the application, to find the Drupal root. + $remoteApp = $this->api() + ->getCurrentDeployment($selectedEnvironment) + ->getWebApp($appName); + $relativeDocRoot = AppConfig::fromWebApp($remoteApp)->getDocumentRoot(); + + // Use the PLATFORM_DOCUMENT_ROOT environment variable, if set, to + // determine the path to Drupal. Fall back to a combination of the known + // document root and the PLATFORM_APP_DIR variable. + $envPrefix = (string) $this->config()->get('service.env_prefix'); + $appRoot = sprintf('${%sAPP_DIR:-/app}', $envPrefix); + $drupalRoot = sprintf('${%sDOCUMENT_ROOT:-%s}', $envPrefix, $appRoot . '/' . $relativeDocRoot); $columns = (new Terminal())->getWidth(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Integration/IntegrationAddCommand.php new/platformsh-cli-3.26.0/src/Command/Integration/IntegrationAddCommand.php --- old/platformsh-cli-3.25.1/src/Command/Integration/IntegrationAddCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Integration/IntegrationAddCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -49,6 +49,8 @@ /** @var Integration $integration */ $integration = $result->getEntity(); + $this->ensureHooks($integration); + $this->stdErr->writeln("Created integration <info>$integration->id</info> (type: {$values['type']})"); $success = true; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Integration/IntegrationCommandBase.php new/platformsh-cli-3.26.0/src/Command/Integration/IntegrationCommandBase.php --- old/platformsh-cli-3.25.1/src/Command/Integration/IntegrationCommandBase.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Integration/IntegrationCommandBase.php 2017-12-21 12:52:01.000000000 +0100 @@ -1,6 +1,7 @@ <?php namespace Platformsh\Cli\Command\Integration; +use GuzzleHttp\Exception\TransferException; use Platformsh\Cli\Command\CommandBase; use Platformsh\Client\Model\Integration; use Platformsh\ConsoleForm\Field\ArrayField; @@ -238,6 +239,96 @@ } /** + * @param \Platformsh\Client\Model\Integration $integration + */ + protected function ensureHooks(Integration $integration) + { + if ($integration->type === 'github') { + $hooksApiUrl = sprintf('https://api.github.com/repos/%s/hooks', $integration->getProperty('repository')); + $requestOptions = [ + 'auth' => false, + 'headers' => [ + 'Accept' => 'application/vnd.github.v3+json', + 'Authorization' => 'token ' . $integration->getProperty('token'), + ], + ]; + $payload = [ + 'name' => 'web', + 'config' => [ + 'url' => $integration->getLink('#hook'), + 'content_type' => 'json', + ], + 'events' => ['*'], + 'active' => true, + ]; + $repoName = $integration->getProperty('repository'); + } elseif ($integration->type === 'gitlab') { + $baseUrl = rtrim($integration->getProperty('base_url'), '/'); + $hooksApiUrl = sprintf('%s/api/v4/projects/%s/hooks', $baseUrl, rawurlencode($integration->getProperty('project'))); + $requestOptions = [ + 'auth' => false, + 'headers' => [ + 'Accept' => 'application/json', + 'Private-Token' => $integration->getProperty('token'), + ], + ]; + $payload = ['url' => $integration->getLink('#hook')]; + $repoName = $baseUrl . '/' . $integration->getProperty('project'); + } else { + return; + } + + $client = $this->api()->getHttpClient(); + + $this->stdErr->writeln(sprintf( + 'Checking webhook configuration on the repository: <info>%s</info>', + $repoName + )); + + try { + $hooks = $client->get($hooksApiUrl, $requestOptions)->json(); + if ($this->findWebHook($integration, $hooks)) { + $this->stdErr->writeln(' Valid configuration found'); + } else { + $this->stdErr->writeln(' Creating new webhook'); + $client->post($hooksApiUrl, ['json' => $payload] + $requestOptions); + } + } catch (TransferException $e) { + $this->stdErr->writeln(''); + $this->stdErr->writeln(' <comment>Failed to read or write webhooks:</comment>'); + $this->stdErr->writeln(' ' . $e->getMessage()); + $this->stdErr->writeln(sprintf( + "\n Please ensure a webhook exists manually.\n Hook URL: %s", + $integration->getLink('#hook') + )); + } + } + + /** + * Find if a valid webhook exists in a service's hooks list. + * + * @param \Platformsh\Client\Model\Integration $integration + * @param array $jsonResult + * + * @return bool + */ + private function findWebHook(Integration $integration, array $jsonResult) + { + $type = $integration->type; + $hookUrl = $integration->getLink('#hook'); + foreach ($jsonResult as $hook) { + if ($type === 'github' && $hook['config']['url'] === $hookUrl) { + return true; + } + if ($type === 'gitlab' && $hook['url'] === $hookUrl) { + return true; + } + } + + return false; + } + + /** * @param Integration $integration */ protected function displayIntegration(Integration $integration) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Integration/IntegrationUpdateCommand.php new/platformsh-cli-3.26.0/src/Command/Integration/IntegrationUpdateCommand.php --- old/platformsh-cli-3.25.1/src/Command/Integration/IntegrationUpdateCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Integration/IntegrationUpdateCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -50,7 +50,8 @@ } } if (!$values) { - $this->stdErr->writeln("No changed values were provided to update"); + $this->stdErr->writeln('No changed values were provided to update.'); + $this->ensureHooks($integration); return 1; } @@ -66,6 +67,7 @@ $result = $integration->update($values); $this->stdErr->writeln("Integration <info>{$integration->id}</info> (<info>{$integration->type}</info>) updated"); + $this->ensureHooks($integration); $this->displayIntegration($integration); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Self/SelfBuildCommand.php new/platformsh-cli-3.26.0/src/Command/Self/SelfBuildCommand.php --- old/platformsh-cli-3.25.1/src/Command/Self/SelfBuildCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Self/SelfBuildCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -190,9 +190,9 @@ $changelog = $shell->execute([ 'git', 'log', - '--pretty=format:"* %s"', + '--pretty=format:* %s', '--no-merges', - 'v' . $oldVersion . '...v' . $version + 'v' . $oldVersion . '...master' ]); } $manifestItem['version'] = $version; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Snapshot/SnapshotCreateCommand.php new/platformsh-cli-3.26.0/src/Command/Snapshot/SnapshotCreateCommand.php --- old/platformsh-cli-3.25.1/src/Command/Snapshot/SnapshotCreateCommand.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Snapshot/SnapshotCreateCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -20,6 +20,7 @@ ->addNoWaitOption('Do not wait for the snapshot to complete'); $this->setHiddenAliases(['backup', 'environment:backup']); $this->addExample('Make a snapshot of the current environment'); + $this->addExample('Request a snapshot (and exit quickly)', '--no-wait'); } protected function execute(InputInterface $input, OutputInterface $output) @@ -45,6 +46,14 @@ if (!$input->getOption('no-wait')) { $this->stdErr->writeln('Waiting for the snapshot to complete...'); + + // Strongly recommend using --no-wait in a cron job. + if (!$this->isTerminal(STDIN)) { + $this->stdErr->writeln( + '<comment>Warning:</comment> use the --no-wait (-W) option if you are running this in a cron job.' + ); + } + /** @var \Platformsh\Cli\Service\ActivityMonitor $activityMonitor */ $activityMonitor = $this->getService('activity_monitor'); $success = $activityMonitor->waitAndLog( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Command/Worker/WorkerListCommand.php new/platformsh-cli-3.26.0/src/Command/Worker/WorkerListCommand.php --- old/platformsh-cli-3.25.1/src/Command/Worker/WorkerListCommand.php 1970-01-01 01:00:00.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Command/Worker/WorkerListCommand.php 2017-12-21 12:52:01.000000000 +0100 @@ -0,0 +1,58 @@ +<?php +namespace Platformsh\Cli\Command\Worker; + +use Platformsh\Cli\Command\CommandBase; +use Platformsh\Cli\Service\Table; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class WorkerListCommand extends CommandBase +{ + protected $hiddenInList = true; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('worker:list') + ->setAliases(['workers']) + ->setDescription('Get a list of all deployed workers') + ->addOption('refresh', null, InputOption::VALUE_NONE, 'Whether to refresh the cache'); + $this->addProjectOption() + ->addEnvironmentOption(); + Table::configureInput($this->getDefinition()); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->validateInput($input); + + $workers = $this->api() + ->getCurrentDeployment($this->getSelectedEnvironment(), $input->getOption('refresh')) + ->workers; + if (empty($workers)) { + $this->stdErr->writeln('No workers found.'); + + return 0; + } + + /** @var \Platformsh\Cli\Service\PropertyFormatter $formatter */ + $formatter = $this->getService('property_formatter'); + $rows = []; + foreach ($workers as $worker) { + $commands = isset($worker->worker['commands']) ? $worker->worker['commands'] : []; + $rows[] = [$worker->name, $worker->type, $formatter->format($commands)]; + } + + /** @var \Platformsh\Cli\Service\Table $table */ + $table = $this->getService('table'); + $table->render($rows, ['Name', 'Type', 'Commands']); + + return 0; + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Console/CustomTextDescriptor.php new/platformsh-cli-3.26.0/src/Console/CustomTextDescriptor.php --- old/platformsh-cli-3.25.1/src/Console/CustomTextDescriptor.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Console/CustomTextDescriptor.php 2017-12-21 12:52:01.000000000 +0100 @@ -148,17 +148,12 @@ $aliases = $command->getVisibleAliases(); } - // Colour local commands differently from remote ones. - $commandDescription = $command->getDescription(); - if ($command instanceof CommandBase && !$command->isLocal()) { - $commandDescription = "<fg=cyan>$commandDescription</fg=cyan>"; - } $this->writeText("\n"); $this->writeText( sprintf( " %-${width}s %s", "<info>$name</info>" . $this->formatAliases($aliases), - $commandDescription + $command->getDescription() ), $options ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Console/EventSubscriber.php new/platformsh-cli-3.26.0/src/Console/EventSubscriber.php --- old/platformsh-cli-3.25.1/src/Console/EventSubscriber.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Console/EventSubscriber.php 2017-12-21 12:52:01.000000000 +0100 @@ -62,6 +62,7 @@ if (($exception instanceof ClientException || $exception instanceof ServerException) && ($response = $exception->getResponse())) { $request = $exception->getRequest(); + $requestConfig = $request->getConfig(); $response->getBody()->seek(0); $json = (array) json_decode($response->getBody()->getContents(), true); @@ -69,6 +70,7 @@ // error. $loginCommand = sprintf('%s login', $this->config->get('application.executable')); if ($response->getStatusCode() === 400 + && $requestConfig['auth'] === 'oauth2' && isset($json['error_description']) && $json['error_description'] === 'Invalid refresh token') { $event->setException(new LoginRequiredException( @@ -77,14 +79,14 @@ $response )); $event->stopPropagation(); - } elseif ($response->getStatusCode() === 401) { + } elseif ($response->getStatusCode() === 401 && $requestConfig['auth'] === 'oauth2') { $event->setException(new LoginRequiredException( "Unauthorized. \nPlease log in again by running: $loginCommand", $request, $response )); $event->stopPropagation(); - } elseif ($response->getStatusCode() === 403) { + } elseif ($response->getStatusCode() === 403 && $requestConfig['auth'] === 'oauth2') { $event->setException(new PermissionDeniedException( "Permission denied. Check your project or environment permissions.", $request, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Exception/RootNotFoundException.php new/platformsh-cli-3.26.0/src/Exception/RootNotFoundException.php --- old/platformsh-cli-3.25.1/src/Exception/RootNotFoundException.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Exception/RootNotFoundException.php 2017-12-21 12:52:01.000000000 +0100 @@ -2,8 +2,25 @@ namespace Platformsh\Cli\Exception; +use Platformsh\Cli\Service\Config; + class RootNotFoundException extends \RuntimeException { - protected $message = 'Project root not found. This can only be run from inside a project directory.'; - protected $code = 2; + public function __construct( + $message = 'Project root not found. This can only be run from inside a project directory.', + $code = 2 + ) + { + // If this is a Git repository that looks like an un-configured project, + // then suggest the "project:set-remote" command. + if (is_dir('.git')) { + $config = new Config(); + if (is_dir($config->get('service.project_config_dir'))) { + $executable = $config->get('application.executable'); + $message .= "\n\nTo set the project for this Git repository, run:\n $executable project:set-remote [id]"; + } + } + + parent::__construct($message, $code); + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Local/LocalApplication.php new/platformsh-cli-3.26.0/src/Local/LocalApplication.php --- old/platformsh-cli-3.25.1/src/Local/LocalApplication.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Local/LocalApplication.php 2017-12-21 12:52:01.000000000 +0100 @@ -1,13 +1,14 @@ <?php namespace Platformsh\Cli\Local; +use Platformsh\Cli\Model\AppConfig; use Platformsh\Cli\Service\Config; use Platformsh\Cli\Exception\InvalidConfigException; use Platformsh\Cli\Local\BuildFlavor\BuildFlavorInterface; use Platformsh\Cli\Service\Mount; use Symfony\Component\Finder\Finder; use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Yaml; class LocalApplication { @@ -114,7 +115,7 @@ */ public function setConfig(array $config) { - $this->config = $config; + $this->config = new AppConfig($config); } /** @@ -124,20 +125,29 @@ */ public function getConfig() { + return $this->getConfigObject()->getNormalized(); + } + + /** + * Get the application's configuration as an object. + * + * @return AppConfig + */ + private function getConfigObject() + { if (!isset($this->config)) { - $this->config = []; + $config = []; $file = $this->appRoot . '/' . $this->cliConfig->get('service.app_config_file'); if (file_exists($file)) { try { - $parser = new Parser(); - $config = (array) $parser->parse(file_get_contents($file)); - $this->config = $this->normalizeConfig($config); + $config = (array) (new Yaml())->parse(file_get_contents($file)); } catch (ParseException $e) { throw new InvalidConfigException( "Parse error in file '$file': \n" . $e->getMessage() ); } } + $this->config = new AppConfig($config); } return $this->config; @@ -154,48 +164,6 @@ } /** - * Normalize an application's configuration. - * - * @param array $config - * - * @return array - */ - protected function normalizeConfig(array $config) - { - // Backwards compatibility with old config format: `toolstack` is - // changed to application `type` and `build`.`flavor`. - if (isset($config['toolstack'])) { - if (!strpos($config['toolstack'], ':')) { - throw new InvalidConfigException("Invalid value for 'toolstack'"); - } - list($config['type'], $config['build']['flavor']) = explode(':', $config['toolstack'], 2); - } - - // The `web` section has changed to `web`.`locations`. - if (isset($config['web']['document_root']) && !isset($config['web']['locations'])) { - $oldConfig = $config['web'] + $this->getOldWebDefaults(); - - $location = &$config['web']['locations']['/']; - - $location['root'] = $oldConfig['document_root']; - $location['expires'] = $oldConfig['expires']; - $location['passthru'] = $oldConfig['passthru']; - $location['allow'] = true; - - foreach ($oldConfig['whitelist'] as $pattern) { - $location['allow'] = false; - $location['rules'][$pattern]['allow'] = true; - } - - foreach ($oldConfig['blacklist'] as $pattern) { - $location['rules'][$pattern]['allow'] = false; - } - } - - return $config; - } - - /** * @return BuildFlavorInterface[] */ public function getBuildFlavors() @@ -281,49 +249,17 @@ } /** - * Get a single application by name. + * Get the configured document root for the application, as a relative path. * - * @param string|null $name - * The application name. - * @param string $directory - * The absolute path to a directory. - * @param Config|null $config - * CLI configuration. + * @param string $default * - * @return LocalApplication - */ - public static function getApplication($name, $directory, Config $config = null) - { - $apps = self::getApplications($directory, $config); - if ($name === null && count($apps) === 1) { - return reset($apps); - } - foreach ($apps as $app) { - if ($app->getName() === $name) { - return $app; - } - } - - throw new \InvalidArgumentException('App not found: ' . $name); - } - - /** - * Get the configured document root for the application, as a relative path. + * @todo stop using 'public' as the default * * @return string */ - public function getDocumentRoot() + public function getDocumentRoot($default = 'public') { - $config = $this->getConfig(); - - // The default document root is '/public'. This is used if the root is - // not set, if it is empty, or if it is set to '/'. - $documentRoot = '/public'; - if (!empty($config['web']['locations']['/']['root']) && $config['web']['locations']['/']['root'] !== '/') { - $documentRoot = $config['web']['locations']['/']['root']; - } - - return ltrim($documentRoot, '/'); + return $this->getConfigObject()->getDocumentRoot() ?: $default; } /** @@ -341,75 +277,4 @@ return $this->getDocumentRoot() === 'public' && !is_dir($this->getRoot() . '/public'); } - - /** - * @return array - */ - protected function getOldWebDefaults() - { - return [ - 'document_root' => '/public', - 'expires' => 0, - 'passthru' => '/index.php', - 'blacklist' => [], - 'whitelist' => [ - // CSS and Javascript. - '\.css$', - '\.js$', - - // image/* types. - '\.gif$', - '\.jpe?g$', - '\.png$', - '\.tiff?$', - '\.wbmp$', - '\.ico$', - '\.jng$', - '\.bmp$', - '\.svgz?$', - - // audio/* types. - '\.midi?$', - '\.mpe?ga$', - '\.mp2$', - '\.mp3$', - '\.m4a$', - '\.ra$', - '\.weba$', - - // video/* types. - '\.3gpp?$', - '\.mp4$', - '\.mpe?g$', - '\.mpe$', - '\.ogv$', - '\.mov$', - '\.webm$', - '\.flv$', - '\.mng$', - '\.asx$', - '\.asf$', - '\.wmv$', - '\.avi$', - - // application/ogg. - '\.ogx$', - - // application/x-shockwave-flash. - '\.swf$', - - // application/java-archive. - '\.jar$', - - // fonts types. - '\.ttf$', - '\.eot$', - '\.woff$', - '\.otf$', - - // robots.txt. - '/robots\.txt$', - ], - ]; - } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Model/AppConfig.php new/platformsh-cli-3.26.0/src/Model/AppConfig.php --- old/platformsh-cli-3.25.1/src/Model/AppConfig.php 1970-01-01 01:00:00.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Model/AppConfig.php 2017-12-21 12:52:01.000000000 +0100 @@ -0,0 +1,187 @@ +<?php + +namespace Platformsh\Cli\Model; + +use Platformsh\Cli\Exception\InvalidConfigException; +use Platformsh\Client\Model\Deployment\WebApp; + +/** + * A class to help reading and normalizing an application's configuration. + */ +class AppConfig +{ + private $config; + private $normalizedConfig; + + /** + * AppConfig constructor. + * + * @param array $config + */ + public function __construct(array $config) + { + $this->config = $config; + $this->normalizedConfig = $this->normalizeConfig($config); + } + + /** + * @param \Platformsh\Client\Model\Deployment\WebApp $app + * + * @return static + */ + public static function fromWebApp(WebApp $app) + { + return new static($app->getProperties()); + } + + /** + * Get normalized configuration. + * + * @return array + */ + public function getNormalized() + { + if (!isset($this->normalizedConfig)) { + $this->normalizedConfig = $this->normalizeConfig($this->config); + } + + return $this->normalizedConfig; + } + + /** + * Get the (normalized) document root as a relative path. + * + * @return string + */ + public function getDocumentRoot() + { + $documentRoot = ''; + $normalized = $this->getNormalized(); + if (empty($normalized['web']['locations'])) { + return $documentRoot; + } + foreach ($this->getNormalized()['web']['locations'] as $path => $location) { + if (isset($location['root'])) { + $documentRoot = $location['root']; + } + if ($path === '/') { + break; + } + } + + return ltrim($documentRoot, '/'); + } + + /** + * Normalize the application config. + * + * @param array $config + * + * @return array + */ + private function normalizeConfig(array $config) + { + // Backwards compatibility with old config format: `toolstack` is + // changed to application `type` and `build`.`flavor`. + if (isset($config['toolstack'])) { + if (!strpos($config['toolstack'], ':')) { + throw new InvalidConfigException("Invalid value for 'toolstack'"); + } + list($config['type'], $config['build']['flavor']) = explode(':', $config['toolstack'], 2); + } + + // The `web` section has changed to `web`.`locations`. + if (isset($config['web']['document_root']) && empty($config['web']['locations'])) { + $oldConfig = $config['web'] + $this->getOldWebDefaults(); + + $location = &$config['web']['locations']['/']; + + $location['root'] = $oldConfig['document_root']; + $location['expires'] = $oldConfig['expires']; + $location['passthru'] = $oldConfig['passthru']; + $location['allow'] = true; + + foreach ($oldConfig['whitelist'] as $pattern) { + $location['allow'] = false; + $location['rules'][$pattern]['allow'] = true; + } + + foreach ($oldConfig['blacklist'] as $pattern) { + $location['rules'][$pattern]['allow'] = false; + } + } + + return $config; + } + + /** + * @return array + */ + private function getOldWebDefaults() + { + return [ + 'document_root' => '/public', + 'expires' => 0, + 'passthru' => '/index.php', + 'blacklist' => [], + 'whitelist' => [ + // CSS and Javascript. + '\.css$', + '\.js$', + + // image/* types. + '\.gif$', + '\.jpe?g$', + '\.png$', + '\.tiff?$', + '\.wbmp$', + '\.ico$', + '\.jng$', + '\.bmp$', + '\.svgz?$', + + // audio/* types. + '\.midi?$', + '\.mpe?ga$', + '\.mp2$', + '\.mp3$', + '\.m4a$', + '\.ra$', + '\.weba$', + + // video/* types. + '\.3gpp?$', + '\.mp4$', + '\.mpe?g$', + '\.mpe$', + '\.ogv$', + '\.mov$', + '\.webm$', + '\.flv$', + '\.mng$', + '\.asx$', + '\.asf$', + '\.wmv$', + '\.avi$', + + // application/ogg. + '\.ogx$', + + // application/x-shockwave-flash. + '\.swf$', + + // application/java-archive. + '\.jar$', + + // fonts types. + '\.ttf$', + '\.eot$', + '\.woff$', + '\.otf$', + + // robots.txt. + '/robots\.txt$', + ], + ]; + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Service/Api.php new/platformsh-cli-3.26.0/src/Service/Api.php --- old/platformsh-cli-3.25.1/src/Service/Api.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Service/Api.php 2017-12-21 12:52:01.000000000 +0100 @@ -9,6 +9,7 @@ use Platformsh\Cli\Session\KeychainStorage; use Platformsh\Cli\Util\NestedArrayUtil; use Platformsh\Client\Connection\Connector; +use Platformsh\Client\Model\Deployment\EnvironmentDeployment; use Platformsh\Client\Model\Environment; use Platformsh\Client\Model\Git\Tree; use Platformsh\Client\Model\Project; @@ -741,4 +742,28 @@ $this->sessionStorage->deleteAll(); } } + + /** + * Get the current deployment for an environment. + * + * @param Environment $environment + * @param bool $refresh + * + * @return EnvironmentDeployment + */ + public function getCurrentDeployment(Environment $environment, $refresh = false) + { + $cacheKey = implode(':', ['current-deployment', $environment->project, $environment->id]); + $data = $this->cache->fetch($cacheKey); + if ($data === false || $refresh) { + $deployment = $environment->getCurrentDeployment(); + $data = $deployment->getData(); + $data['_uri'] = $deployment->getUri(); + $this->cache->save($cacheKey, $data, $this->config->get('api.environments_ttl')); + } else { + $deployment = new EnvironmentDeployment($data, $data['_uri'], $this->getHttpClient(), true); + } + + return $deployment; + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Service/Git.php new/platformsh-cli-3.26.0/src/Service/Git.php --- old/platformsh-cli-3.25.1/src/Service/Git.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Service/Git.php 2017-12-21 12:52:01.000000000 +0100 @@ -10,8 +10,8 @@ class Git { - /** @var string */ - protected $repositoryDir = '.'; + /** @var string|null */ + protected $repositoryDir = null; /** @var Shell */ protected $shellHelper; @@ -126,9 +126,9 @@ * * @param string[] $args * Command arguments (everything after 'git'). - * @param string|false $dir + * @param string|false|null $dir * The path to a Git repository. Set to false if the command should not - * run inside a repository. + * run inside a repository. Set to null to use the default repository. * @param bool $mustRun * Enable exceptions if the Git command fails. * @param bool $quiet diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Service/SelfUpdater.php new/platformsh-cli-3.26.0/src/Service/SelfUpdater.php --- old/platformsh-cli-3.25.1/src/Service/SelfUpdater.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Service/SelfUpdater.php 2017-12-21 12:52:01.000000000 +0100 @@ -100,6 +100,7 @@ $this->stdErr->writeln(" composer global remove " . $this->config->get('application.package_name')); $this->stdErr->writeln(" curl -sS " . $this->config->get('application.installer_url') . " | php\n"); } + return false; } @@ -109,7 +110,13 @@ $currentVersion )); - $updater = new Updater(null, false); + if (!is_writable($localPhar)) { + $this->stdErr->writeln('Cannot update as the Phar file is not writable: ' . $localPhar); + + return false; + } + + $updater = new Updater($localPhar, false); $strategy = new ManifestStrategy($currentVersion, $manifestUrl, $this->allowMajor, $this->allowUnstable); $strategy->setManifestTimeout($this->timeout); $updater->setStrategyObject($strategy); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/platformsh-cli-3.25.1/src/Service/Shell.php new/platformsh-cli-3.26.0/src/Service/Shell.php --- old/platformsh-cli-3.25.1/src/Service/Shell.php 2017-12-14 21:48:13.000000000 +0100 +++ new/platformsh-cli-3.26.0/src/Service/Shell.php 2017-12-21 12:52:01.000000000 +0100 @@ -155,8 +155,8 @@ } // In PHP <7.1 there isn't a way to read all of the current environment // variables. If PHP is running with a variables_order that includes - // 'e', then $_ENV may be populated. - if (!empty($_ENV)) { + // 'e', then $_ENV should be populated. + if (!empty($_ENV) && stripos(ini_get('variables_order'), 'e') !== false) { return $_ENV; } @@ -180,7 +180,9 @@ $variables[$name] = getenv($name); } - return array_filter($variables); + return array_filter($variables, function ($value) { + return $value !== false; + }); } /** ++++++ platformsh-cli-vendor.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/autoload.php new/vendor/autoload.php --- old/vendor/autoload.php 2017-12-15 04:02:16.574490249 +0100 +++ new/vendor/autoload.php 2017-12-21 14:35:11.781831266 +0100 @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInita4fe9dccfc4a6e8ed6afbf057d3bc04d::getLoader(); +return ComposerAutoloaderInit6476145b406e49406b2b25f90c7a82bc::getLoader(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/composer/autoload_real.php new/vendor/composer/autoload_real.php --- old/vendor/composer/autoload_real.php 2017-12-15 04:02:16.574490249 +0100 +++ new/vendor/composer/autoload_real.php 2017-12-21 14:35:11.781831266 +0100 @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInita4fe9dccfc4a6e8ed6afbf057d3bc04d +class ComposerAutoloaderInit6476145b406e49406b2b25f90c7a82bc { private static $loader; @@ -19,15 +19,15 @@ return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInita4fe9dccfc4a6e8ed6afbf057d3bc04d', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit6476145b406e49406b2b25f90c7a82bc', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInita4fe9dccfc4a6e8ed6afbf057d3bc04d', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit6476145b406e49406b2b25f90c7a82bc', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInita4fe9dccfc4a6e8ed6afbf057d3bc04d::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit6476145b406e49406b2b25f90c7a82bc::getInitializer($loader)); } else { $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -48,19 +48,19 @@ $loader->register(true); if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInita4fe9dccfc4a6e8ed6afbf057d3bc04d::$files; + $includeFiles = Composer\Autoload\ComposerStaticInit6476145b406e49406b2b25f90c7a82bc::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { - composerRequirea4fe9dccfc4a6e8ed6afbf057d3bc04d($fileIdentifier, $file); + composerRequire6476145b406e49406b2b25f90c7a82bc($fileIdentifier, $file); } return $loader; } } -function composerRequirea4fe9dccfc4a6e8ed6afbf057d3bc04d($fileIdentifier, $file) +function composerRequire6476145b406e49406b2b25f90c7a82bc($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/composer/autoload_static.php new/vendor/composer/autoload_static.php --- old/vendor/composer/autoload_static.php 2017-12-15 04:02:16.574490249 +0100 +++ new/vendor/composer/autoload_static.php 2017-12-21 14:35:11.781831266 +0100 @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInita4fe9dccfc4a6e8ed6afbf057d3bc04d +class ComposerStaticInit6476145b406e49406b2b25f90c7a82bc { public static $files = array ( '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', @@ -188,9 +188,9 @@ public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInita4fe9dccfc4a6e8ed6afbf057d3bc04d::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInita4fe9dccfc4a6e8ed6afbf057d3bc04d::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInita4fe9dccfc4a6e8ed6afbf057d3bc04d::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInit6476145b406e49406b2b25f90c7a82bc::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit6476145b406e49406b2b25f90c7a82bc::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit6476145b406e49406b2b25f90c7a82bc::$classMap; }, null, ClassLoader::class); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/composer/installed.json new/vendor/composer/installed.json --- old/vendor/composer/installed.json 2017-12-15 04:02:15.974484964 +0100 +++ new/vendor/composer/installed.json 2017-12-21 14:35:10.985830420 +0100 @@ -657,17 +657,17 @@ }, { "name": "platformsh/client", - "version": "v0.13.7", - "version_normalized": "0.13.7.0", + "version": "v0.14.0", + "version_normalized": "0.14.0.0", "source": { "type": "git", "url": "https://github.com/platformsh/platformsh-client-php.git", - "reference": "62f990120e9c8dd386aca1abcd0fe2e92e1a1b43" + "reference": "47013df77c5ac9d1cea32fd4caa3999ecca150ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/62f990120e9c8dd386aca1abcd0fe2e92e1a1b43", - "reference": "62f990120e9c8dd386aca1abcd0fe2e92e1a1b43", + "url": "https://api.github.com/repos/platformsh/platformsh-client-php/zipball/47013df77c5ac9d1cea32fd4caa3999ecca150ca", + "reference": "47013df77c5ac9d1cea32fd4caa3999ecca150ca", "shasum": "" }, "require": { @@ -680,7 +680,7 @@ "require-dev": { "phpunit/phpunit": "~4.5" }, - "time": "2017-12-12T16:46:08+00:00", + "time": "2017-12-20T12:45:06+00:00", "type": "library", "extra": { "patches": { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/DataStructure/ReadOnlyStructureTrait.php new/vendor/platformsh/client/src/DataStructure/ReadOnlyStructureTrait.php --- old/vendor/platformsh/client/src/DataStructure/ReadOnlyStructureTrait.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/DataStructure/ReadOnlyStructureTrait.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,55 @@ +<?php + +namespace Platformsh\Client\DataStructure; + +trait ReadOnlyStructureTrait +{ + private $data = []; + + private function __construct(array $data) + { + $this->data = $data; + } + + public function __get($name) + { + $this->checkExists($name); + + return $this->data[$name]; + } + + public function __set($name, $value) + { + $this->checkExists($name); + throw new \BadMethodCallException('Property not writable: ' . $name); + } + + private function checkExists($property) + { + if (!array_key_exists($property, $this->data)) { + throw new \InvalidArgumentException('Property not found: ' . $property); + } + } + + /** + * Construct from API data. + * + * @param array $data + * + * @return static + */ + public static function fromData(array $data) + { + return new static($data); + } + + /** + * Get all properties. + * + * @return array + */ + public function getProperties() + { + return $this->data; + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Deployment/AppBase.php new/vendor/platformsh/client/src/Model/Deployment/AppBase.php --- old/vendor/platformsh/client/src/Model/Deployment/AppBase.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Deployment/AppBase.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,18 @@ +<?php + +namespace Platformsh\Client\Model\Deployment; + +use Platformsh\Client\DataStructure\ReadOnlyStructureTrait; + +/** + * An application. + * + * @property-read string $name + * @property-read string $type + * @property-read array $runtime + * @property-read array $preflight + */ +abstract class AppBase +{ + use ReadOnlyStructureTrait; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Deployment/EnvironmentDeployment.php new/vendor/platformsh/client/src/Model/Deployment/EnvironmentDeployment.php --- old/vendor/platformsh/client/src/Model/Deployment/EnvironmentDeployment.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Deployment/EnvironmentDeployment.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,71 @@ +<?php + +namespace Platformsh\Client\Model\Deployment; + +use Platformsh\Client\Model\Resource; + +/** + * A Platform.sh environment deployment. + * + * @property-read Route[] $routes + * @property-read Service[] $services + * @property-read WebApp[] $webapps + * @property-read Worker[] $workers + * + * @method Route getRoute(string $originalUrl) + * @method Service getService(string $name) + * @method WebApp getWebApp(string $name) + * @method Worker getWorker(string $name) + */ +class EnvironmentDeployment extends Resource +{ + private static $types = [ + 'services' => Service::class, + 'routes' => Route::class, + 'webapps' => WebApp::class, + 'workers' => Worker::class, + ]; + + /** + * {@inheritdoc} + */ + public function __get($name) + { + if (isset(self::$types[$name])) { + $className = self::$types[$name]; + return array_map(function (array $data) use ($className) { + return $className::fromData($data); + }, $this->data[$name]); + } + + return parent::__get($name); + } + + /** + * Dynamically get an item from a list of sub-properties by name. + * + * This represents the getWebApp(), getService, getRoute() and + * getWorker() methods. + */ + public function __call($name, $arguments) + { + if (strpos($name, 'get') === 0) { + $type = substr($name, 3); + $property = strtolower($type) . 's'; + if (!isset(self::$types[$property])) { + throw new \BadMethodCallException(sprintf('Method not found: %s()', $name)); + } + if (count($arguments) !== 1) { + throw new \InvalidArgumentException(sprintf('%s() expects exactly one argument', $name)); + } + $key = $arguments[0]; + if (!isset($this->data[$property][$key])) { + throw new \InvalidArgumentException(sprintf('%s not found: %s', $type, $key)); + } + $className = self::$types[$property]; + + return $className::fromData($this->data[$property][$key]); + } + throw new \BadMethodCallException(sprintf('Method not found: %s()', $name)); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Deployment/Route.php new/vendor/platformsh/client/src/Model/Deployment/Route.php --- old/vendor/platformsh/client/src/Model/Deployment/Route.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Deployment/Route.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,18 @@ +<?php + +namespace Platformsh\Client\Model\Deployment; + +use Platformsh\Client\DataStructure\ReadOnlyStructureTrait; + +/** + * A route in a deployed environment. + * + * @property-read string $type + * @property-read array $redirects + * @property-read array $tls + * @property-read string $original_url + */ +class Route +{ + use ReadOnlyStructureTrait; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Deployment/Service.php new/vendor/platformsh/client/src/Model/Deployment/Service.php --- old/vendor/platformsh/client/src/Model/Deployment/Service.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Deployment/Service.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,20 @@ +<?php + +namespace Platformsh\Client\Model\Deployment; + +use Platformsh\Client\DataStructure\ReadOnlyStructureTrait; + +/** + * A service in a deployed environment. + * + * @property-read string $type + * @property-read string $size + * @property-read string $disk + * @property-read array $access + * @property-read array $configuration + * @property-read array $relationships + */ +class Service +{ + use ReadOnlyStructureTrait; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Deployment/WebApp.php new/vendor/platformsh/client/src/Model/Deployment/WebApp.php --- old/vendor/platformsh/client/src/Model/Deployment/WebApp.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Deployment/WebApp.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,13 @@ +<?php + +namespace Platformsh\Client\Model\Deployment; + +/** + * A web application in a deployed environment. + * + * @property-read array $web + * @property-read array $hooks + */ +class WebApp extends AppBase +{ +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Deployment/Worker.php new/vendor/platformsh/client/src/Model/Deployment/Worker.php --- old/vendor/platformsh/client/src/Model/Deployment/Worker.php 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Deployment/Worker.php 2017-12-20 13:45:06.000000000 +0100 @@ -0,0 +1,12 @@ +<?php + +namespace Platformsh\Client\Model\Deployment; + +/** + * A web application in a deployed environment. + * + * @property-read array $worker + */ +class Worker extends AppBase +{ +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/platformsh/client/src/Model/Environment.php new/vendor/platformsh/client/src/Model/Environment.php --- old/vendor/platformsh/client/src/Model/Environment.php 2017-12-12 17:46:08.000000000 +0100 +++ new/vendor/platformsh/client/src/Model/Environment.php 2017-12-20 13:45:06.000000000 +0100 @@ -5,6 +5,7 @@ use Cocur\Slugify\Slugify; use Platformsh\Client\Exception\EnvironmentStateException; use Platformsh\Client\Exception\OperationUnavailableException; +use Platformsh\Client\Model\Deployment\EnvironmentDeployment; use Platformsh\Client\Model\Git\Commit; /** @@ -51,6 +52,23 @@ class Environment extends Resource { /** + * Get the current deployment of this environment. + * + * @throws \RuntimeException if no current deployment is found. + * + * @return EnvironmentDeployment + */ + public function getCurrentDeployment() + { + $deployment = EnvironmentDeployment::get('current', $this->getUri() . '/deployments', $this->client); + if (!$deployment) { + throw new EnvironmentStateException('Current deployment not found', $this); + } + + return $deployment; + } + + /** * Get the Git commit for the HEAD of this environment. * * @return Commit|false
