captainhook icon indicating copy to clipboard operation
captainhook copied to clipboard

enable user input for prepush

Open labya opened this issue 1 year ago • 4 comments
trafficstars

i want to have a prompt to confirm the push on a branch

labya avatar Feb 29 '24 15:02 labya

I'm not sure you can receive input via stdIn (which pre-push does) and still ask for user input. I remember trying this and not getting it to work. That's why I only allow user input for hooks that do not receive data via stdIn. Have you actually tried running it with your changes?

sebastianfeldmann avatar Feb 29 '24 15:02 sebastianfeldmann

hi,

yeah i tried and it's work :)

Here my captainhook.json :

"pre-push": {
        "enabled": true,
        "actions": [
          {
            "action": "\\scripts\\CaptainHook\\HookPrePush"
          }
        ]
    },

And my class HookPrePush.php

<?php

namespace scripts\CaptainHook;

use CaptainHook\App\Config;
use CaptainHook\App\Config\Action as ConfigAction;
use CaptainHook\App\Console\IO;
use CaptainHook\App\Hook\Action;
use SebastianFeldmann\Git\Repository;

/**
 *
 */
class HookPrePush implements Action {

  /**
   * Execute the action.
   *
   * @param  \CaptainHook\App\Config           $config
   * @param  \CaptainHook\App\Console\IO       $console_io
   * @param  \SebastianFeldmann\Git\Repository $repository
   * @param  \CaptainHook\App\Config\Action    $action
   * @return void
   * @throws \Exception
   */
  public function execute(
    Config $config,
    IO $console_io,
    Repository $repository,
    ConfigAction $action
  ) : void {
    $show_branch = sprintf(
      'git -C %s %s',
      $repository->getRoot(),
      'branch --show-current'
    );
    $branch = trim(shell_exec($show_branch));
    if ($branch === 'master') {
      $response = $console_io
        ->ask('Are you sure you want to push to ' . $branch . '? (y/n): ', 'n');
      if (strtolower(trim($response)) !== 'y') {
        throw new \Exception('Push aborted.');
      }
    }
  }

}

with this PR, the file .git/hooks/pre-push are now :

#!/bin/sh

# installed by CaptainHook 5.21.2

INTERACTIVE="--no-interaction"
if [ -t 1 ]; then
    # If we're in a terminal, redirect stdout and stderr to /dev/tty and
    # read stdin from /dev/tty. Allow interactive mode for CaptainHook.
    exec >/dev/tty 2>/dev/tty </dev/tty
    INTERACTIVE=""
fi

vendor/bin/captainhook $INTERACTIVE --configuration=captainhook.json --bootstrap=vendor/autoload.php hook:pre-push "$@"

it would be nice to have a parameter to populate the $hooksAllowingUserInput array via captainhook.json

labya avatar Feb 29 '24 15:02 labya

Ah, I see, you are not reading any data from stdIn before. Some conditions read some data from stdIn for pre-push.

Thanks for the example I will try this in combination with some code that requires the stdIn stuff to work as well.

sebastianfeldmann avatar Feb 29 '24 15:02 sebastianfeldmann

So far I could not get it to work to read from stdIn and tty. Since it doesn't seem to be possible to change the stdIn file descriptor from PHP.

I'm thinking of allowing user input and how to reliably do it for a while now.

So here is what I'm going to do. First I will not merge this pull request, since it would break other functionality. But I will make some changes that should allow user input for all hooks.

For this to work I have to use the hook script to actually read the default git stdIn and pass it to CaptainHook as argument or option so the Cap'n can always use the tty.

This will not work with the pure PHP installation method were no shell script is used to execute the Captain. I would hope that no one is still using this variant, it's some very old stuff from the early days. Nevertheless I will still invest some more time to make the impact for people using it as pain free as possible.

So it will take maybe a day or two more to get something released that could solve your issue.

sebastianfeldmann avatar Mar 02 '24 20:03 sebastianfeldmann

I just released version 5.22.0

It contains an Action to prompt the user for confirmation. You can configure it like this:

            {
                "action": "\\CaptainHook\\App\\Hook\\UserInput\\AskConfirmation",
                "options": {
                    "message": "Do you really want it? [yes|no]",
                    "default": true
                },
                "config": {
                    "label": "User confirmation!"
                }
            }

User input should be possible for all hooks now as long as you use run-mode shell or docker. In run-mode php user input does not work for pre-push and post-rewrite because of the stdIn handling if git.

sebastianfeldmann avatar Mar 06 '24 11:03 sebastianfeldmann