Skip to content

Fix git hook GrumPHP command resolution for global installs#332

Merged
coisa merged 3 commits into
mainfrom
chore/331-fix-git-hooks-grumphp-binary
May 11, 2026
Merged

Fix git hook GrumPHP command resolution for global installs#332
coisa merged 3 commits into
mainfrom
chore/331-fix-git-hooks-grumphp-binary

Conversation

@coisa
Copy link
Copy Markdown
Contributor

@coisa coisa commented May 11, 2026

Closes #331

Summary

  • Update packaged hook templates (GrumPHP detected a pre-commit command.
    GrumPHP is sniffing your code!

! [NOTE] Running testsuite: git_pre_commit

Running tasks with priority 0!

Running task 1/5: composer_script...
Running task 2/5: composer...
Running task 3/5: phplint...
Running task 4/5: jsonlint...
Running task 5/5: yamllint...

Running task 1/5: composer_script...
Running task 2/5: composer...
Running task 3/5: phplint...
Running task 4/5: jsonlint...
Running task 5/5: yamllint...

GrumPHP detected a pre-commit command.
GrumPHP is sniffing your code!

! [NOTE] Running testsuite: git_pre_commit

Running tasks with priority 0!

Running task 1/5: composer_script...
Running task 2/5: composer...
Running task 3/5: phplint...
Running task 4/5: jsonlint...
Running task 5/5: yamllint...

Running task 1/5: composer_script...
Running task 2/5: composer...
Running task 3/5: phplint...
Running task 4/5: jsonlint...
Running task 5/5: yamllint... , ) to avoid hardcoded GrumPHP 2.20.0

Usage:
command [options] [arguments]

Options:
-h, --help Display help for the given command. When no command is given display help for the list command
--silent Do not output any message
-q, --quiet Only errors are displayed. All other output is suppressed
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-c, --config=CONFIG Path to config
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
completion Dump the shell completion script
configure Create a grumphp configuration file
help Display help for a command
list List commands
run Run configured tasks
git
git:commit-msg Executed by the commit-msg commit hook
git:deinit Removes the commit hooks
git:init Registers the Git hooks
git:pre-commit Executed by the pre-commit hook.

  • Add resilient fallback resolution: GrumPHP 2.20.0

Usage:
command [options] [arguments]

Options:
-h, --help Display help for the given command. When no command is given display help for the list command
--silent Do not output any message
-q, --quiet Only errors are displayed. All other output is suppressed
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-c, --config=CONFIG Path to config
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
completion Dump the shell completion script
configure Create a grumphp configuration file
help Display help for a command
list List commands
run Run configured tasks
git
git:commit-msg Executed by the commit-msg commit hook
git:deinit Removes the commit hooks
git:init Registers the Git hooks
git:pre-commit Executed by the pre-commit hook -> GrumPHP 2.20.0

Usage:
command [options] [arguments]

Options:
-h, --help Display help for the given command. When no command is given display help for the list command
--silent Do not output any message
-q, --quiet Only errors are displayed. All other output is suppressed
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-c, --config=CONFIG Path to config
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
completion Dump the shell completion script
configure Create a grumphp configuration file
help Display help for a command
list List commands
run Run configured tasks
git
git:commit-msg Executed by the commit-msg commit hook
git:deinit Removes the commit hooks
git:init Registers the Git hooks
git:pre-commit Executed by the pre-commit hook -> GrumPHP 2.20.0

Usage:
command [options] [arguments]

Options:
-h, --help Display help for the given command. When no command is given display help for the list command
--silent Do not output any message
-q, --quiet Only errors are displayed. All other output is suppressed
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-c, --config=CONFIG Path to config
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
completion Dump the shell completion script
configure Create a grumphp configuration file
help Display help for a command
list List commands
run Run configured tasks
git
git:commit-msg Executed by the commit-msg commit hook
git:deinit Removes the commit hooks
git:init Registers the Git hooks
git:pre-commit Executed by the pre-commit hook in PATH.

  • Keep existing precedence for configuration file selection ( then managed fallback) unchanged.
  • Extend packaged hook tests to assert new runtime path resolution.

Context

This is an intermediate stabilization step before implementing #296 (Git hook extraction into dedicated package).

@coisa coisa force-pushed the chore/331-fix-git-hooks-grumphp-binary branch from 5084336 to 399cbb2 Compare May 11, 2026 19:46
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 01fc65c5-b00d-47c7-861f-3f6ee7852897

📥 Commits

Reviewing files that changed from the base of the PR and between 60ea8d4 and cf8045f.

📒 Files selected for processing (5)
  • .github/wiki
  • resources/git-hooks/commit-msg
  • resources/git-hooks/pre-commit
  • src/Config/ECSConfig.php
  • tests/GitHooks/PackagedHooksTest.php

📝 Walkthrough

Summary by CodeRabbit

  • Improvements

    • Git commit and pre-commit hooks now dynamically resolve the GrumPHP executable with fallbacks, and execute it once to avoid duplicate runs.
  • Configuration Changes

    • Removed the "strict" prepared set from the default coding-style configuration.
  • Tests

    • Packaged hook tests expanded to verify the new executable-resolution and invocation behavior.
  • Chores

    • Updated the pinned wiki subproject reference.

Walkthrough

Updates packaged git hooks to prefer vendor/bin/grumphp, then vendor/bin/grumphp.phar, then grumphp from PATH; removes the strict prepared set from ECSConfig defaults; updates the .github/wiki subproject pointer. Tests expanded to assert new hook command resolution and invocation.

Changes

Resilient GrumPHP binary resolution in git hooks

Layer / File(s) Summary
Pre-commit hook executable selection and execution
resources/git-hooks/pre-commit
Pre-commit hook selects the first available GrumPHP binary (vendor/bin/grumphp, vendor/bin/grumphp.phar, grumphp), pipes staged diff into it for git:pre-commit with --skip-success-output, and conditionally adds --config.
Commit-msg hook executable selection and execution
resources/git-hooks/commit-msg
Commit-msg hook resolves GrumPHP command in the same precedence order, pipes the diff into it, runs git:commit-msg with --git-user/--git-email, and conditionally appends --config.
Hook test assertions for binary resolution
tests/GitHooks/PackagedHooksTest.php
Tests assert that packaged pre-commit and commit-msg scripts detect an executable vendor/bin/grumphp, set GRUMPHP_COMMAND accordingly, and invoke it via `printf "%s\n" "${DIFF}"

Remove strict prepared set from ECSConfig defaults

Layer / File(s) Summary
ECSConfig prepared sets and method updates
src/Config/ECSConfig.php
Removed strict from DEFAULT_PREPARED_SETS type and value; applyDefaultRulesAndSets() no longer includes strict in the ->withPreparedSets(...) call.

Wiki subproject reference update

Layer / File(s) Summary
Wiki subproject commit reference
.github/wiki
Updated the wiki subproject pointer to a new pinned commit SHA.

Sequence Diagram(s)

sequenceDiagram
  participant HookScript
  participant Selector as GRUMPHP_COMMAND_Selector
  participant GrumPHP as GrumPHP_Executable
  participant Git as Git_Target
  HookScript->>Selector: check vendor/bin/grumphp -> vendor/bin/grumphp.phar -> grumphp
  Selector->>HookScript: export GRUMPHP_COMMAND
  HookScript->>GrumPHP: printf "%s\n" "${DIFF}" | exec "${GRUMPHP_COMMAND}" git:<hook> [--config args]
  GrumPHP->>Git: execute git:<hook> target
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I sniffed the hooks from root to bin,
I choose the local first, then fall back in,
A strict rule hid, now quietly gone,
Wiki pointer hops to a fresher dawn,
I munch a carrot, tests pass — I'm on!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/331-fix-git-hooks-grumphp-binary
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch chore/331-fix-git-hooks-grumphp-binary

Comment @coderabbitai help to get the list of available commands and usage tips.

github-actions Bot added a commit that referenced this pull request May 11, 2026
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

require_once $autoloadCandidate;
exit(ContainerFactory::get(DevTools::class)->run());

P1 Badge Preserve compatibility when project autoload lacks ContainerFactory

When the global binary runs inside a project, this script loads the project autoloader first, then unconditionally calls ContainerFactory::get(...). Projects pinned to an older fast-forward/dev-tools release (before ContainerFactory existed) will fatal with Class "FastForward\DevTools\Container\ContainerFactory" not found, so the CLI cannot run at all in mixed-version setups. This is a regression from the previous DevTools::create() bootstrap path, which remained compatible with older project installs.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coisa coisa force-pushed the chore/331-fix-git-hooks-grumphp-binary branch 2 times, most recently from 5084336 to 322b9fa Compare May 11, 2026 19:56
@github-actions
Copy link
Copy Markdown
Contributor

@coisa coisa merged commit b2c27ec into main May 11, 2026
12 checks passed
@coisa coisa deleted the chore/331-fix-git-hooks-grumphp-binary branch May 11, 2026 19:58
@github-project-automation github-project-automation Bot moved this from Backlog to Released in PHP Fast Forward Project May 11, 2026
github-actions Bot added a commit that referenced this pull request May 11, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 322b9fa17a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +36 to +40
if [ -n "${GRUMPHP_CONFIG_FILE}" ]; then
printf "%s\n" "${DIFF}" | exec "${GRUMPHP_COMMAND}" '--config' "${GRUMPHP_CONFIG_FILE}" 'git:pre-commit' '--skip-success-output'
fi

printf "%s\n" "${DIFF}" | exec "${GRUMPHP_COMMAND}" 'git:pre-commit' '--skip-success-output'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid unconditional second pre-commit GrumPHP execution

After the configured invocation runs, the script always falls through to a second git:pre-commit call without --config. In environments where /bin/sh executes pipeline segments in subshells (common with dash/bash), the first exec does not terminate the parent script, so this second call still runs and can fail when the default config is absent (a typical global-install case), causing commits to be blocked even though the configured run succeeded.

Useful? React with 👍 / 👎.

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

Labels

enhancement New feature or request

Projects

Status: Released

Development

Successfully merging this pull request may close these issues.

Use resilient GrumPHP binary resolution in packaged git hooks

1 participant