Skip to content

Split hook executor boundaries - #184

Merged
errfld merged 2 commits into
mainfrom
gh-183/executor-boundaries
Jun 29, 2026
Merged

Split hook executor boundaries#184
errfld merged 2 commits into
mainfrom
gh-183/executor-boundaries

Conversation

@errfld

@errfld errfld commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Split the core hook executor facade into cohesive private modules for runner, scheduler, summary, and redaction responsibilities.
  • Kept the public executor API stable, including execute_hook_with_summary, HookRunSummary, and CommandPhase.
  • Preserved the existing behavior tests while moving implementation boundaries under executor/.

Fixes #183

Validation

  • Baseline before refactor: cargo test -p git-smee-core executor::tests::given_summary_success_when_rendering_then_counts_phases_and_durations -- --nocapture
  • cargo test -p git-smee-core
  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test -p git-smee-cli --test cli_integration
  • cargo test --workspace --all-targets --all-features

Summary by CodeRabbit

  • Bug Fixes

    • Improved hook execution reliability across platforms, including better handling of command arguments, quoted values, and input piping.
    • More accurately reports failed, skipped, and terminated hook runs, with clearer first-failure output.
  • New Features

    • Added more detailed hook run summaries, including execution counts, durations, and per-run status information.
    • Parallel and sequential hook execution is now tracked separately for clearer results.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@errfld, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 46 minutes

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable usage-based reviews in Billing to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information, and refer to the rate limits docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4cf69bc0-ed7f-43bf-9176-61d09916a9e8

📥 Commits

Reviewing files that changed from the base of the PR and between 8087479 and a87aeb6.

📒 Files selected for processing (2)
  • crates/git-smee-core/src/executor.rs
  • crates/git-smee-core/src/executor/runner.rs
📝 Walkthrough

Walkthrough

executor.rs (previously ~1525 lines) is split into four submodules: redaction.rs (quote-aware tokenizer and command redaction), runner.rs (CommandRunner trait and PlatformCommandRunner), scheduler.rs (sequential/parallel hook scheduling), and summary.rs (CommandPhase, CommandRun, HookRunSummary). The parent module now declares, wires, and re-exports from these submodules.

Changes

Executor submodule extraction

Layer / File(s) Summary
Summary types
crates/git-smee-core/src/executor/summary.rs
Defines CommandPhase, CommandOutcome, CommandRun, HookRunSummary with query/formatting/error-conversion API and format_duration utility.
Command redaction
crates/git-smee-core/src/executor/redaction.rs
Implements redact_command with a quote-aware tokenizer, inline env-assignment detection, and env-var-name validation.
CommandRunner and platform execution
crates/git-smee-core/src/executor/runner.rs
Defines CommandRunner trait and PlatformCommandRunner implementing Unix and Windows command construction (temp .cmd script, hook-arg env injection via apply_hook_arg_env/is_hook_arg_env_key, stdin piping, process wait, Windows path/quoting helpers).
Hook scheduler
crates/git-smee-core/src/executor/scheduler.rs
Partitions hooks into sequential and parallel sets, runs them via CommandRunner, records CommandRun outcomes into HookRunSummary, and exposes a test-only execute_command helper.
Module wiring
crates/git-smee-core/src/executor.rs
Declares the four submodules, updates imports, re-exports CommandPhase/HookRunSummary from summary, and updates test use statements.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • errfld/git-smee#30: Introduced CommandRunner::shell_display and spawn-failure reporting, the same trait and method now extracted into executor/runner.rs.
  • errfld/git-smee#56: Implemented the same quote-aware tokenization and KEY=value inline-env detection for command redaction, now relocated to executor/redaction.rs.
  • errfld/git-smee#153: Added HookRunSummary and CommandPhase types that this PR moves into the new executor/summary.rs submodule.

Poem

🐇 One file grew wide, a warren too long,
So I dug four tunnels where each part belongs.
Redaction hops left, the runner hops right,
The scheduler schedules, the summary writes.
Tidy burrows now, everything neat—
A refactor complete, with no change to the feat!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main refactor: splitting hook executor boundaries.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gh-183/executor-boundaries

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/git-smee-core/src/executor.rs`:
- Around line 150-155: The extracted-module tests in executor are still reaching
into redaction, runner, scheduler, and summary internals from the parent module.
Move each related test block into the owning module files, using the existing
symbols redact_command, apply_hook_arg_env, is_hook_arg_env_key,
windows_cmd_quote_hook_arg, windows_command_script, execute_command,
CommandOutcome, and CommandRun to place them beside the implementation they
verify. Keep the behavior coverage the same, but relocate the tests into
redaction.rs, runner.rs, scheduler.rs, and summary.rs so each module owns its
own tests.
- Line 12: The executor facade currently re-exports HookRunSummary and
CommandPhase, but CommandRun is still hidden while
HookRunSummary::first_failure() exposes it in its return type. Update the public
surface in executor::executor.rs by re-exporting CommandRun from the summary
module, or change HookRunSummary::first_failure() to return a public facade type
so the method signature no longer leaks a private type.

In `@crates/git-smee-core/src/executor/runner.rs`:
- Around line 107-130: The Windows hook-arg quoting in
windows_cmd_quote_hook_arg only wraps arguments in quotes, so cmd metacharacters
like % and ! can still expand before the .cmd script receives them. Update the
Windows path in runner.rs to escape cmd metacharacters in addition to quoting,
and ensure append_windows_hook_args still passes each hook argument through the
revised helper. Add test coverage for literal %VAR% and !VAR! arguments to
verify they remain unchanged when executed through the Windows command path.

In `@crates/git-smee-core/src/executor/summary.rs`:
- Around line 65-70: `HookRunSummary::first_failure` currently exposes
`&CommandRun` even though `CommandRun` is not publicly reachable from
`git_smee_core::executor`, so downstream users cannot use the return type
cleanly. Fix this by either re-exporting `CommandRun` from the public executor
API or making `first_failure` non-public/removing it if it should remain
internal; update the `HookRunSummary` and `CommandRun` visibility boundaries in
`executor::summary` accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1dd438c7-cd9a-4395-8f9f-1b6b605e9155

📥 Commits

Reviewing files that changed from the base of the PR and between 76146d8 and 8087479.

📒 Files selected for processing (5)
  • crates/git-smee-core/src/executor.rs
  • crates/git-smee-core/src/executor/redaction.rs
  • crates/git-smee-core/src/executor/runner.rs
  • crates/git-smee-core/src/executor/scheduler.rs
  • crates/git-smee-core/src/executor/summary.rs

Comment thread crates/git-smee-core/src/executor.rs Outdated
Comment on lines +150 to +155
use super::redaction::redact_command;
use super::runner::{
apply_hook_arg_env, is_hook_arg_env_key, windows_cmd_quote_hook_arg, windows_command_script,
};
use super::scheduler::execute_command;
use super::summary::{CommandOutcome, CommandRun};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Move extracted-module tests next to the modules they exercise.

These imports pull redaction, runner, scheduler, and summary internals back into the parent test module. Move the relevant test blocks into redaction.rs, runner.rs, scheduler.rs, and summary.rs so the new boundaries own their behavior tests. As per coding guidelines, “Add tests in git-smee-core close to the implemented modules.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/git-smee-core/src/executor.rs` around lines 150 - 155, The
extracted-module tests in executor are still reaching into redaction, runner,
scheduler, and summary internals from the parent module. Move each related test
block into the owning module files, using the existing symbols redact_command,
apply_hook_arg_env, is_hook_arg_env_key, windows_cmd_quote_hook_arg,
windows_command_script, execute_command, CommandOutcome, and CommandRun to place
them beside the implementation they verify. Keep the behavior coverage the same,
but relocate the tests into redaction.rs, runner.rs, scheduler.rs, and
summary.rs so each module owns its own tests.

Source: Coding guidelines

Comment thread crates/git-smee-core/src/executor/runner.rs
Comment thread crates/git-smee-core/src/executor/summary.rs
@errfld

errfld commented Jun 29, 2026

Copy link
Copy Markdown
Owner Author

Addressed review feedback in follow-up commit a87aeb6:

  • Re-exported CommandRun from the executor facade so HookRunSummary::first_failure() exposes a publicly reachable type.
  • Hardened Windows hook-argument quoting for %VAR%, !VAR!, and caret literals, with focused regression coverage.

Local validation after the follow-up:

  • cargo test -p git-smee-core windows_hook_arg -- --nocapture
  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --workspace --all-targets --all-features

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== PR head and changed files =="
gh pr view 184 --repo errfld/git-smee --json headRefOid,baseRefName,headRefName,files \
  --jq '{headRefOid, baseRefName, headRefName, files: [.files[].path]}'

echo
echo "== Diffstat vs base =="
git fetch --quiet origin "$(gh pr view 184 --repo errfld/git-smee --json baseRefName --jq .baseRefName)"
BASE_REF="$(gh pr view 184 --repo errfld/git-smee --json baseRefName --jq .baseRefName)"
git diff --stat "origin/$BASE_REF...HEAD"

echo
echo "== Outline: crates/git-smee-core/src/executor.rs =="
ast-grep outline crates/git-smee-core/src/executor.rs --view expanded || true

echo
echo "== Outline: crates/git-smee-core/src/executor/runner.rs =="
ast-grep outline crates/git-smee-core/src/executor/runner.rs --view expanded || true

echo
echo "== Relevant diff hunks for executor facade and runner =="
git diff --unified=80 "origin/$BASE_REF...HEAD" -- \
  crates/git-smee-core/src/executor.rs \
  crates/git-smee-core/src/executor/runner.rs \
  crates/git-smee-core/src/executor/summary.rs \
  crates/git-smee-core/src/executor/scheduler.rs \
  crates/git-smee-core/src/executor/redaction.rs

echo
echo "== Search for CommandRun re-export and first_failure signature =="
rg -n -C3 'pub use .*CommandRun|first_failure\(' crates/git-smee-core/src/executor.rs crates/git-smee-core/src/executor/summary.rs

echo
echo "== Search for Windows hook arg quoting tests and implementation =="
rg -n -C4 'windows_cmd_quote_hook_arg|windows_hook_arg|%VAR%|!VAR!|\^' crates/git-smee-core/src/executor/runner.rs crates/git-smee-core/src/executor.rs

Length of output: 73757


@errfld Thanks — I checked the follow-up in a87aeb6, and the two issues I raised look addressed.

  • crates/git-smee-core/src/executor.rs now re-exports CommandRun, so HookRunSummary::first_failure() returns a publicly reachable type.
  • crates/git-smee-core/src/executor/runner.rs now hardens Windows quoting for ^, %, and !, and the focused tests cover the key literal-expansion cases.

I didn’t spot any new concerns in the touched executor modules from this follow-up. I’ll kick off a fresh review on the latest commit.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@errfld
errfld dismissed coderabbitai[bot]’s stale review June 29, 2026 06:30

Dismissed as stale: review comments fixed in a87aeb6; CodeRabbit status and CI now pass.

@errfld
errfld merged commit 1d26a47 into main Jun 29, 2026
28 checks passed
@errfld
errfld deleted the gh-183/executor-boundaries branch June 29, 2026 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split hook executor into runner, scheduler, summary boundaries

2 participants