Skip to content

Add pre-commit config for repo hygiene and secret detection - #30

Open
Harshaada wants to merge 1 commit into
redhat-data-and-ai:mainfrom
Harshaada:hgaikwad-fivetran-operator
Open

Add pre-commit config for repo hygiene and secret detection#30
Harshaada wants to merge 1 commit into
redhat-data-and-ai:mainfrom
Harshaada:hgaikwad-fivetran-operator

Conversation

@Harshaada

Copy link
Copy Markdown

Updated .pre-commit-config.yaml with gitleaks for secret detection.
Updated CONTRIBUTING.md with steps to install and enable pre-commit locally.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Documentation

    • Added setup guidance for pre-commit checks.
    • Documented available secret-scanning protections, including GitHub Secret Scanning and Push Protection.
  • Chores

    • Expanded repository safeguards to detect private keys and scan for exposed secrets.
    • Added repository-wide exclusions while retaining existing secret checks.

Walkthrough

The pull request expands pre-commit configuration with private-key detection and Gitleaks scanning. It excludes vendor/, retains check-secrets, and adds README instructions for installation and repository secret-scanning protections.

Changes

Secret Scanning Setup

Layer / File(s) Summary
Pre-commit scanning configuration
.pre-commit-config.yaml
The configuration adds repository exclusions, installation guidance, private-key detection, pinned Gitleaks scanning, and grouped project checks.
Developer setup documentation
README.md
The README documents pre-commit installation and secret-scanning protections.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the pre-commit and secret-detection changes.
Description check ✅ Passed The description accurately covers the pre-commit and Gitleaks changes and is related to the documentation update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 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: 3

🤖 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 @.pre-commit-config.yaml:
- Around line 4-5: Update the pre-commit usage comments to accurately describe
the coverage of `pre-commit run --all-files`, noting that
`scripts/check-secrets.sh` scans only staged added, copied, or modified files
because filename passing is disabled. Either document this as staged-only
coverage or add and document a separate full-tree scan mode.
- Around line 28-30: Update scripts/check-secrets.sh, specifically the output
for matches triggered by the check-secrets hook, so it never prints full
matching lines containing secrets. Report only the detection rule, file path,
and line number, or replace the matched secret with a redacted value while
preserving the existing five-match limit and detection behavior.
- Around line 11-23: Configure Gitleaks explicitly for the vendor/ path by
adding a global vendor/ allowlist in .gitleaks.toml, or remove vendor/ from the
pre-commit exclude if it is not trusted generated content; update the gitleaks
hook configuration without changing the detect-private-key hook.
🪄 Autofix

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: CHILL

Plan: Pro Plus

Run ID: a878ef22-e975-44e2-a8fb-64c63b51cf9d

📥 Commits

Reviewing files that changed from the base of the PR and between 1dcab4b and 4676816.

📒 Files selected for processing (2)
  • .pre-commit-config.yaml
  • README.md

Comment thread .pre-commit-config.yaml
Comment on lines +4 to +5
# Install: pip install pre-commit && pre-commit install
# Run manually: pre-commit run --all-files

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not describe --all-files as a full secret scan.

Line 32 disables filename passing, and scripts/check-secrets.sh builds its file list from git diff --cached --diff-filter=ACM. Therefore the command at Lines 4-5 checks only staged added, copied, or modified files for this hook. Add a full-tree scan mode, or document staged-only coverage.

Also applies to: 32-32

🤖 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 @.pre-commit-config.yaml around lines 4 - 5, Update the pre-commit usage
comments to accurately describe the coverage of `pre-commit run --all-files`,
noting that `scripts/check-secrets.sh` scans only staged added, copied, or
modified files because filename passing is disabled. Either document this as
staged-only coverage or add and document a separate full-tree scan mode.

Comment thread .pre-commit-config.yaml
Comment on lines +11 to +23
exclude: "^vendor/"

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: detect-private-key

# Secret detection (same approach as usernaut / template-ui)
- repo: https://github.com/gitleaks/gitleaks
rev: v8.28.0
hooks:
- id: gitleaks

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

url='https://raw.githubusercontent.com/gitleaks/gitleaks/v8.28.0/.pre-commit-hooks.yaml'
curl -fsSL "$url" |
  grep -nE -A8 'id: gitleaks|entry:|pass_filenames:|args:'

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 851


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- .pre-commit-config.yaml ---'
sed -n '1,120p' .pre-commit-config.yaml

printf '%s\n' '--- scripts/check-secrets.sh ---'
if [ -f scripts/check-secrets.sh ]; then
  sed -n '1,200p' scripts/check-secrets.sh
else
  printf '%s\n' 'missing'
fi

printf '%s\n' '--- tracked vendor paths ---'
git ls-files vendor | sed -n '1,80p'
printf 'tracked_vendor_count='
git ls-files vendor | wc -l

printf '%s\n' '--- vendor references and generation markers ---'
rg -n -i 'vendor|generated|go mod vendor|check-secrets|gitleaks' \
  --glob '!vendor/**' \
  --glob '!.git/**' \
  . | sed -n '1,240p'

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 13807


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- vendor configuration ---'
rg -n -i 'vendor|go mod vendor|GOFLAGS|mod=' \
  go.mod go.work go.sum Makefile .gitignore .gitattributes README.md \
  --no-messages | sed -n '1,200p'

printf '%s\n' '--- hook documentation context ---'
sed -n '1,45p' README.md
sed -n '1,70p' .gitignore

printf '%s\n' '--- tracked vendor file classes ---'
git ls-files vendor | awk '
  BEGIN { files=0; go=0; docs=0; configs=0; }
  {
    files++;
    if ($0 ~ /\.go$/) go++;
    if ($0 ~ /\.(md|txt|rst|adoc)$/ || $0 ~ /(^|\/)(LICENSE|NOTICE|COPYING)(\..*)?$/) docs++;
    if ($0 ~ /\.(ya?ml|json|toml|ini|cfg|conf|bazel|bzl)$/ || $0 ~ /(^|\/)(BUILD|MODULE|WORKSPACE)(\..*)?$/) configs++;
  }
  END {
    printf "files=%d go=%d docs_or_licenses=%d configs=%d\n", files, go, docs, configs;
  }'

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 440


🌐 Web query:

pre-commit documentation exclude pass_filenames false hook files filtering behavior

💡 Result:

In pre-commit, the pass_filenames: false hook configuration serves a specific, narrow purpose: it prevents the framework from appending matched filenames as positional arguments to your command [1][2]. It does not disable the file filtering logic itself [3]. Key behaviors include: Filtering remains active: The files, types, and exclude options continue to function as normal [3]. The framework still identifies which files match your criteria to determine whether the hook should run [3]. If no files match the criteria (and always_run is not set to true), the hook will be skipped [4]. No filenames passed: When the hook is triggered, pre-commit executes the command without passing any of the matched file paths as arguments [1][2]. This is useful for tools that manage their own file discovery (e.g., linters that read from a configuration file or execute on a whole directory) [5][6]. No impact on triggering: The setting only affects the command-line arguments. It does not stop the hook from being triggered by file changes; it simply changes the mechanism of invocation [3]. Because pass_filenames: false changes how the hook interacts with your command, ensure your entry and args are configured correctly to perform the desired action (e.g., linting a directory) without expecting individual file paths from the shell [7][6]. If you need to trigger a hook even when no files are matched, you must use the always_run: true setting [8][5][4].

Citations:


🌐 Web query:

Gitleaks v8.28.0 pre-commit hook --staged exclude vendor path configuration

💡 Result:

To exclude a path (such as a vendor directory) from Gitleaks v8.28.0 when running as a pre-commit hook, you must use the global allowlist configuration in your Gitleaks configuration file (e.g.,.gitleaks.toml) [1][2]. 1. Create or update your.gitleaks.toml file in the root of your repository [3][4]. 2. Add the [allowlist] section and include the path to be excluded using the paths key. Use regex patterns to define the directory or files you wish to ignore [1][5][2]. Example configuration to exclude a vendor directory: [allowlist] description = "Global allowlist to exclude vendor directory" paths = [ '''(^|/)vendor/.*''' ] [extend] useDefault = true Important considerations: - Global Allowlist: Ensure you use the global [allowlist] table rather than a rule-specific [[rules.allowlist]] table to ensure the exclusion applies across all rules [1][2]. - Use Default Rules: If you define your own configuration file, you must include [extend] useDefault = true if you still want to utilize the built-in Gitleaks secret detection rules [1][5]. - Pre-commit Setup: Ensure your.pre-commit-config.yaml is correctly pointing to your custom configuration file if necessary, though Gitleaks typically detects.gitleaks.toml automatically in the project root [3][4]. Gitleaks v8.28.0 also introduced composite rules, but this feature pertains to secret detection logic (proximity matching) and does not alter the fundamental method for excluding paths via the allowlist [6].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- existing module and vendor metadata ---'
for file in go.mod go.work go.sum Makefile .gitignore .gitattributes vendor/modules.txt; do
  if [ -f "$file" ]; then
    printf '\n--- %s ---\n' "$file"
    case "$file" in
      Makefile) rg -n -C 3 -i 'vendor|go mod vendor' "$file" || true ;;
      go.mod|go.work|go.sum) sed -n '1,35p' "$file" ;;
      *) sed -n '1,45p' "$file" ;;
    esac
  fi
done

printf '%s\n' '--- Gitleaks configuration files ---'
git ls-files '*gitleaks*' '.gitleaks.toml' '.gitleaks/*' | sed -n '1,80p'

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 7538


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re
import subprocess

config = Path(".pre-commit-config.yaml").read_text()
gitignore = Path(".gitignore").read_text()
tracked_vendor = subprocess.check_output(
    ["git", "ls-files", "vendor"], text=True
).splitlines()

hook = re.search(
    r"- repo: https://github\.com/gitleaks/gitleaks.*?"
    r"(?=\n  - repo:|\Z)",
    config,
    re.S,
)
if not hook:
    raise SystemExit("gitleaks hook not found")

hook_text = hook.group(0)
entry = re.search(r"entry:\s*(.+)", hook_text)
pass_filenames = re.search(r"pass_filenames:\s*(\w+)", hook_text)

print(f"top_level_exclude={re.search(r'exclude:\s*\"\^vendor/\"', config) is not None}")
print(f"gitleaks_entry={entry.group(1) if entry else '<not found>'}")
print(f"gitleaks_pass_filenames={pass_filenames.group(1) if pass_filenames else '<default true>'}")
print(f"gitleaks_runs_staged_scan={'--staged' in hook_text}")
print(f"tracked_vendor_files={len(tracked_vendor)}")
print(f"vendor_metadata_tracked={Path('vendor/modules.txt').as_posix() in tracked_vendor}")
print(f"gitignore_describes_vendored_files={'except for vendored files' in gitignore}")
print(f"gitleaks_config_present= {Path('.gitleaks.toml').exists() or Path('.gitleaks').exists()}")
PY

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 451


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re
import subprocess

config = Path(".pre-commit-config.yaml").read_text()
gitignore = Path(".gitignore").read_text()
tracked_vendor = subprocess.check_output(
    ["git", "ls-files", "vendor"], text=True
).splitlines()

hook = re.search(
    r"- repo: https://github\.com/gitleaks/gitleaks.*?"
    r"(?=\n  - repo:|\Z)",
    config,
    re.S,
)
if not hook:
    raise SystemExit("gitleaks hook not found")

hook_text = hook.group(0)
entry_match = re.search(r"entry:\s*(.+)", hook_text)
pass_match = re.search(r"pass_filenames:\s*(\w+)", hook_text)
top_level_exclude = bool(re.search(r'exclude:\s*"\\\^vendor/"', config))

print("top_level_exclude=", top_level_exclude)
print("gitleaks_entry=", entry_match.group(1) if entry_match else "<not found>")
print("gitleaks_pass_filenames=", pass_match.group(1) if pass_match else "<default true>")
print("gitleaks_runs_staged_scan=", "--staged" in hook_text)
print("tracked_vendor_files=", len(tracked_vendor))
print("vendor_metadata_tracked=", "vendor/modules.txt" in tracked_vendor)
print("gitignore_describes_vendored_files=", "except for vendored files" in gitignore)
print(
    "gitleaks_config_present=",
    Path(".gitleaks.toml").exists() or Path(".gitleaks").exists(),
)
PY

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 430


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re
import subprocess
import urllib.request

config = Path(".pre-commit-config.yaml").read_text()
tracked_vendor = subprocess.check_output(
    ["git", "ls-files", "vendor"], text=True
).splitlines()

hook_yaml = urllib.request.urlopen(
    "https://raw.githubusercontent.com/gitleaks/gitleaks/v8.28.0/.pre-commit-hooks.yaml"
).read().decode()

local_exclude = re.search(r'^exclude:\s*"([^"]+)"\s*$', config, re.M)
gitleaks_block = re.search(
    r"(?m)^- id: gitleaks$\n(?:(?!^-\s+id:).)*",
    hook_yaml,
    re.S,
)
if not gitleaks_block:
    raise SystemExit("gitleaks hook definition not found")

block = gitleaks_block.group(0)
entry = re.search(r"(?m)^  entry:\s*(.+)$", block)
pass_filenames = re.search(r"(?m)^  pass_filenames:\s*(\w+)$", block)

print("local_exclude=", local_exclude.group(1) if local_exclude else "<not found>")
print("remote_gitleaks_entry=", entry.group(1) if entry else "<not found>")
print(
    "remote_gitleaks_pass_filenames=",
    pass_filenames.group(1) if pass_filenames else "<default true>",
)
print("remote_gitleaks_uses_staged=", "--staged" in block)
print("tracked_vendor_files=", len(tracked_vendor))
print("vendor_modules_tracked=", "vendor/modules.txt" in tracked_vendor)
print(
    "gitleaks_config_present=",
    Path(".gitleaks.toml").exists() or Path(".gitleaks").exists(),
)

# Model the relevant boundary: pre-commit filters hook applicability,
# while the staged Gitleaks command selects its own scan scope.
staged = ["vendor/example.go", "controllers/controller.go"]
pre_commit_candidates = [
    path for path in staged if not path.startswith("vendor/")
]
gitleaks_scope = staged if "--staged" in block else pre_commit_candidates
print("pre_commit_candidates=", pre_commit_candidates)
print("gitleaks_staged_scope=", gitleaks_scope)
PY

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 2461


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

curl -fsSL \
  'https://raw.githubusercontent.com/gitleaks/gitleaks/v8.28.0/.pre-commit-hooks.yaml' |
python3 -c '
from pathlib import Path
import re
import subprocess
import sys

config = Path(".pre-commit-config.yaml").read_text()
hook_yaml = sys.stdin.read()
tracked_vendor = subprocess.check_output(
    ["git", "ls-files", "vendor"], text=True
).splitlines()

local_exclude = re.search(r"^exclude:\s*\"([^\"]+)\"\s*$", config, re.M)
gitleaks_block = re.search(
    r"(?m)^- id: gitleaks$\n(?:(?!^-\s+id:).)*",
    hook_yaml,
    re.S,
)
if not gitleaks_block:
    raise SystemExit("gitleaks hook definition not found")

block = gitleaks_block.group(0)
entry = re.search(r"(?m)^  entry:\s*(.+)$", block)
pass_filenames = re.search(r"(?m)^  pass_filenames:\s*(\w+)$", block)

print("local_exclude=", local_exclude.group(1) if local_exclude else "<not found>")
print("remote_gitleaks_entry=", entry.group(1) if entry else "<not found>")
print(
    "remote_gitleaks_pass_filenames=",
    pass_filenames.group(1) if pass_filenames else "<default true>",
)
print("remote_gitleaks_uses_staged=", "--staged" in block)
print("tracked_vendor_files=", len(tracked_vendor))
print("vendor_modules_tracked=", "vendor/modules.txt" in tracked_vendor)
print(
    "gitleaks_config_present=",
    Path(".gitleaks.toml").exists() or Path(".gitleaks").exists(),
)
'

Repository: redhat-data-and-ai/fivetran-operator

Length of output: 435


Configure Gitleaks to exclude vendor/ explicitly.

The hook scans staged content independently of pre-commit’s exclude filter. Add a global vendor/ path allowlist to .gitleaks.toml, or remove vendor/ from the exclusion if it is not trusted generated content.

🤖 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 @.pre-commit-config.yaml around lines 11 - 23, Configure Gitleaks explicitly
for the vendor/ path by adding a global vendor/ allowlist in .gitleaks.toml, or
remove vendor/ from the pre-commit exclude if it is not trusted generated
content; update the gitleaks hook configuration without changing the
detect-private-key hook.

Comment thread .pre-commit-config.yaml
Comment on lines 28 to 30
- id: check-secrets
name: Security Check
entry: bash scripts/check-secrets.sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Redact secret matches before printing them.

scripts/check-secrets.sh prints up to five matching lines after detection. A detected API key, password, or private key can therefore enter terminal or CI logs. Report only the rule, path, and line number, or redact the matched value.

🤖 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 @.pre-commit-config.yaml around lines 28 - 30, Update
scripts/check-secrets.sh, specifically the output for matches triggered by the
check-secrets hook, so it never prints full matching lines containing secrets.
Report only the detection rule, file path, and line number, or replace the
matched secret with a redacted value while preserving the existing five-match
limit and detection behavior.

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