Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-discover non-Drupal commands #4696

Merged
merged 10 commits into from Mar 22, 2021
Merged

Conversation

claudiu-cristea
Copy link
Member

@claudiu-cristea claudiu-cristea commented Mar 21, 2021

True, there is a way to discover such commands by adding their paths in Drush configuration. But I want to be able to have such commands available automatically, when I composer require a 3rd party library Drush commands provider.

This PR uses the Robo RelativeNamespaceDiscovery to grab the Drush commands living in 3rd party libraries, loadable via PSR4. Such a class should comply with the following requirements:

  • The commands class namespace ends with *\Drush\Commands, e.g. My\Custom\Library\Drush\Commands.
  • The class and file name ends with *DrushCommands, e.g. FooDrushCommands.

@claudiu-cristea
Copy link
Member Author

We may want to deprecate global commands discoverable via config (?)

@weitzman
Copy link
Member

LGTM. @greg-1-anderson would be right person to review and merge this.

@weitzman
Copy link
Member

weitzman commented Mar 21, 2021

We should make sure that Generators can be discovered similarly, and edit docs at https://www.drush.org/latest/generators/ accordingly. #4547 might be related.

@claudiu-cristea
Copy link
Member Author

@weitzman I see global generators are already discovered by their namespace (\Drush\Generators\*). Should we add the same logic, e.g. My\Custom\Library\Drush\Generators?

What about deprecating the old way for commands (see my previous comment) and generators (\Drush\Generators\*)?

@weitzman
Copy link
Member

Should we add the same logic, e.g. My\Custom\Library\Drush\Generators

Yes, I think so.

What about deprecating the old way for commands (see my previous comment) and generators

Yes, IMO.

Copy link
Member

@greg-1-anderson greg-1-anderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is spot on; thank you for submitting it.

I am 👍 on merging this, but holding off for a bit to see if we want to add deprecations first. Auto-discovering generators would be good for consistency, but could be follow-on work IMO.

@claudiu-cristea
Copy link
Member Author

claudiu-cristea commented Mar 21, 2021

Generators are postponed to a followup. This is not a straight task as RelativeNamespaceDiscovery needs the class loader to grab the classes.

Consider to postpone also deprecations. In PR I'm suggesting to deprecate drush.commands discovery, which seems not documented anywhere, but can be observed here \Drush\Application::commandsFromConfiguration(). There is also drush.paths.include and this is confusing me.

if ($commandsFromConfig) {
@trigger_error("Discovering global commands by specifying them in 'drush.commands' config is deprecated and will be removed in Drush 11.0.0. See docs/commands.md on how to create auto-discoverable global commands.", E_USER_DEPRECATED);
}
$commandClasses = array_merge(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other question about this PR is, what happens if the same commandfile is found twice by multiple methods? For example, the example-drush-extension project creates an autoloadable class that is discovered based on its location, and is probably also discovered by this PR. I am presuming that this array_merge will cause these two identical items to become a single entry in the resulting array, since they should have the same key.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, not all parts of the merge have keys. So, we should remove the keys > merge > array_unique(), assuming that there are no same two namespaces with different paths in this universe. That would be a nonsense and a bug somewhere.

@@ -320,8 +320,12 @@ public function configureAndRegisterCommands(InputInterface $input, OutputInterf
$discovery = $this->commandDiscovery();
$commandClasses = $discovery->discover($commandfileSearchpath, '\Drush');
$commandClasses[] = \Consolidation\Filter\Hooks\FilterHooks::class;
$commandsFromConfig = $this->commandsFromConfiguration();
if ($commandsFromConfig) {
@trigger_error("Discovering global commands by specifying them in 'drush.commands' config is deprecated and will be removed in Drush 11.0.0. See docs/commands.md on how to create auto-discoverable global commands.", E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if trigger_error is too noisy. Maybe we should deprecate with trigger_error in Drush 11, and remove in Drush 12? I know that's a long long ways off, but folks are very slow at upgrading Drush commands in modules.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that's a long long ways off, but folks are very slow at upgrading Drush commands in modules.

This is something that leads to exactly the opposite conclusion: If they're slow to adopt changes, then we should deprecate as soon as possible, giving them enough time to take action. We can change the removal version from 11.0.0 to 12.0.0 but the deprecation should occur now. Deprecating doesn't mean the command doesn't work. Also note that this is a muted deprecation @trigger_error(...), so there should be no noise in console. Normally code deprecation tests should catch this error but that's fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, deprecation is postponed.

@greg-1-anderson
Copy link
Member

My last comment is that maybe we should note in the documentation that this new loading mechanism is experimental, and subject to change until Drush 10.5 or 11.0 is tagged.

@greg-1-anderson
Copy link
Member

I realize that it's early for this PR to deprecate the drush.commands discovery method, as this PR does not provide dependency injection for discovered commands, whereas drush.commands does.

I think this PR is still good to merge; we can add DI as follow-on work. We should back out the deprecation, though.

We could potentially deprecate auto-discovery by location (__DRUPAL_ROOT__ . /drush), potentially.

@claudiu-cristea
Copy link
Member Author

I realize that it's early for this PR to deprecate the drush.commands discovery method, as this PR does not provide dependency injection for discovered commands, whereas drush.commands does.

Not sure it provides DI but, yes, let's drop the deprecation for now, it needs more analysis.

claudiu-cristea and others added 2 commits March 21, 2021 20:11
Co-authored-by: Claudiu Cristea <clau.cristea@gmail.com>
@greg-1-anderson
Copy link
Member

I guess I'm not that opposed to AutoloaderAwareTrait.

@weitzman weitzman merged commit 09ef1ac into 10.x Mar 22, 2021
@weitzman weitzman deleted the autodiscover-3rd-party-commands branch March 22, 2021 03:55
@AdamPS
Copy link
Contributor

AdamPS commented Apr 7, 2021

Many thanks I confirm this satisfies my requirement mentioned in #4641

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants