captainhookphp / captainhook

CaptainHook is a very flexible git hook manager for software developers that makes sharing git hooks with your team a breeze.
http://captainhook.info
MIT License
1.01k stars 87 forks source link

Docker mode not working? #239

Closed aruku closed 7 months ago

aruku commented 8 months ago

I work on a Windows machine using WSL; PHP only exists in my containers. Also, the project structure on the host is like this: /home/eduardo/project/app (with .git at the same level), while in the container that is mapped to /workspace. I added a new volume under /workspace/.git to include the Git directory, so that the hooks can be installed. The main config file lives in /home/eduardo/project/app/captainhook.json (/workspace/captainhook.json), and I have defined another one in /home/eduardo/project/captainhook.json (not visible for the container), that simply includes the main one and tells CaptainHook to use Docker:

{
    "config": {
        "includes": [
            "app/captainhook.json"
        ],
        "run": {
            "mode": "docker",
            "exec": "docker exec -i pvet_php",
            "path": "bin/captainhook"
        }
    }
}

The hooks work as expected in the container; however, this Docker config doesn't.

Am I missing something? Is this use case even possible?

Thank you in advance.

sebastianfeldmann commented 8 months ago

What's the error message you get?

Check for example .git/hooks/pre-push if the path the Cap'n generated are correct.

aruku commented 8 months ago

Sorry, I just realized I didn't add that. In the host, where the IDE is, I get the following error: .git/hooks/pre-commit: 7: bin/captainhook: not found That is the right path for inside the container.

sebastianfeldmann commented 8 months ago

So, make sure your hook scripts contain the actual docker command.

cat .git/hooks/pre-push

should look like this

#!/bin/sh

# installed by CaptainHook 5.22.1

# read original hook stdIn to pass it in as --input option
input=$(cat)

if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then
        exec < /dev/tty
fi

docker exec -i my-container-name ./bin/captainhook --bootstrap=vendor/autoload.php --input="$input" hook:pre-push "$@"

If your hook scripts do not actually contain the docker command, its because your configuration is broken. Try to configure the run settings like this.

{
    "config": {
        "verbosity": "verbose",
        "ansi-colors": true,
        "includes": [],
        "run-mode": "docker",
        "run-exec": "docker exec my-container-name",
        "run-cmd": "bin/captainhook",
        "bootstrap": "vendor/autoload.php"
    },
    ...
}
aruku commented 8 months ago

I was using 5.21.2, which by default wouldn't overwrite the hooks, so I wasn't seeing the proper changes if I didn't uninstall the hooks beforehand. 🤦 The problem now is that if composer install is ran in the container, as our bootstrapping does, the hooks are configured without the Docker command and won't work in the host. Can hook-installer deal with this use case too somehow?

sebastianfeldmann commented 8 months ago

If you want to execute the same hooks from outside and inside the container sadly not.

It is important that the configuration you use to install must have the correct run-mode configuration otherwise the default version will be installed, and that is not what you want.

aruku commented 8 months ago

I can live without being able to commit directly in the container, but the real problem will be CI: the pipeline doesn't use our containers. If you or anybody else has any suggestions about what to do in this scenario, I'd appreciate it.

EDIT: Maybe read an environment variable during installation to tell it what config to use? That way, the CI pipeline could use one value and my computer a different one?

PD: what is the shell mode? It still uses PHP, right?

sebastianfeldmann commented 8 months ago

There are multiple ways to make sure you do not execute hooks in CI

The shell mode writes shell scripts to you hook directory. This shell script calls the PHP directly. The docker mode writes similar shell scripts, the difference being that docker is called instead of PHP.

aruku commented 8 months ago

Ahhh, good. I found another env variable this morning but not that one. Are all of them listed somewhere? I can't find them.

One last question: what is the difference between the shell and local modes? They seem to output the same hook.

Thank you for all your help!

sebastianfeldmann commented 7 months ago

Legacy naming party ;)