pantheon-systems / terminus

The Pantheon CLI — a standalone utility for performing operations on the Pantheon Platform
https://pantheon.io
Other
315 stars 194 forks source link

Plugin:install breaks Terminus 3.0.3 #2305

Open ErroneousBosch opened 2 years ago

ErroneousBosch commented 2 years ago

Platform

( ) MacOS (X) Linux (Ubuntu 20.04) ( ) Winderz

Installed Via

( ) Homebrew ( ) Apt Package ( ) Manually (X) Composer

PHP Version

(X) 7.4x ( ) 8.0 ( ) 8.1

Command Executed

my-username@my-workstation:~$ terminus plugin:install terminus-plugin-project/terminus-pancakes-plugin
 [notice] Installed terminus-plugin-project/terminus-pancakes-plugin.
 [notice] 
my-username@my-workstation:~$ terminus help plugin
PHP Fatal error:  Uncaught Error: Call to undefined method Symfony\Component\Console\Input\InputOption::isNegatable() in /home/my-username/vendor/symfony/console/Input/InputDefinition.php:253
Stack trace:
#0 /home/my-username/vendor/symfony/console/Input/InputDefinition.php(222): Symfony\Component\Console\Input\InputDefinition->addOption()
#1 /home/my-username/vendor/symfony/console/Input/InputDefinition.php(211): Symfony\Component\Console\Input\InputDefinition->addOptions()
#2 /home/my-username/vendor/symfony/console/Input/InputDefinition.php(63): Symfony\Component\Console\Input\InputDefinition->setOptions()
#3 /home/my-username/vendor/symfony/console/Input/InputDefinition.php(44): Symfony\Component\Console\Input\InputDefinition->setDefinition()
#4 /home/my-username/.terminus/terminus-dependencies-2512c16/vendor/symfony/console/Application.php(988): Symfony\Component\Console\Input\InputDefinition->__construct()
#5 /home/my-username/.terminus/terminus-dependencies-2512c16/vendor/symfony/console/Application in /home/my-username/vendor/symfony/console/Input/InputDefinition.php on line 253

Expected behavior

Installing a plugin should install the plugin and terminus should work

Actual behavior

After installing a plugin using terminus's built in commands breaks terminus entirely, it then errors out on every subsequent command until the ~/.terminus/ directory is cleared out. This happens with any plugin tried (pancakes, filer, and site-status tried). Terminus functions normally prior to this, and after cleaning out all non-cache subdirs in its directory.

greg-1-anderson commented 2 years ago

How did you install via Composer? If you've mixed Composer in with some other application (e.g. via composer global require), that is likely the problem. We probably need better validation in the plugin manager to detect situations where the plugin dependencies do not line up with the Composer dependencies.

Note that Composer is not a recommended installation method for Terminus 3. You should use Homebrew on Mac, or download terminus.phar from GitHub if Homebrew is not an option.

ErroneousBosch commented 2 years ago

Terminus was installed via Composer, but not a global one (enterprise managed machine), so Composer is a homedir install, and terminus's binary is in ~/vendor/bin. This is a clean composer install at this level, with just Terminus and PHPCS installed. Terminus itself seems to be doing a shadow install of dependencies, which then do not get used properly:

:~$ ll .terminus/terminus-dependencies-2512c16/vendor
total 92
drwxr-xr-x 22 my-username users 4096 Jan 10 12:09 ./
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 ../
-rw-r--r--  1 my-username users  178 Jan 10 12:09 autoload.php
drwxr-xr-x  2 my-username users 4096 Jan 10 12:09 bin/
drwxr-xr-x  9 my-username users 4096 Jan 10 12:09 composer/
drwxr-xr-x 11 my-username users 4096 Jan 10 12:09 consolidation/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 czproject/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 dflydev/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 grasmash/
drwxr-xr-x  5 my-username users 4096 Jan 10 12:09 guzzlehttp/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 justinrainbow/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 league/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 monolog/
drwxr-xr-x  2 my-username users 4096 Jan 10 12:09 pantheon-systems/
drwxr-xr-x  8 my-username users 4096 Jan 10 12:09 psr/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 ralouphie/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 react/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 rogervila/
drwxr-xr-x  4 my-username users 4096 Jan 10 12:09 seld/
drwxr-xr-x 18 my-username users 4096 Jan 10 12:09 symfony/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 terminus-plugin-project/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 tm/
drwxr-xr-x  3 my-username users 4096 Jan 10 12:09 twig/

This seems to be at the heart of the issue, and generating conflicts. It installs its own version of symfony here, which conflicts with the higher level one, rather than using the same packages. Seems like a misapplication of package management here.

Switching to the standalone phar file is a solution, but seems suboptimal.

greg-1-anderson commented 2 years ago

The shadow dependencies are required when doing plugins with dependencies using the .phar install of Terminus. If Terminus is installed via Composer, we could consider simply installing the plugins into Terminus' vendor, but Composer installations of Terminus are not recommended at this time.

Regarding your installation of Terminus, if by "a homedir install" you mean that you installed via cd $HOME followed by composer require, that is not recommended, because with this configuration, you risk combining Terminus with any other application you install via a "homedir install". If you are going to install Terminus via Composer, you must give it its own vendor directory. See https://pantheon.io/blog/fixing-composer-global-command

greg-1-anderson commented 2 years ago

Also, I am curious, why do you think that the Terminus .phar installation method is suboptimal?

ErroneousBosch commented 2 years ago

I understand the potential for conflicts of using a higher level composer require, which is why I keep it limited to a few key PHP applications. But that fix also does not address the behavior I was seeing in this, since in this case, symfony is installed by terminus for terminus; PHPCS does not use it. In this case Terminus's own dependencies were conflicting, since they were coming from two different places.

Suboptimal is mostly from a clutter standpoint and personal preference. Just ends up one more 30mb executable in my ~/bin.

greg-1-anderson commented 2 years ago

Mixing applications is not a supported installation mechanism. Installation combinations that work today might break at any time. Dependencies between symfony and the dependencies of other applications may change the versions of symfony components that get installed, which may or may not expose bugs, since you'll be using a different set of dependencies than were tested with Terminus. Worse, upgrades to Terminus or any of the applications you've installed with Terminus could cause conflicts that break your install.

You are right that there is a bug in the Terminus plugin manager regarding dependency selection. Basically, Terminus is using the composer.lock file at Terminus' root rather than using the composer.lock file that Terminus was actually installed into (in a Composer install). The workaround for this right now is, don't install Terminus this way, or don't use plugins. I'm not sure that we will prioritize fixing it to support the Composer installation method, since there are other reasons why (as mentioned above) that installation method is problematic, and hard for us to support.

Regarding the size of the Terminus .phar, we can shrink that quite a bit as a separate issue. The phar build is not optimized at all. The phar would be a fraction of its current size if we did that.

bwood commented 2 years ago

I just hit this problem today. For years I've been installing terminus via consolidation/cgr, but even this approach is vulnerable to this problem.

Everything was working fine until I did terminus plugin:install and then I hit the above error.

I tried to recover with

cgr remove pantheon-systems/terminus 
cgr pantheon-systems/terminus  #(install)

and was surprised when that didn't work. Thanks for the pointer to ~/.terminus/terminus-dependencies-*. Removing that allowed me to recover, but I guess I'll move to homebrew to manage terminus from now on so that I can use plugins.