Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f83ee53b6e | |||
| 9fff3c883d | |||
| 583229af05 | |||
| 9ab1455dbb | |||
| 209c628c5f | |||
| 7f7f5b8228 | |||
| 1f92dad033 | |||
| cf9a21278d | |||
| 605d0403ed | |||
| 75769927ae | |||
| ff9f397618 | |||
| 50c135b336 | |||
| ecaab5ba3a | |||
| 575fae1b3b | |||
| 04aceae6b2 | |||
| 5b32e78a63 | |||
| b28a802403 | |||
| 644c3ac03c | |||
| 47898c7ddb | |||
| 3058a53097 | |||
| fc3803cfe7 | |||
| 981d4e5ae8 | |||
| 748e779740 | |||
| 5a12112c96 | |||
| d9cbeaf66e | |||
| f6b9bfda13 | |||
| 003ca3c52b | |||
| efdc09af01 | |||
| ee81f14f34 | |||
| 492062f5de | |||
| 5748f919f7 | |||
| 9b1f71d7c4 | |||
| 538cd82400 | |||
| 1a940442ba | |||
| 3da939a38d | |||
| 6882dab217 | |||
| fb9cabcd02 | |||
| b5f0cc5837 | |||
| 1006c7c4f6 | |||
| a09213a46f | |||
| ecc88227fe | |||
| 7a740c1906 | |||
| ab094b87d7 | |||
| 23fef7df19 | |||
| 5be61d84ac | |||
| 817cd9b835 | |||
| ff3110225f |
@@ -20,38 +20,10 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -e ".[dev]"
|
pip install -e .
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: pytest tests/ -v --cov=config_auditor
|
run: pytest tests/ -v --cov=config_auditor
|
||||||
|
|
||||||
- name: Run linting
|
- name: Run linting
|
||||||
run: ruff check config_auditor/ tests/
|
run: ruff check .
|
||||||
|
|
||||||
build:
|
|
||||||
needs: test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
cache: 'pip'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
pip install --upgrade pip
|
|
||||||
pip install .
|
|
||||||
|
|
||||||
- name: Build package
|
|
||||||
run: |
|
|
||||||
pip install build
|
|
||||||
python -m build
|
|
||||||
|
|
||||||
- name: Upload package
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: dist
|
|
||||||
path: dist/
|
|
||||||
|
|||||||
101
.gitignore
vendored
101
.gitignore
vendored
@@ -1,11 +1,94 @@
|
|||||||
*.pyc
|
# =============================================================================
|
||||||
__pycache__/
|
# 7000%AUTO .gitignore
|
||||||
venv/
|
# =============================================================================
|
||||||
|
|
||||||
|
# Environment
|
||||||
.env
|
.env
|
||||||
*.egg-info/
|
.env.local
|
||||||
.coverage
|
.env.*.local
|
||||||
.pytest_cache/
|
|
||||||
.mypy_cache/
|
# Python
|
||||||
.ruff_cache/
|
__pycache__/
|
||||||
.dist/
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
build/
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env/
|
||||||
|
.venv/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.project
|
||||||
|
.pydevproject
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
htmlcov/
|
||||||
|
.pytest_cache/
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Database
|
||||||
|
data/
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite3
|
||||||
|
|
||||||
|
# Workspace (generated projects)
|
||||||
|
workspace/
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.docker/
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
|
||||||
|
# Secrets
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
secrets/
|
||||||
|
|||||||
13
app/MANIFEST.in
Normal file
13
app/MANIFEST.in
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
include README.md
|
||||||
|
include LICENSE
|
||||||
|
include pyproject.toml
|
||||||
|
include setup.py
|
||||||
|
|
||||||
|
exclude tests/*
|
||||||
|
exclude fixtures/*
|
||||||
|
exclude database/*
|
||||||
|
exclude depnav/*
|
||||||
|
exclude gitignore_generator/*
|
||||||
|
exclude mcp_servers/*
|
||||||
|
exclude orchestrator/*
|
||||||
|
exclude web/*
|
||||||
60
app/pyproject.toml
Normal file
60
app/pyproject.toml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=61.0", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "config_auditor"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "A CLI tool that scans project configuration files and detects issues"
|
||||||
|
readme = "README.md"
|
||||||
|
license = {text = "MIT"}
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
authors = [
|
||||||
|
{name = "Config Auditor Team", email = "dev@example.com"}
|
||||||
|
]
|
||||||
|
keywords = ["config", "cli", "audit", "scanner"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Environment :: Console",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"click>=8.0.0",
|
||||||
|
"PyYAML>=6.0",
|
||||||
|
"toml>=0.10.0",
|
||||||
|
"requests>=2.31.0",
|
||||||
|
"semver>=3.0.0",
|
||||||
|
"packaging>=23.0",
|
||||||
|
"ollama>=0.1.41",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
config-auditor = "config_auditor.cli:main"
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest>=7.0.0",
|
||||||
|
"pytest-cov>=4.0.0",
|
||||||
|
"pytest-mock>=3.10.0",
|
||||||
|
"ruff>=0.1.0",
|
||||||
|
"mypy>=1.0.0",
|
||||||
|
"types-requests>=2.25.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["."]
|
||||||
|
include = ["config_auditor"]
|
||||||
|
exclude = ["tests", "fixtures"]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
python_files = ["test_*.py"]
|
||||||
|
python_classes = ["Test*"]
|
||||||
|
python_functions = ["test_*"]
|
||||||
|
addopts = "-v --cov=config_auditor --cov-report=term-missing"
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import sys
|
import sys
|
||||||
import click
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from config_auditor.cli import cli
|
from config_auditor.cli import cli
|
||||||
|
|
||||||
|
|||||||
@@ -201,10 +201,8 @@ def generate(ctx: click.Context, template: Optional[str]):
|
|||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def config(ctx: click Context):
|
def config(ctx: click.Context):
|
||||||
"""Show current configuration."""
|
"""Show current configuration."""
|
||||||
import yaml
|
|
||||||
|
|
||||||
config_path = Path("config.yaml")
|
config_path = Path("config.yaml")
|
||||||
if config_path.exists():
|
if config_path.exists():
|
||||||
content = config_path.read_text()
|
content = config_path.read_text()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from abc import ABC, abstractmethod
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Dict, List, Optional
|
from typing import Any, Callable, Dict, List, Optional
|
||||||
import json
|
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
import json
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
from packaging import version
|
from packaging import version
|
||||||
|
|||||||
58
pyproject.toml
Normal file
58
pyproject.toml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=61.0", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "config_auditor"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "A CLI tool that scans project configuration files and detects issues"
|
||||||
|
readme = "README.md"
|
||||||
|
license = {text = "MIT"}
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
authors = [
|
||||||
|
{name = "Config Auditor Team", email = "dev@example.com"}
|
||||||
|
]
|
||||||
|
keywords = ["config", "cli", "audit", "scanner"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Environment :: Console",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"click>=8.0.0",
|
||||||
|
"PyYAML>=6.0",
|
||||||
|
"toml>=0.10.0",
|
||||||
|
"requests>=2.31.0",
|
||||||
|
"semver>=3.0.0",
|
||||||
|
"packaging>=23.0",
|
||||||
|
"ollama>=0.1.41",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
config-auditor = "config_auditor.cli:main"
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest>=7.0.0",
|
||||||
|
"pytest-cov>=4.0.0",
|
||||||
|
"pytest-mock>=3.10.0",
|
||||||
|
"ruff>=0.1.0",
|
||||||
|
"mypy>=1.0.0",
|
||||||
|
"types-requests>=2.25.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["."]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
python_files = ["test_*.py"]
|
||||||
|
python_classes = ["Test*"]
|
||||||
|
python_functions = ["test_*"]
|
||||||
|
addopts = "-v --cov=config_auditor --cov-report=term-missing"
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import pytest
|
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import pytest
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tempfile
|
import tempfile
|
||||||
import os
|
|
||||||
|
|
||||||
from config_auditor.fixes import (
|
from config_auditor.fixes import (
|
||||||
Fixer,
|
Fixer,
|
||||||
@@ -84,7 +82,7 @@ class TestFixer:
|
|||||||
config_path.write_text(content)
|
config_path.write_text(content)
|
||||||
|
|
||||||
fixer = Fixer(dry_run=True)
|
fixer = Fixer(dry_run=True)
|
||||||
fix_count = fixer.fix_config(config_path, "json", content)
|
fixer.fix_config(config_path, "json", content)
|
||||||
|
|
||||||
actual_content = config_path.read_text()
|
actual_content = config_path.read_text()
|
||||||
assert actual_content == content
|
assert actual_content == content
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import pytest
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tempfile
|
import tempfile
|
||||||
import json
|
import pytest
|
||||||
|
|
||||||
from config_auditor.generate import ConfigGenerator
|
from config_auditor.generate import ConfigGenerator
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import pytest
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from unittest.mock import Mock, patch, MagicMock
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
from config_auditor.llm import (
|
from config_auditor.llm import (
|
||||||
LLMClient,
|
|
||||||
OllamaClient,
|
OllamaClient,
|
||||||
FallbackClient,
|
FallbackClient,
|
||||||
LLMProvider,
|
LLMProvider,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import pytest
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tempfile
|
import tempfile
|
||||||
import os
|
|
||||||
|
|
||||||
from config_auditor.discovery import ConfigDiscovery
|
from config_auditor.discovery import ConfigDiscovery
|
||||||
from config_auditor.parsers import ParserFactory, JsonParser, YamlParser, TomlParser
|
from config_auditor.parsers import ParserFactory, JsonParser, YamlParser, TomlParser
|
||||||
@@ -10,7 +8,6 @@ from config_auditor.rules import (
|
|||||||
DeprecatedPackageRule,
|
DeprecatedPackageRule,
|
||||||
OutdatedVersionRule,
|
OutdatedVersionRule,
|
||||||
MissingTypeCheckingRule,
|
MissingTypeCheckingRule,
|
||||||
SecurityVulnerabilityRule,
|
|
||||||
MissingScriptsRule,
|
MissingScriptsRule,
|
||||||
PythonProjectMetaRule,
|
PythonProjectMetaRule,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import pytest
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tempfile
|
|
||||||
|
|
||||||
from config_auditor.report import ReportGenerator
|
from config_auditor.report import ReportGenerator
|
||||||
from config_auditor.rules import Issue
|
from config_auditor.rules import Issue
|
||||||
|
|||||||
@@ -1,64 +1,59 @@
|
|||||||
import pytest
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from config_auditor.utils import (
|
from config_auditor.utils import (
|
||||||
find_config_file,
|
find_config_file,
|
||||||
get_exit_code,
|
get_exit_code,
|
||||||
|
format_severity,
|
||||||
validate_path,
|
validate_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestUtils:
|
class TestFindConfigFile:
|
||||||
def test_find_config_file_exists(self):
|
def test_finds_config_in_current_directory(self):
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
(Path(tmpdir) / "package.json").write_text("{}")
|
config_path = Path(tmpdir) / "config.yaml"
|
||||||
|
config_path.write_text("key: value")
|
||||||
|
|
||||||
result = find_config_file(Path(tmpdir), ["package.json"])
|
result = find_config_file(Path(tmpdir), ["config.yaml"])
|
||||||
|
|
||||||
assert result is not None
|
assert result == config_path
|
||||||
assert result.name == "package.json"
|
|
||||||
|
|
||||||
def test_find_config_file_not_exists(self):
|
def test_finds_config_in_parent_directory(self):
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
|
||||||
result = find_config_file(Path(tmpdir), ["nonexistent.json"])
|
|
||||||
|
|
||||||
assert result is None
|
|
||||||
|
|
||||||
def test_find_config_file_in_parent(self):
|
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
subdir = Path(tmpdir) / "subdir"
|
subdir = Path(tmpdir) / "subdir"
|
||||||
subdir.mkdir()
|
subdir.mkdir()
|
||||||
(Path(tmpdir) / "package.json").write_text("{}")
|
|
||||||
|
|
||||||
result = find_config_file(subdir, ["package.json"])
|
config_path = Path(tmpdir) / "config.yaml"
|
||||||
|
config_path.write_text("key: value")
|
||||||
|
|
||||||
assert result is not None
|
result = find_config_file(subdir, ["config.yaml"])
|
||||||
|
|
||||||
def test_get_exit_code_no_issues(self):
|
assert result == config_path
|
||||||
result = get_exit_code(0, 0)
|
|
||||||
assert result == 0
|
|
||||||
|
|
||||||
def test_get_exit_code_has_issues(self):
|
def test_returns_none_when_not_found(self):
|
||||||
result = get_exit_code(5, 0)
|
|
||||||
assert result == 4
|
|
||||||
|
|
||||||
def test_get_exit_code_critical(self):
|
|
||||||
result = get_exit_code(3, 2)
|
|
||||||
assert result == 4
|
|
||||||
|
|
||||||
def test_validate_path_exists(self):
|
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
result = validate_path(tmpdir)
|
result = find_config_file(Path(tmpdir), ["nonexistent.yaml"])
|
||||||
assert result.exists()
|
|
||||||
|
|
||||||
def test_validate_path_not_exists(self):
|
assert result is None
|
||||||
with pytest.raises(SystemExit) as excinfo:
|
|
||||||
validate_path("/nonexistent/path")
|
|
||||||
assert excinfo.value.code == 2
|
|
||||||
|
|
||||||
def test_validate_path_is_file(self):
|
|
||||||
with tempfile.NamedTemporaryFile() as f:
|
class TestGetExitCode:
|
||||||
with pytest.raises(SystemExit) as excinfo:
|
def test_returns_4_for_critical_issues(self):
|
||||||
validate_path(f.name)
|
assert get_exit_code(1, 1) == 4
|
||||||
assert excinfo.value.code == 2
|
|
||||||
|
def test_returns_4_for_warnings_without_critical(self):
|
||||||
|
assert get_exit_code(3, 0) == 4
|
||||||
|
|
||||||
|
def test_returns_0_for_no_issues(self):
|
||||||
|
assert get_exit_code(0, 0) == 0
|
||||||
|
|
||||||
|
|
||||||
|
class TestFormatSeverity:
|
||||||
|
def test_format_severity_colors(self):
|
||||||
|
assert format_severity("critical") == "red"
|
||||||
|
assert format_severity("warning") == "yellow"
|
||||||
|
assert format_severity("info") == "blue"
|
||||||
|
|
||||||
|
def test_format_severity_default(self):
|
||||||
|
assert format_severity("unknown") == "white"
|
||||||
|
|||||||
Reference in New Issue
Block a user