Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install Python tools
run: pip install ruff

- name: Prepare test environment
run: |
chmod +x python/*.sh
Expand Down Expand Up @@ -161,3 +164,68 @@ jobs:
- name: Run YAML tests
run: |
for suite in tests/yml/*/run.sh; do "$suite"; done

simple-tests:
name: Simple Tests
runs-on: ubuntu-latest
needs: shellcheck

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install codespell
run: pip install codespell

- name: Prepare test environment
run: |
chmod +x simple/*.sh
chmod +x tests/lib/*.bash
find tests/simple -name "*.sh" -exec chmod +x {} +

- name: Run Simple tests
run: |
for suite in tests/simple/*/run.sh; do "$suite"; done

git-tests:
name: Git Tests
runs-on: ubuntu-latest
needs: shellcheck

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Prepare test environment
run: |
chmod +x git/*.sh
chmod +x tests/lib/*.bash
find tests/git -name "*.sh" -exec chmod +x {} +

- name: Run Git tests
run: |
for suite in tests/git/*/run.sh; do "$suite"; done

shell-tests:
name: Shell Tests
runs-on: ubuntu-latest
needs: shellcheck

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install shfmt
run: |
curl -sS https://webi.sh/shfmt | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

- name: Prepare test environment
run: |
chmod +x shell/*.sh
chmod +x tests/lib/*.bash
find tests/shell -name "*.sh" -exec chmod +x {} +

- name: Run Shell tests
run: |
for suite in tests/shell/*/run.sh; do "$suite"; done
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ tests/**/tmp/
# Logs
*.log

articles/
articles/
tasks/
25 changes: 22 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Project Overview

A collection of reusable git hook scripts for automating code quality checks. Covers JavaScript/TypeScript, Python, PHP/Laravel, CSS, HTML, Markdown, YAML, Docker, and shell scripts.
A collection of reusable git hook scripts for automating code quality checks. Covers JavaScript/TypeScript, Python, PHP/Laravel, CSS, HTML, Markdown, YAML, Docker, shell scripts, and general-purpose checks (spelling, JSON, secret detection, shell formatting).

## Directory Structure

Expand All @@ -16,6 +16,8 @@ docker/ # Docker-related hooks

git/ # Git workflow hooks
├── check_branch_name.sh # Branch naming convention validator
├── check_gitleaks.sh # Secret detection in staged changes (optional)
├── check_gitleaks_all.sh # Secret detection in full repository history
└── preparations/ # Commit message enhancers
├── add_task_id_in_commit.sh
└── prepare-commit-description.sh
Expand Down Expand Up @@ -54,10 +56,20 @@ python/ # Python hooks
├── check_mypy_in_docker.sh # Mypy (Docker)
├── check_pytest.sh # Pytest (local)
├── check_pytest_in_docker.sh # Pytest (Docker)
├── check_ruff.sh # Ruff linter for staged files
├── check_ruff_all.sh # Ruff linter for entire project
└── find_test.sh # Service test existence validator

shell/ # Shell script validation
└── check_shellcheck.sh # ShellCheck via Docker
├── check_shellcheck.sh # ShellCheck via Docker
├── check_shfmt.sh # shfmt formatting check for staged files
└── check_shfmt_all.sh # shfmt formatting check for entire project

simple/ # General-purpose hooks
├── check_codespell.sh # Spelling check for staged files
├── check_codespell_all.sh # Spelling check for entire project
├── check_json_validate.sh # JSON syntax validation for staged files
└── check_json_validate_all.sh # JSON syntax validation for entire project

scripts/ # Local utility scripts
├── check_shellcheck.sh # ShellCheck (local execution)
Expand All @@ -71,11 +83,14 @@ tests/ # Test framework
├── run_all.sh # Run all test suites
├── lib/test_helper.bash # Test utilities and assertions
├── css/ # CSS hook tests
├── git/ # Git hook tests (gitleaks)
├── html/ # HTML hook tests
├── javascript/ # JavaScript hook tests
├── markdown/ # Markdown hook tests
├── php/ # PHP hook tests
├── python/ # Python hook tests
├── python/ # Python hook tests (flake8, mypy, ruff, pytest, find_test)
├── shell/ # Shell hook tests (shfmt)
├── simple/ # Simple hook tests (codespell, json_validate)
└── yml/ # YAML hook tests
```

Expand Down Expand Up @@ -112,11 +127,15 @@ Every script must start with a description block after the shebang:
- Bash 4.0+, Git, jq
- Node.js with npx (for JavaScript/TypeScript, CSS, HTML hooks)
- Python 3, Flake8, Mypy, Pytest (for Python hooks)
- Ruff (`pip install ruff`) for `python/check_ruff.sh`
- Codespell (`pip install codespell`) for `simple/check_codespell.sh`
- PHP 8.1+, Composer (for PHPStan/Pint)
- Stylelint via npx (for CSS hooks)
- HTMLHint via npx (for HTML hooks)
- markdownlint-cli (for Markdown hooks)
- yamllint (for YAML hooks)
- shfmt (`go install mvdan.cc/sh/v3/cmd/shfmt@latest` or `brew install shfmt`) for `shell/check_shfmt.sh`
- gitleaks (optional, see [install guide](https://github.com/gitleaks/gitleaks#installing)) for `git/check_gitleaks.sh`
- Docker (optional, for containerized checks)
- ShellCheck (for shell validation)

Expand Down
81 changes: 78 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ A collection of reusable git hook scripts for automating code quality checks and
## Features

- **JavaScript/TypeScript**: ESLint, Prettier, TypeScript type checking, Vitest test runner, test existence validation
- **Python**: Flake8 linting, Mypy static analysis, Pytest runner, service test validation (local and Docker modes)
- **Python**: Flake8 linting, Mypy static analysis, Ruff linting, Pytest runner, service test validation (local and Docker modes)
- **PHP/Laravel**: PHPStan analysis with progressive error reduction, Pint code style fixing, test coverage validation
- **CSS/SCSS/Less**: Stylelint code style validation
- **HTML**: HTMLHint linting
- **Markdown**: markdownlint style validation
- **YAML**: yamllint style validation
- **Docker**: Dockerfile linting with Hadolint
- **Shell**: Script validation with ShellCheck
- **Git**: Branch naming conventions, automatic task ID injection in commits
- **Shell**: Script validation with ShellCheck, shfmt formatting check
- **Git**: Branch naming conventions, automatic task ID injection in commits, secret detection with gitleaks
- **Simple**: Spelling check with codespell, JSON syntax validation

## Quick Start

Expand Down Expand Up @@ -48,6 +49,8 @@ A collection of reusable git hook scripts for automating code quality checks and
| `python/check_mypy_in_docker.sh` | Runs Mypy inside the Docker container, maps host/container paths. |
| `python/check_pytest.sh` | Runs the full Pytest suite locally with `PYTHONPATH=./app`. |
| `python/check_pytest_in_docker.sh` | Runs Pytest inside the Docker container, converts container paths to host paths. |
| `python/check_ruff.sh` | Runs Ruff linter on staged Python files passed as arguments. |
| `python/check_ruff_all.sh` | Runs Ruff linter on all Python files in the project. |
| `python/find_test.sh` | Validates that each service in `app/services/` has exactly one corresponding test file. |

### PHP
Expand Down Expand Up @@ -92,6 +95,8 @@ A collection of reusable git hook scripts for automating code quality checks and
| Script | Description |
|--------|-------------|
| `git/check_branch_name.sh` | Validates branch names match pattern: `{type}/{task-id}_{description}` |
| `git/check_gitleaks.sh` | Scans staged changes for secrets using gitleaks (optional; exits 0 if not installed). |
| `git/check_gitleaks_all.sh` | Scans full repository history for secrets using gitleaks. |
| `git/preparations/add_task_id_in_commit.sh` | Prepends task ID from branch name to commit message. |
| `git/preparations/prepare-commit-description.sh` | Appends list of changed files to commit message. |

Expand All @@ -106,8 +111,19 @@ A collection of reusable git hook scripts for automating code quality checks and
| Script | Description |
|--------|-------------|
| `shell/check_shellcheck.sh` | Validates shell scripts using ShellCheck (via Docker). |
| `shell/check_shfmt.sh` | Checks shell script formatting using shfmt (`-i 2 -ci`). |
| `shell/check_shfmt_all.sh` | Checks formatting of all `.sh` files in the project. |
| `scripts/check_shellcheck.sh` | Validates shell scripts using ShellCheck (local). |

### Simple

| Script | Description |
|--------|-------------|
| `simple/check_codespell.sh` | Checks files for spelling mistakes using codespell. |
| `simple/check_codespell_all.sh` | Checks all project files for spelling mistakes. |
| `simple/check_json_validate.sh` | Validates JSON files for syntax correctness using `python3 -m json.tool`. |
| `simple/check_json_validate_all.sh` | Validates all `*.json` files in the project. |

## Usage Examples

### JavaScript/TypeScript
Expand Down Expand Up @@ -210,6 +226,56 @@ A collection of reusable git hook scripts for automating code quality checks and
./yml/check_yamllint_all.sh
```

### Ruff

```bash
# Check staged files
./python/check_ruff.sh app/services/user.py app/models/auth.py

# Check all Python files in the project
./python/check_ruff_all.sh
```

### Gitleaks

```bash
# Check staged changes for secrets (optional: exits 0 if gitleaks not installed)
./git/check_gitleaks.sh

# Scan full repository history for secrets
./git/check_gitleaks_all.sh
```

### shfmt

```bash
# Check staged shell scripts for formatting
./shell/check_shfmt.sh deploy.sh scripts/setup.sh

# Check all shell scripts in the project
./shell/check_shfmt_all.sh
```

### Codespell

```bash
# Check specific files for spelling mistakes
./simple/check_codespell.sh README.md src/utils.py

# Check all project files
./simple/check_codespell_all.sh
```

### JSON Validation

```bash
# Validate specific JSON files
./simple/check_json_validate.sh package.json .eslintrc.json

# Validate all JSON files in the project
./simple/check_json_validate_all.sh
```

### Branch Name Validation

```bash
Expand Down Expand Up @@ -290,6 +356,7 @@ SH_FILES=$(echo "$FILES" | grep '\.sh$' || true)
./tests/javascript/vitest/run.sh
./tests/python/flake8/run.sh
./tests/python/mypy/run.sh
./tests/python/ruff/run.sh
./tests/python/find_test/run.sh
./tests/css/stylelint/run.sh
./tests/css/stylelint_all/run.sh
Expand All @@ -299,6 +366,10 @@ SH_FILES=$(echo "$FILES" | grep '\.sh$' || true)
./tests/markdown/markdownlint_all/run.sh
./tests/yml/yamllint/run.sh
./tests/yml/yamllint_all/run.sh
./tests/git/gitleaks/run.sh
./tests/shell/shfmt/run.sh
./tests/simple/codespell/run.sh
./tests/simple/json_validate/run.sh
```

## Requirements
Expand All @@ -308,11 +379,15 @@ SH_FILES=$(echo "$FILES" | grep '\.sh$' || true)
- jq
- Node.js with npx (for JavaScript/TypeScript, CSS, HTML hooks)
- Python 3, Flake8, Mypy, Pytest (for Python hooks)
- Ruff (`pip install ruff`) for `python/check_ruff.sh`
- Codespell (`pip install codespell`) for `simple/check_codespell.sh`
- PHP 8.1+ with Composer (for PHP hooks)
- Stylelint (`npm install -g stylelint`) or via `npx`
- HTMLHint (`npm install -g htmlhint`) or via `npx`
- markdownlint-cli (`npm install -g markdownlint-cli`)
- yamllint (`pip install yamllint` or system package)
- shfmt (`go install mvdan.cc/sh/v3/cmd/shfmt@latest` or `brew install shfmt`) for `shell/check_shfmt.sh`
- gitleaks (optional, see [install guide](https://github.com/gitleaks/gitleaks#installing)) for `git/check_gitleaks.sh`
- Docker (optional, for Docker-based hooks)
- ShellCheck (for shell validation)

Expand Down
26 changes: 26 additions & 0 deletions git/check_gitleaks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Scans staged changes for secrets and tokens using gitleaks.
# Runs gitleaks protect --staged --redact --exit-code 1.
# Exits 0 with a warning if gitleaks is not installed (optional hook).
# Exits 1 if any secrets are detected; exits 0 on clean scan.
# ------------------------------------------------------------------------------

if ! command -v gitleaks > /dev/null 2>&1; then
echo "WARNING: gitleaks is not installed. Skipping secret detection."
echo "Install it with: https://github.com/gitleaks/gitleaks#installing"
exit 0
fi

OUTPUT=$(gitleaks protect --staged --redact --exit-code 1 2>&1)
EXIT_CODE=$?

if [ $EXIT_CODE -ne 0 ]; then
echo "ERROR: gitleaks detected secrets in staged changes!"
echo "$OUTPUT"
echo "Remove the secrets above before committing."
exit 1
fi

echo "gitleaks: no secrets detected in staged changes."
exit 0
25 changes: 25 additions & 0 deletions git/check_gitleaks_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Scans the entire repository history for secrets using gitleaks detect.
# Runs gitleaks detect --redact --exit-code 1 on the full git history.
# Exits 0 with a warning if gitleaks is not installed (optional hook).
# Exits 1 if any secrets are detected; exits 0 on clean scan.
# ------------------------------------------------------------------------------

if ! command -v gitleaks > /dev/null 2>&1; then
echo "WARNING: gitleaks is not installed. Skipping secret detection."
echo "Install it with: https://github.com/gitleaks/gitleaks#installing"
exit 0
fi

OUTPUT=$(gitleaks detect --redact --exit-code 1 2>&1)
EXIT_CODE=$?

if [ $EXIT_CODE -ne 0 ]; then
echo "ERROR: gitleaks detected secrets in repository history!"
echo "$OUTPUT"
exit 1
fi

echo "gitleaks: no secrets detected in repository history."
exit 0
1 change: 1 addition & 0 deletions git/preparations/prepare-commit-description.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ PROMPT="git-agent desc commit en $STAGED_FILES"
COMMIT_TEXT=$(printf "%s\n" "$PROMPT" | claude -p)

# Remove possible triple backticks ``` and empty lines
# shellcheck disable=SC2016
COMMIT_TEXT=$(echo "$COMMIT_TEXT" | sed 's/^```//; s/```$//' | sed '/^$/d')

# Exit if the generated text is empty
Expand Down
Loading
Loading