Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REPO_EVALUATOR_HOST=0.0.0.0
REPO_EVALUATOR_PORT=8000
REPO_EVALUATOR_LOG_LEVEL=info
52 changes: 52 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: CI

on:
push:
branches: [main, feature/*]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12", "3.13"]

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

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run tests with coverage
run: pytest

- name: Run linting
run: ruff check .

docker-build:
runs-on: ubuntu-latest
needs: test

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

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: repo-evaluator:latest
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
.venv/
venv/
ENV/
env/
*.egg-info/
dist/
build/

# Testing
.pytest_cache/
.coverage
htmlcov/
.mypy_cache/

# Environment
.env
.env.local

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM python:3.12-slim AS builder

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*

COPY pyproject.toml ./
COPY README.md ./
COPY src/ ./src/

RUN pip install --no-cache-dir -e "."

FROM python:3.12-slim

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends git docker.io && rm -rf /var/lib/apt/lists/*

COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY src/ ./src/
COPY pyproject.toml ./
COPY README.md ./

RUN pip install --no-cache-dir -e "."

EXPOSE 8000

CMD ["uvicorn", "repo_evaluator.main:app", "--host", "0.0.0.0", "--port", "8000"]
141 changes: 140 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,140 @@
# python-repo-evaluator
# python-repo-evaluator

Evaluate Python repositories for health, structure, and Docker readiness.

## Features

- **Repository Analysis**: Clone and inspect any public GitHub repository.
- **Health Scoring**: Automated scoring based on README, Dockerfile, docker-compose, dependency files, tests, Python files, collected tests, and Docker build success.
- **Docker Validation**: Detects `Dockerfile` presence and attempts a build to verify it works.
- **CLI Tool**: Run evaluations from the terminal with JSON or Markdown output.
- **REST API**: FastAPI-based HTTP API for programmatic access.
- **CI/CD Ready**: GitHub Actions workflow included for automated testing and Docker validation.

## Install

Requires Python 3.12+.

```bash
pip install -e ".[dev]"
```

## Usage

### CLI

```bash
# Evaluate a repo and output JSON (default)
repo-eval evaluate https://github.com/example/repo --output json

# Evaluate a repo and output Markdown
repo-eval evaluate https://github.com/example/repo --output markdown
```

### API

```bash
# Start the server
uvicorn repo_evaluator.main:app --reload --host 0.0.0.0 --port 8000
```

Then POST to `http://localhost:8000/api/v1/evaluate` with:

```json
{
"repo_url": "https://github.com/example/repo"
}
```

Health check: `GET http://localhost:8000/health` (also available at `/api/v1/health`)

### Docker

```bash
# Build and run with Docker Compose
docker-compose up --build

# Or build manually
docker build -t repo-evaluator .
docker run -p 8000:8000 repo-evaluator
```

## Scoring Rubric

| Category | Weight | Criteria |
|----------|--------|----------|
| README | 15 | `README.md` (or `.rst`, `.txt`) present |
| Dockerfile | 15 | `Dockerfile` present |
| docker-compose | 10 | `docker-compose.yml` (or `.yaml`) present |
| Dependency file | 10 | `requirements.txt`, `pyproject.toml`, `setup.py`, or `setup.cfg` present |
| Tests directory | 10 | `tests/` or `test/` directory present |
| Python files | 10 | At least one `.py` file in the repo |
| Collected tests | 15 | `pytest --collect-only` finds > 0 tests |
| Docker build | 15 | `docker build` succeeds for the repo |

**Max score: 100**

## Development

```bash
# Run tests with coverage
pytest

# Run linting
ruff check .

# Run type checking
mypy src/repo_evaluator
```

## Environment Variables

Copy `.env.example` to `.env` and adjust as needed:

```bash
cp .env.example .env
```

| Variable | Description | Default |
|----------|-------------|---------|
| `REPO_EVALUATOR_HOST` | API bind host | `0.0.0.0` |
| `REPO_EVALUATOR_PORT` | API bind port | `8000` |
| `REPO_EVALUATOR_LOG_LEVEL` | Logging level | `info` |

## CI/CD

This project includes a GitHub Actions workflow (`.github/workflows/ci.yml`) that:

1. Runs the test suite with pytest and enforces 70% coverage.
2. Validates the Docker image builds successfully.
3. Runs linting with ruff.

## Project Structure

```
python-repo-evaluator/
├── src/repo_evaluator/ # Source code
│ ├── __init__.py
│ ├── analyzer.py # Repository analysis
│ ├── api.py # FastAPI routes
│ ├── cli.py # Typer CLI
│ ├── docker_validator.py # Docker build validation
│ ├── formatters.py # JSON / Markdown output
│ ├── main.py # FastAPI app factory
│ ├── models.py # Pydantic models
│ └── scorer.py # Health scoring logic
├── tests/ # Test suite (pytest)
├── scripts/
│ └── run-local.sh # Local API startup helper
├── .github/workflows/
│ └── ci.yml # GitHub Actions CI
├── Dockerfile # Multi-stage Python 3.12 build
├── docker-compose.yml # Local orchestration
├── .env.example # Environment template
├── pyproject.toml # Project config & dependencies
└── README.md # This file
```

## License

MIT
10 changes: 10 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
repo-evaluator:
build: .
ports:
- "8000:8000"
env_file:
- .env
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
73 changes: 73 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "repo-evaluator"
version = "0.1.0"
description = "Evaluate Python repositories for health, structure, and Docker readiness."
readme = "README.md"
requires-python = ">=3.12"
license = { text = "MIT" }
authors = [
{ name = "SD Soporte", email = "sdsoporte@example.com" },
]
keywords = ["python", "repository", "health", "docker", "cli"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Software Development :: Quality Assurance",
]
dependencies = [
"pydantic>=2.0",
"typer>=0.12",
"fastapi>=0.110",
"uvicorn[standard]>=0.29",
"gitpython>=3.1",
"httpx>=0.27",
]

[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-cov>=5.0",
"mypy>=1.9",
"ruff>=0.4",
"respx>=0.21",
]

[project.scripts]
repo-eval = "repo_evaluator.cli:app"

[tool.hatch.build.targets.wheel]
packages = ["src/repo_evaluator"]

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=repo_evaluator --cov-report=term-missing --cov-fail-under=70"

[tool.coverage.run]
source = ["src/repo_evaluator"]
branch = true

[tool.coverage.report]
show_missing = true
skip_covered = false

[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_configs = true

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
ignore = ["E501"]
31 changes: 31 additions & 0 deletions scripts/run-local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail

# Local development startup script for python-repo-evaluator API

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
VENV_PATH="${PROJECT_ROOT}/.venv"

if [ ! -d "$VENV_PATH" ]; then
echo "Virtual environment not found at $VENV_PATH"
echo "Run: python -m venv .venv && source .venv/bin/activate && pip install -e \".[dev]\""
exit 1
fi

source "$VENV_PATH/bin/activate"

HOST="${REPO_EVALUATOR_HOST:-0.0.0.0}"
PORT="${REPO_EVALUATOR_PORT:-8000}"
LOG_LEVEL="${REPO_EVALUATOR_LOG_LEVEL:-info}"

echo "Starting python-repo-evaluator API on http://${HOST}:${PORT}"
echo "Health check: http://${HOST}:${PORT}/api/v1/health"
echo "Evaluate endpoint: POST http://${HOST}:${PORT}/api/v1/evaluate"
echo "Press Ctrl+C to stop"

exec uvicorn repo_evaluator.main:app \
--host "$HOST" \
--port "$PORT" \
--log-level "$LOG_LEVEL" \
--reload
3 changes: 3 additions & 0 deletions src/repo_evaluator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""repo-evaluator package."""

__version__ = "0.1.0"
Loading
Loading