Skip to content

chore: add pre-commit hooks + pre-push test guard#8018

Merged
Git-on-my-level merged 5 commits into
BasedHardware:mainfrom
Git-on-my-level:chore/pre-commit-hooks
Jun 19, 2026
Merged

chore: add pre-commit hooks + pre-push test guard#8018
Git-on-my-level merged 5 commits into
BasedHardware:mainfrom
Git-on-my-level:chore/pre-commit-hooks

Conversation

@Git-on-my-level

@Git-on-my-level Git-on-my-level commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds pre-commit and pre-push automation so contributors catch lint/format issues and test failures locally before pushing to CI.

This would have caught the black formatting failure on PR #7954 (which wasted a CI run).

What's included

Pre-commit hooks (.pre-commit-config.yaml)

Hook Purpose Time
black Code formatting (mirrors CI: --line-length 120) ~0.3s
ruff Lint + import sorting (unused imports, undefined names) ~0.5s
detect-secrets Secret detection (critical for open-source repo) ~1.2s
no-commit-to-main Block direct pushes to main instant
trailing-whitespace + end-of-file-fixer Auto-fix diff noise instant
check-yaml/json/toml Validate config files instant
debug-statements Catch leftover breakpoint()/pdb instant
check-merge-conflict Catch leftover conflict markers instant

Total pre-commit time: ~2.1s (warm cache, M2 MacBook)

Pre-push hook (.git/hooks/pre-push.example)

  • Runs pytest on tests matching changed backend Python files
  • Smart file→test mapping: exact match → prefix glob → import grep
  • ~8s total (~0.2s test execution for 18 tests)
  • Bypass with SKIP_PRE_PUSH_TEST=1 or git push --no-verify

Manual scripts (.github/scripts/)

  • run-lint.sh — Run all lints manually (--fix, --files <list>)
  • run-pre-push.sh — Simulate pre-push test check without pushing

Setup

pip install pre-commit detect-secrets
pre-commit install                              # pre-commit hooks
cp .git/hooks/pre-push.example .git/hooks/pre-push && chmod +x .git/hooks/pre-push

CI integration (for maintainer with workflow scope)

Add this step to .github/workflows/lint.yml:

- name: Run pre-commit
  uses: pre-commit/action@v3.0.1
  with:
    extra_args: --files $(git diff --name-only origin/main...HEAD)

This ensures PRs from contributors without pre-commit installed still get the same checks.

Files added

  • .pre-commit-config.yaml — Pre-commit hook definitions
  • .secrets.baseline — Initial detect-secrets baseline (excludes known FPs)
  • .github/scripts/run-lint.sh — Manual lint runner
  • .github/scripts/run-pre-push.sh — Manual pre-push test simulator
  • .git/hooks/pre-push.example — Pre-push hook template

Review in cubic

Adds local pre-commit and pre-push automation to catch lint/format
issues and test failures BEFORE pushing to CI.

## Pre-commit hooks (.pre-commit-config.yaml)
- **black** (mirrors CI: line-length 120, skip-string-normalization)
- **ruff** (lint + format: unused imports, undefined names, noqa abuse)
- **detect-secrets** (critical for open-source repo with creds in history)
- **pre-commit-hooks** (no-commit-to-main, trailing-whitespace,
  check-yaml/json/toml, debug-statements, merge-conflict detection)

## Pre-push hook (.git/hooks/pre-push.example)
- Runs pytest on tests matching changed backend Python files
- Smart file→test mapping: exact match → prefix glob → import grep
- Timing: ~8s total (~0.2s for 18 tests)
- Bypass: SKIP_PRE_PUSH_TEST=1 or git push --no-verify

## Manual run scripts (.github/scripts/)
- `run-lint.sh` — Run all lints manually (`--fix`, `--files`)
- `run-pre-push.sh` — Simulate pre-push test check

## Timings (M2 MacBook, warm cache)
| Hook | Time |
|------|------|
| black | ~0.3s |
| ruff (lint+format) | ~0.5s |
| detect-secrets | ~1.2s |
| pre-commit-hooks | ~0.1s |
| **Pre-commit total** | **~2.1s** |
| Pre-push (18 tests) | **~7.9s** |

## Setup
```bash
pip install pre-commit detect-secrets
pre-commit install                    # pre-commit hooks
cp .git/hooks/pre-push.example .git/hooks/pre-push && chmod +x .git/hooks/pre-push  # pre-push
```

Note: CI integration (pre-commit/action@v3) should be added to
.github/workflows/lint.yml by a maintainer with workflow scope.
@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces pre-commit hooks, a detect-secrets baseline, and two helper shell scripts to catch formatting/lint issues and test failures before pushing. The tooling infrastructure is well-structured but several of the scripts contain logic errors that prevent them from working correctly out of the box.

  • run-pre-push.sh is broken: MERGE_BASE="$($REMOTE/$candidate)" wraps the ref string in $(), executing origin/main as a shell command. Under set -euo pipefail this aborts the script whenever a remote ref is found. The computed $MERGE_BASE is also never passed to the subsequent git diff, which hardcodes $REMOTE/main.
  • run-lint.sh has inverted --fix logic for black: ${ARGS:+--check} adds --check when --fix is passed, so the fix mode runs black in check-only mode and the default mode actually modifies files.
  • .pre-commit-config.yaml enables both black and ruff-format; these formatters can produce divergent output in edge cases, causing hooks to loop or conflict. One should be removed (the ruff docs recommend choosing one formatter).

Confidence Score: 3/5

The pre-commit config and secrets baseline are safe to merge; the two shell scripts have logic errors that make them non-functional in their current state.

Both helper scripts contain defects that prevent their core functionality from working: run-pre-push.sh aborts on startup due to $() wrapping a git ref name, and run-lint.sh applies --check to black when --fix is requested. Additionally, the pre-commit config runs both black and ruff-format, which can conflict. None of these affect the CI pipeline directly, but the scripts would mislead contributors who try to use them.

.github/scripts/run-pre-push.sh and .github/scripts/run-lint.sh need corrections before the scripts can be used. .pre-commit-config.yaml should pick one formatter (black or ruff-format), not both.

Important Files Changed

Filename Overview
.github/scripts/run-pre-push.sh Broken script: $($REMOTE/$candidate) executes the ref name as a shell command, aborting under set -e. $MERGE_BASE is also never used in the downstream git diff.
.github/scripts/run-lint.sh Inverted --fix logic for black: ${ARGS:+--check} adds --check when --fix is passed, running black in check-only mode instead of applying fixes.
.pre-commit-config.yaml Configures both black and ruff-format simultaneously; these formatters can conflict and cause pre-commit to loop. One should be removed.
.secrets.baseline Empty baseline for detect-secrets — no issues; this is the expected starting state for a new secrets scan.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[git commit] --> B{pre-commit hooks}
    B --> C[black format]
    B --> D[ruff lint+fix]
    B --> E[ruff-format]
    B --> F[detect-secrets]
    B --> G[pre-commit-hooks\ntrailing-ws, yaml, etc.]
    C -->|conflict risk| E
    E -->|conflict risk| C
    B --> H{all pass?}
    H -->|yes| I[commit created]
    H -->|no| J[abort + show errors]

    K[git push] --> L[pre-push hook]
    L --> M[run-pre-push.sh]
    M --> N{find MERGE_BASE}
    N -->|MERGE_BASE bug: executes ref as command| O[set -e aborts script]
    N -->|fixed| P[git diff changed py files]
    P --> Q[find matching tests]
    Q --> R[pytest --timeout=30]
    R -->|pass| S[push proceeds]
    R -->|fail| T[push blocked]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[git commit] --> B{pre-commit hooks}
    B --> C[black format]
    B --> D[ruff lint+fix]
    B --> E[ruff-format]
    B --> F[detect-secrets]
    B --> G[pre-commit-hooks\ntrailing-ws, yaml, etc.]
    C -->|conflict risk| E
    E -->|conflict risk| C
    B --> H{all pass?}
    H -->|yes| I[commit created]
    H -->|no| J[abort + show errors]

    K[git push] --> L[pre-push hook]
    L --> M[run-pre-push.sh]
    M --> N{find MERGE_BASE}
    N -->|MERGE_BASE bug: executes ref as command| O[set -e aborts script]
    N -->|fixed| P[git diff changed py files]
    P --> Q[find matching tests]
    Q --> R[pytest --timeout=30]
    R -->|pass| S[push proceeds]
    R -->|fail| T[push blocked]
Loading

Reviews (1): Last reviewed commit: "chore: add pre-commit hooks + pre-push t..." | Re-trigger Greptile

Comment thread .github/scripts/run-pre-push.sh Outdated
MERGE_BASE=""
for candidate in main master; do
if git rev-parse --verify "$REMOTE/$candidate" >/dev/null 2>&1; then
MERGE_BASE="$($REMOTE/$candidate)"

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.

P1 MERGE_BASE assignment uses command substitution instead of string assignment

"$($REMOTE/$candidate)" should be "$REMOTE/$candidate" — the $() syntax runs the value as a shell command. With set -e, this causes the script to exit immediately after git rev-parse confirms the ref exists.

Suggested change
MERGE_BASE="$($REMOTE/$candidate)"
MERGE_BASE="$REMOTE/$candidate"

if git rev-parse --verify "$REMOTE/$candidate" >/dev/null 2>&1; then
MERGE_BASE="$($REMOTE/$candidate)"
break
fi

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.

P1 Command-substitution bug makes script non-functional

"$($REMOTE/$candidate)" wraps the ref name (e.g., origin/main) in $(), which tries to execute it as a shell command. That command doesn't exist, so it returns exit code 127. Because set -euo pipefail is active at the top, the script aborts immediately whenever the git rev-parse check succeeds — the exact case the script is supposed to handle. The assigned value is always empty, so the [ -z "$MERGE_BASE" ] guard on line 33 will always exit the script with an error message.

Comment thread .github/scripts/run-pre-push.sh Outdated
exit 1
fi

CHANGED_FILES=$(git diff --name-only "$(git merge-base "$REMOTE/main" HEAD 2>/dev/null || echo HEAD)" HEAD -- 'backend/**/*.py' 2>/dev/null || true)

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.

P1 $MERGE_BASE computed but never used downstream

The loop populates $MERGE_BASE but the git diff on line 39 hardcodes $REMOTE/main instead of using the variable. If the remote only has master (or any other name), the diff silently falls back to echo HEAD, so the "changed files" list becomes every file in HEAD — running a much larger test set than intended.

Suggested change
CHANGED_FILES=$(git diff --name-only "$(git merge-base "$REMOTE/main" HEAD 2>/dev/null || echo HEAD)" HEAD -- 'backend/**/*.py' 2>/dev/null || true)
CHANGED_FILES=$(git diff --name-only "$(git merge-base "$MERGE_BASE" HEAD 2>/dev/null || echo HEAD)" HEAD -- 'backend/**/*.py' 2>/dev/null || true)

Comment thread .github/scripts/run-lint.sh Outdated
echo "⚠️ pre-commit not installed, running tools directly"
for f in $FILES; do
[ "${f##*.}" != "py" ] && continue
echo " black $f" && black --line-length=120 --skip-string-normalization ${ARGS:+--check} "$f" || true

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.

P1 --fix flag has inverted effect on the black invocation

${ARGS:+--check} expands to --check when ARGS is non-empty — i.e., exactly when --fix was passed. So ./run-lint.sh --fix runs black in check-only mode (no changes applied), and omitting --fix runs black in write mode (modifying files). The intended behavior is the reverse.

Suggested change
echo " black $f" && black --line-length=120 --skip-string-normalization ${ARGS:+--check} "$f" || true
echo " black $f" && black --line-length=120 --skip-string-normalization ${ARGS:-"--check"} "$f" || true

Comment thread .pre-commit-config.yaml Outdated
Comment on lines +16 to +39
# ── Python formatting (mirrors CI: black --line-length 120) ──
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
name: black (format)
language_version: python3.9
args: [--line-length=120, --skip-string-normalization]
types_or: [python]

# ── Python linting + import sorting (NOT in CI — free bug finding) ──
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
# Lint + auto-fix (unused imports, undefined names, noqa abuse)
- id: ruff
name: ruff (lint + fix)
args: [--fix, --exit-non-zero-on-fix, --target-version, py39]
types_or: [python]
# Formatter (complements black, handles things black doesn't)
- id: ruff-format
name: ruff-format
args: [--line-length=120]
types_or: [python]

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.

P1 Running both black and ruff-format will cause a formatting loop

black and ruff-format are competing formatters. Even though ruff-format aims to be black-compatible, edge cases exist where they disagree on output. When they do, each hook fixes the file differently, causing pre-commit to re-run infinitely (or until the retry limit). The ruff docs explicitly recommend choosing one or the other. Since ruff-format supersedes black and is already configured here, removing the black hook is the cleaner approach.

Suggested change
# ── Python formatting (mirrors CI: black --line-length 120) ──
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
name: black (format)
language_version: python3.9
args: [--line-length=120, --skip-string-normalization]
types_or: [python]
# ── Python linting + import sorting (NOT in CI — free bug finding) ──
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
# Lint + auto-fix (unused imports, undefined names, noqa abuse)
- id: ruff
name: ruff (lint + fix)
args: [--fix, --exit-non-zero-on-fix, --target-version, py39]
types_or: [python]
# Formatter (complements black, handles things black doesn't)
- id: ruff-format
name: ruff-format
args: [--line-length=120]
types_or: [python]
# ── Python linting + import sorting (NOT in CI — free bug finding) ──
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
# Lint + auto-fix (unused imports, undefined names, noqa abuse)
- id: ruff
name: ruff (lint + fix)
args: [--fix, --exit-non-zero-on-fix, --target-version, py39]
types_or: [python]
# Formatter — black-compatible, replaces black (mirrors CI line-length)
- id: ruff-format
name: ruff-format
args: [--line-length=120]
types_or: [python]

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dcfe21f534

ℹ️ 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 thread .github/scripts/run-pre-push.sh Outdated
MERGE_BASE=""
for candidate in main master; do
if git rev-parse --verify "$REMOTE/$candidate" >/dev/null 2>&1; then
MERGE_BASE="$($REMOTE/$candidate)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resolve remote refs instead of executing them

In a normal clone where origin/main or origin/master exists, this assignment tries to run the ref name as a shell command (for example origin/main) rather than resolving it. Because the script has set -e, that exits before any changed files or tests are computed, so the pre-push check is unusable for the main advertised case; use git rev-parse "$REMOTE/$candidate" or store the ref name instead.

Useful? React with 👍 / 👎.

Comment thread .github/scripts/run-pre-push.sh Outdated
echo ""

cd backend
python -m pytest -v --timeout=30 --tb=short $TEST_TARGETS

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add pytest-timeout before using --timeout

When matching backend tests are found, this command passes --timeout=30, but the checked backend test environment does not provide that option (python -m pytest --help has no --timeout, and backend/requirements.txt does not install pytest-timeout). As a result the guard exits with an unrecognized-argument error instead of running the selected tests unless contributors happen to have that plugin installed outside the repo.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai 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.

7 issues found across 4 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread .github/scripts/run-pre-push.sh Outdated
Comment thread .github/scripts/run-lint.sh Outdated
Comment thread .secrets.baseline Outdated
Comment thread .github/scripts/run-pre-push.sh Outdated
Comment thread .github/scripts/run-lint.sh Outdated
Comment thread .github/scripts/run-lint.sh Outdated
Comment thread .pre-commit-config.yaml Outdated

@kodjima33 kodjima33 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Chore (pre-commit hooks + pre-push test guard) — approve only per policy (tooling/chore, not bug fix).

run-pre-push.sh:
- P1: Fix command execution bug — use `git rev-parse` instead of
  bare ref (was trying to execute remote ref as shell command)
- P2: Use detected base branch instead of hardcoding origin/main

run-lint.sh:
- P1: Fix reversed black logic — --check mode now correctly passes
  --check to black, fix mode omits it
- P2: Remove unsupported --fix flag from pre-commit run (pre-commit
  auto-fixes via individual hooks, not a global flag)
- P2: Same --fix removal in all-files mode

.secrets.baseline:
- P1: Tighten exclude regex patterns with proper anchors (^|/) and (/|$)
  to prevent overly broad matching (e.g., 'build' no longer matches
  filenames containing that substring)

.pre-commit-config.yaml:
- P2: Remove ruff-format hook (conflicts with black — ruff docs state
  they are not intended to be used interchangeably due to known
  output deviations; keep black as sole formatter)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9b206ca33

ℹ️ 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 thread .github/scripts/run-pre-push.sh Outdated
# Timing: ~5-30s depending on how many files changed

set -euo pipefail
cd "$(dirname "$0")/.."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Run the pre-push guard from the repo root

When the script is invoked as documented from the repo root, this cd lands in /workspace/omi/.github, not /workspace/omi. From that directory Git treats the 'backend/**/*.py' pathspec as relative to .github (for example, git -C .github ls-files 'backend/**/*.py' matches 0 files), so backend Python changes are reported as “No backend Python files changed” and no tests run. Change this to the repo root, such as ../.. or git rev-parse --show-toplevel.

Useful? React with 👍 / 👎.

Comment thread .github/scripts/run-pre-push.sh Outdated
exit 1
fi

CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" HEAD -- 'backend/**/*.py' 2>/dev/null || true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include backend root modules in the pre-push diff

This pathspec skips Python files directly under backend/; in this repo backend/main.py and backend/dependencies.py are not matched by git ls-files 'backend/**/*.py'. Changes to those core modules therefore bypass the pre-push test guard even after the script runs from the right directory; include backend/*.py or use a pathspec that covers both depths.

Useful? React with 👍 / 👎.

Comment thread .github/scripts/run-pre-push.sh Outdated
Comment on lines +73 to +74
find backend/tests/unit backend/tests/integration \
-name "test_${MODULE_NAME}*.py" >> "$TEST_TMP" 2>/dev/null || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize prefix-glob test paths before filtering

The prefix-glob branch writes paths like backend/tests/unit/test_foo.py, but the later filter checks [ -f "backend/$t" ], turning those into backend/backend/tests/... and discarding every test found by find. In the case where only a prefix match exists, the guard incorrectly prints “No matching test files found”; emit paths relative to backend/ here or adjust the filter.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread .github/scripts/run-lint.sh Outdated
Comment thread .github/scripts/run-pre-push.sh Outdated
Both scripts live in .github/scripts/, so $(dirname "$0")/..
resolved to .github/ not the repo root. Changed to ../..

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91f8731684

ℹ️ 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 thread .pre-commit-config.yaml
Comment on lines +12 to +13
# Pre-push hook runs pytest on changed files (~10-30s).
# See: .git/hooks/pre-push

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register the pre-push guard as an actual hook

The only tracked pre-push code in this change is the manual .github/scripts/run-pre-push.sh simulator; .git/hooks is not versioned, and this config does not add default_install_hook_types or a local hook staged for pre-push. Per the pre-commit docs, installing a pre-push hook requires --hook-type pre-push or equivalent config, so a contributor following the added setup will get commit hooks but a normal git push will never run the pytest guard.

Useful? React with 👍 / 👎.

Comment thread .pre-commit-config.yaml
# Validate config files
- id: check-yaml
args: [--unsafe] # allow custom tags in workflows
- id: check-json

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude or fix existing invalid JSON before enabling checks

When the documented pre-commit run --all-files path or run-lint.sh all-files path runs, this hook processes existing tracked JSON files that are already invalid: app/.vscode/settings.json has a trailing comma and app/web/manifest.json is empty. Because the new config neither excludes nor fixes those files, a clean checkout fails the new lint suite before it reaches a contributor's changes.

Useful? React with 👍 / 👎.

Comment thread .github/scripts/run-lint.sh Outdated
Comment on lines +47 to +48
echo " black (check) $f" && black --check --line-length=120 --skip-string-normalization "$f" || true
echo " ruff (check) $f" && ruff check --target-version py39 "$f" || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Propagate fallback lint failures

In the supported fallback path where pre-commit is not installed, each direct black/ruff invocation is followed by || true, so the script exits successfully even when the tools report errors or are missing. I ran this path on backend/main.py in the repo and it printed ruff errors followed by ✅ Lint complete with exit 0, which lets contributors or CI wrappers silently accept lint failures.

Useful? React with 👍 / 👎.

run-pre-push.sh:
- P2: Add backend/*.py pathspec to catch root-level Python files
  (backend/**/*.py alone misses backend/main.py etc.)
- P2: Strip leading 'backend/' from find output to prevent double-prefix
  in test target paths
- P2: Guard --timeout flag behind pytest-timeout plugin detection,
  gracefully degrade if plugin not installed

pre-push.example (same fixes synced):
- Same pathspec, prefix-strip, and timeout-guard fixes

run-lint.sh:
- P2: Propagate fallback lint failures — replace || true with error
  tracking and exit non-zero if any tool fails

.pre-commit-config.yaml:
- P2: Add exclude patterns to check-json for known-invalid JSON
  (Flutter app JSON, Firebase config, IDE files, lock files)

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread .pre-commit-config.yaml Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a04ffcee7

ℹ️ 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".

MODULE_NAME=$(basename "$f" .py)

# If the changed file IS a test file, run it directly
if [[ "$REL_PATH" == tests/*/test_*.py ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include top-level backend tests in the guard

When the changed file is a test directly under backend/tests (this repo has backend/tests/test_cache_manager.py), REL_PATH becomes tests/test_cache_manager.py, which does not match tests/*/test_*.py; it then falls through to the source-file mapping and the later search only considers tests/unit and tests/integration. A push that edits that existing test file therefore reports no matching tests instead of running the test that changed.

Useful? React with 👍 / 👎.

cd backend

# Build pytest args — only include --timeout if plugin is available
PYTEST_ARGS="-v --tb=short"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Detect pytest-timeout with a supported option

In environments that actually have pytest-timeout installed, this probe still returns nonzero because upstream pytest-timeout registers --timeout, --timeout-method, and --session-timeout, but not --timeout-version (checked its pytest_addoption implementation: https://raw.githubusercontent.com/pytest-dev/pytest-timeout/main/pytest_timeout.py). The script therefore always drops the intended 30s limit, so a hanging matched backend test can block the pre-push guard indefinitely; detect the plugin via pytest --help or an import instead.

Useful? React with 👍 / 👎.

Replace broad app/.*\.json with specific patterns:
- app/lib/*.g.json (Dart codegen generated)
- app/*.arb (App resource bundles, not strict JSON)
- Keep .firebase/, .idea/, lock files

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4bce4d9d3

ℹ️ 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 thread .pre-commit-config.yaml
hooks:
- id: black
name: black (format)
language_version: python3.9

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use the repo Python for the black hook

In a Python 3.11-only dev or CI environment, this pin makes pre-commit create the black hook env with python3.9, but the repo’s backend images use Python 3.11 and the setup instructions only install pre-commit, not a 3.9 interpreter. That causes the first hook install/run to fail before any linting; use the repo Python version or omit language_version so pre-commit uses the installed interpreter.

Useful? React with 👍 / 👎.

Comment thread .pre-commit-config.yaml

# ── Secret detection (critical for open-source repo with creds in history) ──
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pin detect-secrets to the baseline version

This hook is pinned to detect-secrets v1.4.0, but the committed baseline is version 1.5.0 and lists v1.5-only plugins such as OpenAIDetector and IPPublicDetector. When the pre-commit hook runs, v1.4.0 initializes plugins from the baseline and errors on the unknown plugin before scanning, so ordinary commits that reach this hook are blocked; pin the hook to v1.5.0 or regenerate the baseline with v1.4.0.

Useful? React with 👍 / 👎.

Comment thread .secrets.baseline
]
}
],
"results": {},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Record existing secrets in the baseline

The new baseline enables detectors such as PrivateKeyDetector but records no findings, while tracked files like omi/firmware/bootloader/mcuboot/enc-rsa2048-priv.pem and root-rsa-2048.pem contain RSA private-key blocks and are not excluded by these filters. After the hook version issue is fixed, the documented pre-commit run --all-files / run-lint.sh all-files path reports those existing keys on a clean checkout instead of only new leaks; update the baseline or explicitly exclude known test keys.

Useful? React with 👍 / 👎.

@Git-on-my-level Git-on-my-level merged commit 014991b into BasedHardware:main Jun 19, 2026
2 checks passed
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.

2 participants