Skip to content

CLI-248 git hooks#160

Open
kirill-knize-sonarsource wants to merge 1 commit intotask/kk/CLI-244-245-callback-infrastructurefrom
task/kk/CLI-248-git-hooks
Open

CLI-248 git hooks#160
kirill-knize-sonarsource wants to merge 1 commit intotask/kk/CLI-244-245-callback-infrastructurefrom
task/kk/CLI-248-git-hooks

Conversation

@kirill-knize-sonarsource
Copy link
Copy Markdown
Member

No description provided.

@hashicorp-vault-sonar-prod hashicorp-vault-sonar-prod bot changed the title Task/kk/cli 248 git hooks CLI-280 Task/kk/cli 248 git hooks Apr 8, 2026
@sonar-review-alpha
Copy link
Copy Markdown
Contributor

sonar-review-alpha bot commented Apr 8, 2026

Summary

What changed: Refactored git hook logic from shell scripts to TypeScript callback handlers. Previously, pre-commit and pre-push hooks contained inline shell logic for scanning staged/pushed files for secrets. This PR moves that logic into two new TypeScript commands: sonar hook git-pre-commit and sonar hook git-pre-push.

Why: Maintains feature parity while improving maintainability, testability, and consistency with the callback infrastructure pattern established in CLI-244-245. The implementation is now easier to evolve and test compared to embedded shell scripts.

What's new:

  • git-pre-commit.ts: Scans staged files via git diff --cached, skipping gracefully if not authenticated or if the secrets binary isn't installed
  • git-pre-push.ts: Scans files in new commits, with logic to handle branch deletions and new branches (comparing against empty tree when needed)
  • stdin.ts: Utilities for reading git push refs from stdin and parsing JSON payloads, with 5-second timeout to prevent hanging
  • Shell scripts simplified: Now just resolve the binary path and invoke the CLI callback instead of doing the work inline
  • Enhanced spawnProcess to support writing data to stdin (used by pre-push to generate empty tree with git mktree)
  • Registered two new hook commands in command-tree.ts

What reviewers should know

Start here:

  1. Read the shell script changes in git-shell-fragments.ts to see how hooks went from ~50 lines of script logic to 1 line calling the CLI
  2. Review git-pre-commit.ts — straightforward implementation that mirrors the old shell logic
  3. Review git-pre-push.ts — more complex, handles three scenarios: branch deletion (skip), existing branch (diff two SHAs), and new branch (special handling with empty tree or rev-list)

Key implementation details:

  • Both handlers silently return on auth failure or missing binary (fail-open: push/commit proceeds)
  • git-pre-push must handle empty tree creation for new branches pushed when no other remotes exist (getEmptyTree() helper)
  • stdin.ts provides two paths: raw stdin reading with timeout (for git hook refs), and JSON parsing (for future hooks)
  • The timeout prevents hooks from hanging indefinitely waiting for stdin

For reviewers:

  • File changes are isolated: hook handlers → command registration → shell script simplification → utils
  • Tests are comprehensive: unit tests for the logic, integration tests for end-to-end scenarios
  • Behavior is unchanged — this is a like-for-like refactor of existing functionality, not new features

  • Generate Walkthrough
  • Generate Diagram

🗣️ Give feedback

@hashicorp-vault-sonar-prod
Copy link
Copy Markdown

hashicorp-vault-sonar-prod bot commented Apr 8, 2026

CLI-280

sonar-review-alpha[bot]

This comment was marked as resolved.

@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-244-245-callback-infrastructure branch 2 times, most recently from e5bc9f8 to 6f2f053 Compare April 8, 2026 19:17
sonar-review-alpha[bot]

This comment was marked as outdated.

@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-244-245-callback-infrastructure branch from 6f2f053 to aa6bc64 Compare April 8, 2026 19:58
@kirill-knize-sonarsource kirill-knize-sonarsource changed the title CLI-280 Task/kk/cli 248 git hooks CLI-280 git hooks Apr 8, 2026
@kirill-knize-sonarsource kirill-knize-sonarsource changed the title CLI-280 git hooks CLI-248 git hooks Apr 8, 2026
@kirill-knize-sonarsource kirill-knize-sonarsource changed the base branch from task/kk/CLI-244-245-callback-infrastructure to task/kk/CLI-247-post-tool-use April 8, 2026 20:05
sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as resolved.

@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-247-post-tool-use branch 2 times, most recently from e2211ff to 581f8af Compare April 8, 2026 21:02
@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-248-git-hooks branch 2 times, most recently from dc076f4 to f266954 Compare April 8, 2026 21:34
@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-247-post-tool-use branch from 581f8af to 00bea22 Compare April 8, 2026 21:34
@kirill-knize-sonarsource kirill-knize-sonarsource changed the base branch from task/kk/CLI-247-post-tool-use to task/kk/CLI-244-245-callback-infrastructure April 8, 2026 21:39
Copy link
Copy Markdown
Contributor

@sonar-review-alpha sonar-review-alpha bot left a comment

Choose a reason for hiding this comment

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

Conclusion: Solid PR — the migration from inline shell logic to TypeScript callback handlers is clean and well-tested. One logic duplication worth tidying up before merge.

🗣️ Give feedback

Comment on lines +40 to +49
try {
const exitCode = await scanFiles(binaryPath, stagedFiles, auth);
if (exitCode === EXIT_CODE_SECRETS_FOUND) {
throw new CommandFailedError('Secrets detected in staged files');
}
} catch (err) {
if (err instanceof CommandFailedError) throw err;
logger.debug(`git pre-commit secrets scan failed: ${(err as Error).message}`);
throw new CommandFailedError('Secrets scan failed');
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Logic duplication: This try-catch block — scanFiles → check EXIT_CODE_SECRETS_FOUND → re-throw as CommandFailedError, with a catch that re-throws CommandFailedError and wraps everything else — is duplicated verbatim in git-pre-push.ts lines 52–61. The only differences are the error message strings ('staged files' vs 'pushed commits') and the debug log prefix.

If the exit-code check or error-wrapping logic ever needs to change (e.g. new exit codes, changed error format, added telemetry), both files must be updated in sync.

Extract a shared helper into secrets-scan.ts (or a new run-secrets.ts), e.g.:

export async function runSecretsOrFail(
  binaryPath: string,
  files: string[],
  auth: ResolvedAuth,
  context: string,
): Promise<void> {
  try {
    const exitCode = await scanFiles(binaryPath, files, auth);
    if (exitCode === EXIT_CODE_SECRETS_FOUND) {
      throw new CommandFailedError(`Secrets detected in ${context}`);
    }
  } catch (err) {
    if (err instanceof CommandFailedError) throw err;
    logger.debug(`${context} secrets scan failed: ${(err as Error).message}`);
    throw new CommandFailedError('Secrets scan failed');
  }
}

Then call await runSecretsOrFail(binaryPath, stagedFiles, auth, 'staged files') and await runSecretsOrFail(binaryPath, files, auth, 'pushed commits') respectively.

  • Mark as noise

@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-248-git-hooks branch 2 times, most recently from 39242f7 to 4ef81c1 Compare April 8, 2026 22:36
sonar-review-alpha[bot]

This comment was marked as outdated.

@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-244-245-callback-infrastructure branch from c4b4665 to e44c9d3 Compare April 8, 2026 23:31
@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-244-245-callback-infrastructure branch from e44c9d3 to d117a3a Compare April 8, 2026 23:34
sonar-review-alpha[bot]

This comment was marked as outdated.

@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-244-245-callback-infrastructure branch 9 times, most recently from f4cbc21 to 468e45c Compare April 9, 2026 14:33
@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-248-git-hooks branch 3 times, most recently from 41ad13e to 3a9bf2e Compare April 9, 2026 15:04
@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-244-245-callback-infrastructure branch 3 times, most recently from 9191141 to 129cc50 Compare April 13, 2026 09:34
@kirill-knize-sonarsource kirill-knize-sonarsource force-pushed the task/kk/CLI-248-git-hooks branch 2 times, most recently from a7e0a09 to 384bf12 Compare April 13, 2026 12:20
sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as outdated.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@sonar-review-alpha sonar-review-alpha bot left a comment

Choose a reason for hiding this comment

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

LGTM! ✅

The logic duplication flagged in the prior review round — the try/catch block that wraps runSecretsBinary, checks EXIT_CODE_SECRETS_FOUND, and re-throws as CommandFailedError — remains identical in both git-pre-commit.ts (lines 48–58) and git-pre-push.ts (lines 52–62). That issue is still open.

🗣️ Give feedback

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.

1 participant