drush-ops / drush

Drush is a command-line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those who spend their working hours hacking away at the command prompt.
https://www.drush.org
2.34k stars 1.08k forks source link

Implement shell hooks #3719

Open geek-merlin opened 6 years ago

geek-merlin commented 6 years ago

Is your feature request related to a problem? Please describe.

As a deployment architect, i want to connect different components of my deployment workflow without PHP coding.

Describe the solution you'd like

In drush.yml (or another sensible place):

shell-hooks:
  sql-dump:
    post-command:
      - ../vendor/bin/my-custom-script.sh
  code-deploy: # Custom
    post-command:
      - ../vendor/bin/drush $TARGET cim -y

And then in our shell deployment script (this is the easy part):

#!/bin/bash
# ... [do deployment]
drush fire-hook code-deploy post-command

Describe alternatives you've considered

Currently we're coding PHP, which is tedious for small issues.

Additional context

For us, and presumably many others, this will make a huge increase in the usefulness of drush. We'd be able to maintain deployment config with other drush config.

Note that at least lando and ddev implement shell hooks like this for their platforms.

Alas, if drush does not leverage the idea, doing this in contrib would need an equivalent of hook_module_implements_alter for the HookManager, to register the config stuff there.

weitzman commented 6 years ago

I think I prefer this to start in Contrib, instead of Drush core. See https://github.com/consolidation/annotated-command#hooks for the available hooks. You could make a Drush commandfile that reads the yml file (could be in drush config or separate) and executes shell commands during each hook implementation.

Also see related issue #2943

greg-1-anderson commented 6 years ago

Yeah, 👍 on this. This could be implemented in contrib. It would make sense to do this and #2943 together.

geek-merlin commented 6 years ago

Cool you like it too. And good thing to start it in contrib and learn from that.

I might well do that when it itches a bit more.

You could make a Drush commandfile that reads the yml file and executes shell commands during each hook implementation.

That's simple enough in principle. But as noted in the IS, i'd approach this by altering the HookManager's implementations, and have not yet groked where i find some early hook (that gets called with every command) to do this. (Note that we want to catch both command and custom hooks.)

greg-1-anderson commented 6 years ago

In your CommandFile, use @hook pre-init * to declare a hook that is called at the beginning of each command's execution. Perhaps the CommandFile constructor might be a better place. In either event, use \Drush\Drush::service('hookManager') to get a reference to the hook manager.

I think you should do it the way @weitzman suggested. Read the yaml file, and then add hooks of the appropriate type based on what you find there. The existing implementation of the HookManager isn't well-suited to doing it the way that you suggest above.

geek-merlin commented 6 years ago

Gee, i did not notice the possibility of wildcard hooks! Thanks for the pointer. I'll eventually work on this when it itches...

weitzman commented 6 years ago

Feeling itchy yet? Note the new Drush::process() which may be a good way to run each line.

Hoping someone takes this on.

ademarco commented 5 years ago

We did something similar in our Robo-based Task Runner, there you can create Robo commands in YAML, for ex.:

commands:
  drupal:site-setup:
    - { task: "chmod", file: "${drupal.root}/sites", permissions: 0774, recursive: true }
    - { task: "symlink", from: "../../custom/modules", to: "${drupal.root}/modules/custom" }
    - { task: "symlink", from: "../../custom/themes", to: "${drupal.root}/themes/custom" }
    - { task: "run", command: "drupal:drush-setup" }
    - { task: "run", command: "drupal:settings-setup" }
    - { task: "run", command: "setup:behat" }
    - "./vendor/bin/drush --root=$(pwd)/${drupal.root} cr"
  setup:behat:
    - { task: "process", source: "behat.yml.dist", destination: "behat.yml" }

In this case we could support two root properties:

hooks:
   ...
commands:
   ...

Hooks will allow a list of commands to run before and/or after existing Drush commands, and commands will be just convenience commands, as the example above.

If the proposed approach is interesting we could work on it as a contrib project.

geek-merlin commented 5 years ago

@ademarco I did not work with Robo and TaskRunner, but it looks like it gives me more scripting power in the first place. Also i have no strong opinion if the hooks are on drush, Robo, or TaskRunner side (someone who already combined them might have).

I'm really interested! Sort things out in a dedicated issue?

weitzman commented 4 years ago

Sort things out here! ... I still think this would be nice to have.

geek-merlin commented 4 years ago

Ack. FYI: I'm making some experiments to extend composer scripts to hooks, it looks like this is not far to go. But TBH, it's currently a research project, so no ETA.