Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
91 changes: 91 additions & 0 deletions .github/workflows/pr-scope-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: PR Scope Check

permissions:
contents: read
pull-requests: read

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
scope-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Get full history for proper diff

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install dependencies
run: |
python -m pip install --upgrade pip

- name: Run PR Scope Check
run: |
python scripts/check_pr_scope.py --strict
continue-on-error: false

- name: Check branch naming (secure)
env:
BRANCH_NAME: ${{ github.head_ref }}
run: |
# Validate branch name using environment variable (safer than direct interpolation)
if [[ ! "$BRANCH_NAME" =~ ^(feat|fix|chore|refactor|docs|test)/[a-z]+(-[a-z]+)*$ ]]; then
echo "❌ Branch name must follow pattern: type/short-description"
echo " Current: $BRANCH_NAME"
echo " Examples: feat/add-user-auth, fix/validate-input, chore/update-deps"
exit 1
fi
echo "βœ… Branch name follows convention: $BRANCH_NAME"

- name: Check PR size limits (secure)
env:
BASE_BRANCH: ${{ github.base_ref }}
HEAD_REF: ${{ github.head_ref }}
run: |
# Validate input parameters
if [[ -z "$BASE_BRANCH" || -z "$HEAD_REF" ]]; then
echo "❌ Missing required branch information"
exit 1
fi

# Ensure base branch exists in origin
if ! git show-ref --verify --quiet "refs/remotes/origin/$BASE_BRANCH"; then
echo "❌ Base branch origin/$BASE_BRANCH not found"
exit 1
fi

# Count files changed using triple-dot merge-base diff for accurate PR changes
FILES_CHANGED=$(git diff --name-only "origin/$BASE_BRANCH...HEAD" | wc -l)
echo "Files changed: $FILES_CHANGED"

# Count lines changed using triple-dot merge-base diff for accurate PR changes
SHORTSTAT=$(git diff --shortstat "origin/$BASE_BRANCH...HEAD")
LINES_CHANGED=0

if [[ -n "$SHORTSTAT" ]]; then
# Extract insertions and deletions from shortstat
INSERTIONS=$(echo "$SHORTSTAT" | grep -o '[0-9]\+ insertion' | head -1 | grep -o '[0-9]\+' || echo "0")
DELETIONS=$(echo "$SHORTSTAT" | grep -o '[0-9]\+ deletion' | head -1 | grep -o '[0-9]\+' || echo "0")
LINES_CHANGED=$((INSERTIONS + DELETIONS))
fi

echo "Lines changed: $LINES_CHANGED"

# Check limits with proper error handling
if [[ "$FILES_CHANGED" -gt 50 ]]; then
echo "❌ Too many files changed: $FILES_CHANGED (max 50)"
exit 1
fi

if [[ "$LINES_CHANGED" -gt 1500 ]]; then
echo "❌ Too many lines changed: $LINES_CHANGED (max 1500)"
exit 1
fi

echo "βœ… PR size within limits: $FILES_CHANGED files, $LINES_CHANGED lines"
42 changes: 42 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SAMO-DL Makefile - Minimal Code Quality Edition
.PHONY: help format lint test quality-check clean check-scope pre-commit-install

help: ## Show this help message
@echo "SAMO-DL Code Quality Commands"
@echo "============================="
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'

format: ## Format code with ruff
ruff format src/ tests/ scripts/

lint: ## Run comprehensive linting with ruff and pylint
ruff check src/ tests/ scripts/
pylint --rcfile=pyproject.toml src/ tests/ scripts/

test: ## Run tests with coverage
pytest tests/ --cov=src --cov-report=term-missing

quality-check: ## Run all quality checks (matches pre-commit)
@echo "Running comprehensive code quality checks..."
ruff check --diff src/ tests/ scripts/
ruff format --check src/ tests/ scripts/
pylint --rcfile=pyproject.toml src/ tests/ scripts/
mypy src/ tests/ scripts/
bandit -r src/ -c pyproject.toml
bandit -r tests/ -c pyproject.toml -s B101
safety scan --json --output safety-report.json
docformatter --check --wrap-summaries=88 --wrap-descriptions=88 src/ tests/ scripts/

check-scope: ## Check PR scope compliance
python scripts/check_pr_scope.py --strict

pre-commit-install: ## Install pre-commit hooks
pre-commit install
git config commit.template .gitmessage.txt

clean: ## Clean up generated files
rm -rf build/ dist/ *.egg-info/
rm -rf .pytest_cache/ .coverage htmlcov/
rm -rf bandit-report.json safety-report.json
find . -type d -name __pycache__ -exec rm -rf {} +
find . -type f -name "*.pyc" -delete
Loading
Loading