drush icon indicating copy to clipboard operation
drush copied to clipboard

Drush 11 sees but no longer reads ~/.drush/drush.yml

Open fskreuz opened this issue 3 years ago • 7 comments

Describe the bug Drush 11 sees but no longer reads ~/.drush/drush.yml

To Reproduce

  1. Install Drush 11 with composer global require 'drush/drush:^11
    • I'm aware global installs are no longer supported, but technically it should still work (i.e. the bin is just somewhere else)
  2. Create ~/.drush/drush.yml containing the following:
command:
  sql:
    dump:
      options:
        db-url: 'mysql://user:[email protected]/dbname' # some path to a live MySQL db
  1. Do drush --verbose --debug status
  2. Do drush --verbose --debug sql:dump
  3. Replace Drush 11 with Drush 10 (composer global require 'drush/drush:^10) and repeat steps 3 and 4.

Expected behavior

  • In step 3, Drush declares it discovered ~/.drush/drush.yml.
  • In step 4, Drush declares it discovered ~/.drush/drush.yml.
  • In step 4, the console screen will be filled with the contents of the DB.
  • In step 5, it should be no different.

Actual behavior

  • In step 3, Drush declares it discovered ~/.drush/drush.yml.
  • In step 4, Drush declares it discovered ~/.drush/drush.yml.
  • In step 4, I see the following error:
PHP Fatal error:  Uncaught Error: Class 'Drupal\Core\Database\Database' not found in /home/ec2-user/.config/composer/vendor/drush/drush/src/Sql/SqlBase.php:96

The line numbers of this error change depending on the version of Drush, but it's this block of code. Despite db-url being filled in the yaml, it is empty once it reaches this part of the code. Same goes for the rest of the properties in $options.

        if ($url = $options['db-url']) {
            $url = is_array($url) ? $url[$database] : $url;
            $db_spec = static::dbSpecFromDbUrl($url);
            $db_spec['prefix'] = $options['db-prefix'];
            return static::getInstance($db_spec, $options);
        } elseif (($databases = $options['databases']) && (array_key_exists($database, $databases)) && (array_key_exists($target, $databases[$database]))) {
            // @todo 'databases' option is not declared anywhere?
            $db_spec = $databases[$database][$target];
            return static::getInstance($db_spec, $options);
        } elseif ($info = Database::getConnectionInfo($database)) {
            $db_spec = $info[$target];
            return static::getInstance($db_spec, $options);
        } else {
            throw new \Exception(dt('Unable to load Drupal settings. Check your --root, --uri, etc.'));
        }
  • In step 5, it's working.

Workaround Rollback to Drush 10 until this issue is resolved.

System Configuration

Q A
Drush version? 11.x
Drupal version? 9.x
PHP version 8.x
OS? Linux

Additional information

This setup is purely for pulling the database down from an intermediate server and takes advantage of the fact that sql:dump doesn't require Drupal to read the contents of the database. This intermediate server doesn't have Drupal installed, only a ~/.drush/drush.yml that contains command-specific options for sql:dump to set db-url to the database server. Both steps 3 and 4 were invoked remotely (as an alias) and on the server itself, same results.

Tested all the way back to 11.0.0-rc1 and still happening.

fskreuz avatar Apr 05 '22 21:04 fskreuz

I'm aware global installs are no longer supported, but technically it should still work (i.e. the bin is just somewhere else)

It's more complicated than that. See https://pantheon.io/blog/trouble-two-autoloaders

Could you try to reproduce with a site-local Drush (non-global install)? It's unlikely that a maintainer will try to fix a global install problem. We are likely to hard-break bootstrapping Drupal sites from a global Drush (so global installs will still run, but will only be useful as a launcher, or to run commands like archive:resotre etc)

greg-1-anderson avatar Apr 05 '22 22:04 greg-1-anderson

Tested with a local Drush 11. The file structure looks like

drupal/
  composer.json
  composer.lock
  drush/
    drush.yml
  vendor/

The command I ran this time is:

./vendor/bin/drush status

The output looks like:

PHP binary    : /usr/bin/php
PHP config    : /etc/php.ini
PHP OS        : Linux
Drush script  : /home/user/drupal/vendor/bin/drush
Drush version : 11.0.7
Drush temp    : /tmp
Drush configs : /home/user/drupal/vendor/drush/drush/drush.yml

For both Drush 10 and 11, it doesn't look like it found drush/drush.yml inside the setup. Not sure if this is related, just putting it out there. Reran the command, this time explicitly providing --config=drush/drush.yml. Same result as the global, Drush 10 dumps my DB while Drush 11 shows me the same error.

fskreuz avatar Apr 05 '22 22:04 fskreuz

I can confirm. I have this issue as well. Is this maybe related? #4345

  1. I have a single site (not a multi-site) and my site "default" path is /var/www/SITE/web/sites/default
  2. This "default" folder contains drush.yml with the following:
options:
  uri: 'https://SITE.example.com'
  1. drush status shows this (I removed some info):
 Drupal version   : 9.3.12
 Site URI         : http://default
 Database         : Connected
 Drupal bootstrap : Successful
 PHP binary       : /usr/bin/php7.4
 PHP config       : /etc/php/7.4/cli/php.ini
 PHP OS           : Linux
 Drush script     : /usr/local/bin/drush
 Drush version    : 11.0.9
 Drush temp       : /tmp
 Drush configs    : /var/www/SITE/vendor/drush/drush/drush.yml
                    sites/default/drush.yml
 Install profile  : standard
 Drupal root      : /var/www/SITE/web
 Site path        : sites/default

Running drush status -vvv adds the following:

 [preflight] Config paths: /var/www/SITE/vendor/drush/drush/drush.yml
 [preflight] Alias paths: /var/www/SITE/web/drush/sites,/var/www/SITE/drush/sites
 [preflight] Commandfile search paths: /var/www/SITE/vendor/drush/drush/src
 [info] Starting bootstrap to max [0.06 sec, 8.77 MB]
 [debug] Trying to bootstrap as far as we can [0.06 sec, 8.77 MB]
 [info] Drush bootstrap phase: bootstrapDrupalRoot() [0.06 sec, 8.77 MB]
 [info] Change working directory to /var/www/SITE/web [0.06 sec, 8.77 MB]
 [info] Initialized Drupal 9.3.12 root directory at /var/www/SITE/web [0.06 sec, 8.77 MB]
 [info] Drush bootstrap phase: bootstrapDrupalSite() [0.06 sec, 8.78 MB]
 [debug] Loaded Drush config file at sites/default/drush.yml. [0.07 sec, 9.02 MB]
 [info] Initialized Drupal site default at sites/default [0.07 sec, 9.02 MB]
 [info] Drush bootstrap phase: bootstrapDrupalConfiguration() [0.07 sec, 9.02 MB]
 [debug] Add service modifier [0.07 sec, 9.2 MB]
 [info] Drush bootstrap phase: bootstrapDrupalDatabase() [0.08 sec, 9.74 MB]
 [info] Successfully connected to the Drupal database. [0.08 sec, 9.74 MB]
 [info] Drush bootstrap phase: bootstrapDrupalFull() [0.08 sec, 9.74 MB]
 [debug] Start bootstrap of the Drupal Kernel. [0.08 sec, 9.74 MB]
 [debug] Finished bootstrap of the Drupal Kernel. [0.13 sec, 14.69 MB]

As you can see, the drush.yml file is found and it says it was loaded, but the Site URI still shows http://default. Running drush uli also shows http://default in the resulting URL, despite my setting the URI in drush.yml.

mbomb007 avatar May 11 '22 17:05 mbomb007

@mbomb007 Your problem is unrelated. This issue is about $HOME/.drush/drush.yml, whereas you are working with a site-specific drush.yml. It is too late to set the URI by the time Drush loads this config file, because the URI was used to select the "default" folder. Try putting your config file at /var/www/SITE/drush/drush.yml instead.

greg-1-anderson avatar May 11 '22 19:05 greg-1-anderson

Right. Or define DRUSH_OPTIONS_URL env variable as per https://www.drush.org/latest/using-drush-configuration/#environment-variables

weitzman avatar May 11 '22 19:05 weitzman

Ah, that helps. Thanks.

mbomb007 avatar May 12 '22 15:05 mbomb007

I opened #5653 for the sites/default/drush.yml bug.

damienmckenna avatar Jun 12 '23 21:06 damienmckenna