Upload folder using huggingface_hub
Browse files- README.md +161 -0
- auto-guardian-system.zip +3 -0
- core_system/auto-fix.sh +362 -0
- core_system/code-analyzer.py +411 -0
- core_system/pyproject.toml +36 -0
- core_system/report-generator.py +216 -0
- core_system/requirements.txt +19 -0
README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# GitHub Auto-Guardian
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
GitHub Auto-Guardian is an automated code quality maintenance system for GitHub repositories. It automatically detects and fixes code issues, prevents merging of broken code, and alerts you to problems that require human intervention.
|
| 6 |
+
|
| 7 |
+
## Features
|
| 8 |
+
|
| 9 |
+
- **Issue Detection**: Analyze code for syntax errors, security vulnerabilities, and code quality issues
|
| 10 |
+
- **Auto-Fix**: Automatically fix formatting issues, linting errors, and style violations
|
| 11 |
+
- **Quality Gate**: Prevent merging of code that doesn't meet quality standards
|
| 12 |
+
- **Smart Alerts**: Notify developers about issues that require human intervention
|
| 13 |
+
|
| 14 |
+
## Quick Start
|
| 15 |
+
|
| 16 |
+
### 1. Setup
|
| 17 |
+
|
| 18 |
+
```bash
|
| 19 |
+
# Copy the .github folder to your project
|
| 20 |
+
cp -r .github/ /path/to/your/project/
|
| 21 |
+
|
| 22 |
+
# Install dependencies
|
| 23 |
+
pip install -r .github/scripts/requirements.txt
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
### 2. Configure Branch Protection
|
| 27 |
+
|
| 28 |
+
Go to your GitHub repository settings:
|
| 29 |
+
|
| 30 |
+
1. Navigate to **Settings** → **Branches** → **Branch protection rules**
|
| 31 |
+
2. Create a new rule for your main branch
|
| 32 |
+
3. Enable **Require status checks to pass before merging**
|
| 33 |
+
4. Add `Auto-Guardian Quality Gate` to the required checks
|
| 34 |
+
|
| 35 |
+
### 3. Test the System
|
| 36 |
+
|
| 37 |
+
Create a pull request with some code quality issues to see the system in action.
|
| 38 |
+
|
| 39 |
+
## File Structure
|
| 40 |
+
|
| 41 |
+
```
|
| 42 |
+
.github/
|
| 43 |
+
├── workflows/
|
| 44 |
+
│ └── auto-maintenance.yml # Main GitHub Actions workflow
|
| 45 |
+
├── scripts/
|
| 46 |
+
│ ├── auto-fix.sh # Auto-fix script
|
| 47 |
+
│ ├── code-analyzer.py # Code analysis script
|
| 48 |
+
│ ├── report-generator.py # Report generation script
|
| 49 |
+
│ └── requirements.txt # Python dependencies
|
| 50 |
+
└── configs/
|
| 51 |
+
├── .eslintrc.json # ESLint configuration
|
| 52 |
+
├── .prettierrc # Prettier configuration
|
| 53 |
+
└── pyproject.toml # Python tools configuration
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
## Local Usage
|
| 57 |
+
|
| 58 |
+
### Run Code Analysis
|
| 59 |
+
|
| 60 |
+
```bash
|
| 61 |
+
python .github/scripts/code-analyzer.py
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
### Run Auto-Fix
|
| 65 |
+
|
| 66 |
+
```bash
|
| 67 |
+
bash .github/scripts/auto-fix.sh
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
### Generate Report
|
| 71 |
+
|
| 72 |
+
```bash
|
| 73 |
+
python .github/scripts/report-generator.py --scan-results scan-results.json
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
## Supported Languages
|
| 77 |
+
|
| 78 |
+
- Python
|
| 79 |
+
- JavaScript / TypeScript
|
| 80 |
+
- Go
|
| 81 |
+
- Java
|
| 82 |
+
|
| 83 |
+
## How It Works
|
| 84 |
+
|
| 85 |
+
### 1. Detection Phase
|
| 86 |
+
The system analyzes your code using multiple tools:
|
| 87 |
+
- Linters (ESLint, Flake8, Pylint)
|
| 88 |
+
- Security scanners (Bandit, custom patterns)
|
| 89 |
+
- Code quality analyzers
|
| 90 |
+
|
| 91 |
+
### 2. Auto-Fix Phase
|
| 92 |
+
The system automatically fixes issues that are safe to correct:
|
| 93 |
+
- Code formatting
|
| 94 |
+
- Import organization
|
| 95 |
+
- Style violations
|
| 96 |
+
- Deprecated syntax
|
| 97 |
+
|
| 98 |
+
### 3. Quality Gate Phase
|
| 99 |
+
All changes must pass strict quality checks:
|
| 100 |
+
- Test execution
|
| 101 |
+
- Code complexity limits
|
| 102 |
+
- Type checking
|
| 103 |
+
- Security validation
|
| 104 |
+
|
| 105 |
+
### 4. Alert Phase
|
| 106 |
+
The system provides clear feedback:
|
| 107 |
+
- Comments on Pull Requests
|
| 108 |
+
- Slack/Discord notifications (optional)
|
| 109 |
+
- Status checks with detailed reports
|
| 110 |
+
|
| 111 |
+
## Configuration
|
| 112 |
+
|
| 113 |
+
### Customizing Rules
|
| 114 |
+
|
| 115 |
+
Edit the configuration files to customize behavior:
|
| 116 |
+
|
| 117 |
+
- `.eslintrc.json` - ESLint rules
|
| 118 |
+
- `.prettierrc` - Prettier formatting rules
|
| 119 |
+
- `pyproject.toml` - Python tool settings
|
| 120 |
+
- `.github/workflows/auto-maintenance.yml` - CI/CD pipeline
|
| 121 |
+
|
| 122 |
+
### Adding New Languages
|
| 123 |
+
|
| 124 |
+
1. Add language detection to `code-analyzer.py`
|
| 125 |
+
2. Add fix commands to `auto-fix.sh`
|
| 126 |
+
3. Create language-specific configurations
|
| 127 |
+
|
| 128 |
+
## Troubleshooting
|
| 129 |
+
|
| 130 |
+
### Issues Not Being Fixed
|
| 131 |
+
|
| 132 |
+
1. Check if the issue is marked as `fixable: false`
|
| 133 |
+
2. Review the suggestion in the report
|
| 134 |
+
3. Manual intervention may be required
|
| 135 |
+
|
| 136 |
+
### False Positives
|
| 137 |
+
|
| 138 |
+
1. Add suppressions to ESLint/Pylint config
|
| 139 |
+
2. Use `# noqa` comments in code
|
| 140 |
+
3. Update the analyzer rules
|
| 141 |
+
|
| 142 |
+
### Workflow Not Running
|
| 143 |
+
|
| 144 |
+
1. Verify GitHub Actions are enabled
|
| 145 |
+
2. Check branch protection settings
|
| 146 |
+
3. Review workflow syntax
|
| 147 |
+
|
| 148 |
+
## Contributing
|
| 149 |
+
|
| 150 |
+
1. Fork the repository
|
| 151 |
+
2. Create a feature branch
|
| 152 |
+
3. Make your changes
|
| 153 |
+
4. Submit a pull request
|
| 154 |
+
|
| 155 |
+
## License
|
| 156 |
+
|
| 157 |
+
MIT License - feel free to use this in your projects.
|
| 158 |
+
|
| 159 |
+
## Support
|
| 160 |
+
|
| 161 |
+
For issues and feature requests, please open a GitHub issue.
|
auto-guardian-system.zip
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:96a306735b7279473a7d16f9f9f8e961e141cab38ed42eb1c747157e6e0964bc
|
| 3 |
+
size 15963
|
core_system/auto-fix.sh
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# ============================================================================
|
| 4 |
+
# Auto-Guardian: Auto-Fix Script
|
| 5 |
+
# ============================================================================
|
| 6 |
+
# Purpose: Fix common issues automatically without affecting code behavior
|
| 7 |
+
# Supported Languages: JavaScript, Python, TypeScript, Go, Java
|
| 8 |
+
# ============================================================================
|
| 9 |
+
|
| 10 |
+
set -e # Exit on first error
|
| 11 |
+
|
| 12 |
+
# Colors for beautiful output
|
| 13 |
+
RED='\033[0;31m'
|
| 14 |
+
GREEN='\033[0;32m'
|
| 15 |
+
YELLOW='\033[1;33m'
|
| 16 |
+
BLUE='\033[0;34m'
|
| 17 |
+
NC='\033[0m' # No Color
|
| 18 |
+
|
| 19 |
+
# Environment variables
|
| 20 |
+
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
| 21 |
+
FIXED_COUNT=0
|
| 22 |
+
SKIPPED_COUNT=0
|
| 23 |
+
ERROR_COUNT=0
|
| 24 |
+
|
| 25 |
+
# Helper function for colored logging
|
| 26 |
+
log_info() {
|
| 27 |
+
echo -e "${BLUE}[INFO]${NC} $1"
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
log_success() {
|
| 31 |
+
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
| 32 |
+
((FIXED_COUNT++))
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
log_warning() {
|
| 36 |
+
echo -e "${YELLOW}[WARNING]${NC} $1"
|
| 37 |
+
((SKIPPED_COUNT++))
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
log_error() {
|
| 41 |
+
echo -e "${RED}[ERROR]${NC} $1"
|
| 42 |
+
((ERROR_COUNT++))
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
# ============================================================================
|
| 46 |
+
# Section 1: General File Cleanup
|
| 47 |
+
# ============================================================================
|
| 48 |
+
clean_general() {
|
| 49 |
+
log_info "Starting general file cleanup..."
|
| 50 |
+
|
| 51 |
+
# Remove temporary files
|
| 52 |
+
find . -type f -name "*.pyc" -delete
|
| 53 |
+
find . -type f -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
| 54 |
+
find . -type f -name "*.py.bak" -delete
|
| 55 |
+
find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
|
| 56 |
+
find . -type d -name "node_modules" -exec rm -rf {} + 2>/dev/null || true
|
| 57 |
+
find . -type f -name "*.log" -delete 2>/dev/null || true
|
| 58 |
+
|
| 59 |
+
# Clean system files
|
| 60 |
+
find . -type f -name ".DS_Store" -delete
|
| 61 |
+
find . -type f -name "Thumbs.db" -delete
|
| 62 |
+
|
| 63 |
+
log_success "General cleanup completed"
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
# ============================================================================
|
| 67 |
+
# Section 2: Fix JavaScript/TypeScript
|
| 68 |
+
# ============================================================================
|
| 69 |
+
fix_javascript() {
|
| 70 |
+
log_info "Scanning and fixing JavaScript/TypeScript files..."
|
| 71 |
+
|
| 72 |
+
# Check for package.json
|
| 73 |
+
if [ ! -f "package.json" ]; then
|
| 74 |
+
log_warning "No package.json found - skipping JavaScript"
|
| 75 |
+
return
|
| 76 |
+
fi
|
| 77 |
+
|
| 78 |
+
# Install Prettier and ESLint
|
| 79 |
+
if [ -f "package-lock.json" ] || [ -f "yarn.lock" ]; then
|
| 80 |
+
npm ci --prefer-offline --no-audit 2>/dev/null || npm install
|
| 81 |
+
else
|
| 82 |
+
npm install
|
| 83 |
+
fi
|
| 84 |
+
|
| 85 |
+
# Run Prettier for formatting
|
| 86 |
+
if command -v npx &> /dev/null; then
|
| 87 |
+
if [ -f ".prettierrc.js" ] || [ -f ".prettierrc.json" ] || [ -f "prettier.config.js" ]; then
|
| 88 |
+
npx prettier --write "src/**/*.js" "src/**/*.ts" 2>/dev/null || true
|
| 89 |
+
npx prettier --write "**/*.js" "**/*.ts" 2>/dev/null || true
|
| 90 |
+
log_success "JavaScript/TypeScript formatted"
|
| 91 |
+
fi
|
| 92 |
+
fi
|
| 93 |
+
|
| 94 |
+
# Fix ESLint errors
|
| 95 |
+
if command -v npx &> /dev/null && grep -q '"eslint"' package.json; then
|
| 96 |
+
npx eslint --fix "src/**/*.js" "src/**/*.ts" 2>/dev/null || true
|
| 97 |
+
log_success "ESLint errors fixed"
|
| 98 |
+
fi
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
# ============================================================================
|
| 102 |
+
# Section 3: Fix Python
|
| 103 |
+
# ============================================================================
|
| 104 |
+
fix_python() {
|
| 105 |
+
log_info "Scanning and fixing Python files..."
|
| 106 |
+
|
| 107 |
+
# Check for Python files
|
| 108 |
+
if ! find . -name "*.py" -type f | grep -q .; then
|
| 109 |
+
log_warning "No Python files found in project"
|
| 110 |
+
return
|
| 111 |
+
fi
|
| 112 |
+
|
| 113 |
+
# Install formatting tools
|
| 114 |
+
pip install black isort flake8 autoflake 2>/dev/null || true
|
| 115 |
+
|
| 116 |
+
# Remove unused imports with autoflake
|
| 117 |
+
if command -v autoflake &> /dev/null; then
|
| 118 |
+
autoflake --remove-all-unused-imports --recursive --in-place . 2>/dev/null || true
|
| 119 |
+
log_success "Unused imports removed"
|
| 120 |
+
fi
|
| 121 |
+
|
| 122 |
+
# Organize imports with isort
|
| 123 |
+
if command -v isort &> /dev/null; then
|
| 124 |
+
isort --profile black --apply --diff . 2>/dev/null || true
|
| 125 |
+
isort --profile black --apply . 2>/dev/null || true
|
| 126 |
+
log_success "Imports organized"
|
| 127 |
+
fi
|
| 128 |
+
|
| 129 |
+
# Format code with Black
|
| 130 |
+
if command -v black &> /dev/null; then
|
| 131 |
+
black --line-length 100 --target-version py39 --diff . 2>/dev/null || true
|
| 132 |
+
black --line-length 100 --target-version py39 . 2>/dev/null || true
|
| 133 |
+
log_success "Code formatted with Black"
|
| 134 |
+
fi
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
# ============================================================================
|
| 138 |
+
# Section 4: Fix Go
|
| 139 |
+
# ============================================================================
|
| 140 |
+
fix_go() {
|
| 141 |
+
log_info "Scanning and fixing Go files..."
|
| 142 |
+
|
| 143 |
+
# Check for Go files
|
| 144 |
+
if ! find . -name "*.go" -type f | grep -q .; then
|
| 145 |
+
log_warning "No Go files found in project"
|
| 146 |
+
return
|
| 147 |
+
fi
|
| 148 |
+
|
| 149 |
+
# Format code
|
| 150 |
+
if command -v gofmt &> /dev/null; then
|
| 151 |
+
gofmt -w . 2>/dev/null || true
|
| 152 |
+
log_success "Go formatted"
|
| 153 |
+
fi
|
| 154 |
+
|
| 155 |
+
# Fix imports
|
| 156 |
+
if command -v goimports &> /dev/null; then
|
| 157 |
+
goimports -w . 2>/dev/null || true
|
| 158 |
+
log_success "Go imports fixed"
|
| 159 |
+
fi
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
# ============================================================================
|
| 163 |
+
# Section 5: Fix Java
|
| 164 |
+
# ============================================================================
|
| 165 |
+
fix_java() {
|
| 166 |
+
log_info "Scanning and fixing Java files..."
|
| 167 |
+
|
| 168 |
+
# Check for Java files
|
| 169 |
+
if ! find . -name "*.java" -type f | grep -q .; then
|
| 170 |
+
log_warning "No Java files found in project"
|
| 171 |
+
return
|
| 172 |
+
fi
|
| 173 |
+
|
| 174 |
+
# Check for Google Java Format
|
| 175 |
+
if [ -f ".google-java-format" ]; then
|
| 176 |
+
if command -v google-java-format &> /dev/null; then
|
| 177 |
+
google-java-format -i --replace $(find . -name "*.java") 2>/dev/null || true
|
| 178 |
+
log_success "Java formatted"
|
| 179 |
+
fi
|
| 180 |
+
fi
|
| 181 |
+
|
| 182 |
+
# Traditional formatting
|
| 183 |
+
if command -v astyle &> /dev/null; then
|
| 184 |
+
astyle --style=google --recursive "*.java" 2>/dev/null || true
|
| 185 |
+
log_success "Java formatted with Astyle"
|
| 186 |
+
fi
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
# ============================================================================
|
| 190 |
+
# Section 6: Fix YAML/JSON
|
| 191 |
+
# ============================================================================
|
| 192 |
+
fix_config_files() {
|
| 193 |
+
log_info "Scanning and fixing configuration files..."
|
| 194 |
+
|
| 195 |
+
# Install YAML tools
|
| 196 |
+
pip install pyyaml 2>/dev/null || true
|
| 197 |
+
|
| 198 |
+
# Fix YAML
|
| 199 |
+
find . -name "*.yaml" -o -name "*.yml" | while read -r file; do
|
| 200 |
+
if command -v python3 &> /dev/null; then
|
| 201 |
+
python3 -c "
|
| 202 |
+
import yaml
|
| 203 |
+
import sys
|
| 204 |
+
try:
|
| 205 |
+
with open('$file', 'r') as f:
|
| 206 |
+
content = yaml.safe_load(f)
|
| 207 |
+
with open('$file', 'w') as f:
|
| 208 |
+
yaml.dump(content, f, default_flow_style=False, allow_unicode=True)
|
| 209 |
+
print('Fixed: $file')
|
| 210 |
+
except Exception as e:
|
| 211 |
+
pass
|
| 212 |
+
" 2>/dev/null || true
|
| 213 |
+
fi
|
| 214 |
+
done
|
| 215 |
+
|
| 216 |
+
# Format JSON
|
| 217 |
+
find . -name "*.json" | while read -r file; do
|
| 218 |
+
if command -v python3 &> /dev/null; then
|
| 219 |
+
python3 -c "
|
| 220 |
+
import json
|
| 221 |
+
import sys
|
| 222 |
+
try:
|
| 223 |
+
with open('$file', 'r') as f:
|
| 224 |
+
content = json.load(f)
|
| 225 |
+
with open('$file', 'w') as f:
|
| 226 |
+
json.dump(content, f, indent=2, ensure_ascii=False)
|
| 227 |
+
print('Fixed: $file')
|
| 228 |
+
except Exception as e:
|
| 229 |
+
pass
|
| 230 |
+
" 2>/dev/null || true
|
| 231 |
+
fi
|
| 232 |
+
done
|
| 233 |
+
|
| 234 |
+
log_success "Configuration files fixed"
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
# ============================================================================
|
| 238 |
+
# Section 7: Add License Headers
|
| 239 |
+
# ============================================================================
|
| 240 |
+
add_license_headers() {
|
| 241 |
+
log_info "Scanning license headers..."
|
| 242 |
+
|
| 243 |
+
# List of files that need headers
|
| 244 |
+
if [ -f "COPYRIGHT_HEADER.txt" ]; then
|
| 245 |
+
local header=$(cat COPYRIGHT_HEADER.txt)
|
| 246 |
+
|
| 247 |
+
for ext in "*.py" "*.js" "*.ts" "*.java" "*.go"; do
|
| 248 |
+
find . -name "$ext" -type f | while read -r file; do
|
| 249 |
+
# Check for existing header
|
| 250 |
+
if ! head -5 "$file" | grep -q "Copyright"; then
|
| 251 |
+
# Add header
|
| 252 |
+
if [ "$ext" == "*.py" ]; then
|
| 253 |
+
echo "# $header" | cat - "$file" > temp && mv temp "$file"
|
| 254 |
+
elif [ "$ext" == "*.js" ] || [ "$ext" == "*.ts" ]; then
|
| 255 |
+
echo "// $header" | cat - "$file" > temp && mv temp "$file"
|
| 256 |
+
elif [ "$ext" == "*.java" ]; then
|
| 257 |
+
echo "/* $header */" | cat - "$file" > temp && mv temp "$file"
|
| 258 |
+
elif [ "$ext" == "*.go" ]; then
|
| 259 |
+
echo "// $header" | cat - "$file" > temp && mv temp "$file"
|
| 260 |
+
fi
|
| 261 |
+
log_success "License header added: $file"
|
| 262 |
+
fi
|
| 263 |
+
done
|
| 264 |
+
done
|
| 265 |
+
fi
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
# ============================================================================
|
| 269 |
+
# Section 8: Organize Files
|
| 270 |
+
# ============================================================================
|
| 271 |
+
organize_files() {
|
| 272 |
+
log_info "Improving file organization..."
|
| 273 |
+
|
| 274 |
+
# Reorder Python imports
|
| 275 |
+
if [ -f "setup.cfg" ] || [ -f "pyproject.toml" ]; then
|
| 276 |
+
isort --recursive . 2>/dev/null || true
|
| 277 |
+
log_success "Imports reordered"
|
| 278 |
+
fi
|
| 279 |
+
|
| 280 |
+
# Update README.md
|
| 281 |
+
if [ -f "README.md" ]; then
|
| 282 |
+
# Ensure table of contents exists
|
| 283 |
+
if ! grep -q "^## Table of Contents$" README.md && ! grep -q "^## الفهرس$" README.md; then
|
| 284 |
+
echo -e "\n## Table of Contents\n" | cat - README.md > temp && mv temp README.md
|
| 285 |
+
log_success "README.md updated"
|
| 286 |
+
fi
|
| 287 |
+
fi
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
# ============================================================================
|
| 291 |
+
# Section 9: Basic Security Check
|
| 292 |
+
# ============================================================================
|
| 293 |
+
security_check() {
|
| 294 |
+
log_info "Running basic security check..."
|
| 295 |
+
|
| 296 |
+
# Check for passwords or keys in code
|
| 297 |
+
local secrets_patterns=(
|
| 298 |
+
"password\s*=\s*['\"][^'\"]+['\"]"
|
| 299 |
+
"api_key\s*=\s*['\"][^'\"]+['\"]"
|
| 300 |
+
"secret\s*=\s*['\"][^'\"]+['\"]"
|
| 301 |
+
"private_key\s*=\s*['\"][^'\"]+['\"]"
|
| 302 |
+
"AWS_ACCESS_KEY"
|
| 303 |
+
"AWS_SECRET_KEY"
|
| 304 |
+
)
|
| 305 |
+
|
| 306 |
+
for pattern in "${secrets_patterns[@]}"; do
|
| 307 |
+
if grep -rqE "$pattern" . --include="*.py" --include="*.js" --include="*.ts" 2>/dev/null; then
|
| 308 |
+
log_warning "Potential sensitive data found: $pattern"
|
| 309 |
+
fi
|
| 310 |
+
done
|
| 311 |
+
|
| 312 |
+
log_success "Security check completed"
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
# ============================================================================
|
| 316 |
+
# Main Function
|
| 317 |
+
# ============================================================================
|
| 318 |
+
main() {
|
| 319 |
+
echo "=============================================="
|
| 320 |
+
echo " Auto-Guardian: Auto-Fix Script"
|
| 321 |
+
echo "=============================================="
|
| 322 |
+
echo ""
|
| 323 |
+
|
| 324 |
+
cd "$PROJECT_ROOT"
|
| 325 |
+
|
| 326 |
+
# Log start
|
| 327 |
+
echo "Date: $(date)"
|
| 328 |
+
echo "Directory: $PROJECT_ROOT"
|
| 329 |
+
echo ""
|
| 330 |
+
|
| 331 |
+
# Execute all fix tasks
|
| 332 |
+
clean_general
|
| 333 |
+
fix_javascript
|
| 334 |
+
fix_python
|
| 335 |
+
fix_go
|
| 336 |
+
fix_java
|
| 337 |
+
fix_config_files
|
| 338 |
+
add_license_headers
|
| 339 |
+
organize_files
|
| 340 |
+
security_check
|
| 341 |
+
|
| 342 |
+
# Print summary
|
| 343 |
+
echo ""
|
| 344 |
+
echo "=============================================="
|
| 345 |
+
echo " Fix Summary"
|
| 346 |
+
echo "=============================================="
|
| 347 |
+
echo -e " Fixed: ${GREEN}$FIXED_COUNT${NC}"
|
| 348 |
+
echo -e " Skipped: ${YELLOW}$SKIPPED_COUNT${NC}"
|
| 349 |
+
echo -e " Errors: ${RED}$ERROR_COUNT${NC}"
|
| 350 |
+
echo ""
|
| 351 |
+
|
| 352 |
+
if [ $ERROR_COUNT -gt 0 ]; then
|
| 353 |
+
echo "Warning: Some errors occurred during fixing"
|
| 354 |
+
exit 1
|
| 355 |
+
else
|
| 356 |
+
echo "All fixes completed successfully"
|
| 357 |
+
exit 0
|
| 358 |
+
fi
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
# Run main function
|
| 362 |
+
main "$@"
|
core_system/code-analyzer.py
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Auto-Guardian: Smart Code Analyzer
|
| 4 |
+
===================================
|
| 5 |
+
This script analyzes code to detect various issues
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import json
|
| 9 |
+
import os
|
| 10 |
+
import re
|
| 11 |
+
import subprocess
|
| 12 |
+
import sys
|
| 13 |
+
from dataclasses import dataclass, field
|
| 14 |
+
from datetime import datetime
|
| 15 |
+
from enum import Enum
|
| 16 |
+
from pathlib import Path
|
| 17 |
+
from typing import Optional
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class Severity(Enum):
|
| 21 |
+
"""Issue severity levels"""
|
| 22 |
+
CRITICAL = "critical"
|
| 23 |
+
HIGH = "high"
|
| 24 |
+
MEDIUM = "medium"
|
| 25 |
+
LOW = "low"
|
| 26 |
+
INFO = "info"
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class IssueType(Enum):
|
| 30 |
+
"""Types of issues"""
|
| 31 |
+
SYNTAX_ERROR = "syntax_error"
|
| 32 |
+
LINTING_ERROR = "linting_error"
|
| 33 |
+
SECURITY_VULNERABILITY = "security_vulnerability"
|
| 34 |
+
CODE_SMELL = "code_smell"
|
| 35 |
+
DEPRECATED_USAGE = "deprecated_usage"
|
| 36 |
+
PERFORMANCE_ISSUE = "performance_issue"
|
| 37 |
+
STYLE_VIOLATION = "style_violation"
|
| 38 |
+
TYPE_ERROR = "type_error"
|
| 39 |
+
UNUSED_CODE = "unused_code"
|
| 40 |
+
IMPORT_ERROR = "import_error"
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
@dataclass
|
| 44 |
+
class CodeIssue:
|
| 45 |
+
"""Representation of a code issue"""
|
| 46 |
+
file: str
|
| 47 |
+
line: int
|
| 48 |
+
column: int
|
| 49 |
+
severity: Severity
|
| 50 |
+
issue_type: IssueType
|
| 51 |
+
message: str
|
| 52 |
+
rule_id: Optional[str] = None
|
| 53 |
+
suggestion: Optional[str] = None
|
| 54 |
+
fixable: bool = False
|
| 55 |
+
|
| 56 |
+
def to_dict(self) -> dict:
|
| 57 |
+
"""Convert issue to dictionary"""
|
| 58 |
+
return {
|
| 59 |
+
"file": self.file,
|
| 60 |
+
"line": self.line,
|
| 61 |
+
"column": self.column,
|
| 62 |
+
"severity": self.severity.value,
|
| 63 |
+
"type": self.issue_type.value,
|
| 64 |
+
"message": self.message,
|
| 65 |
+
"rule_id": self.rule_id,
|
| 66 |
+
"suggestion": self.suggestion,
|
| 67 |
+
"fixable": self.fixable
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
@dataclass
|
| 72 |
+
class ScanResult:
|
| 73 |
+
"""Complete scan result"""
|
| 74 |
+
timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
|
| 75 |
+
files_scanned: int = 0
|
| 76 |
+
issues_found: int = 0
|
| 77 |
+
issues_by_severity: dict = field(default_factory=dict)
|
| 78 |
+
issues_by_type: dict = field(default_factory=dict)
|
| 79 |
+
critical_issues: list = field(default_factory=list)
|
| 80 |
+
auto_fixable_issues: list = field(default_factory=list)
|
| 81 |
+
issues: list = field(default_factory=list)
|
| 82 |
+
|
| 83 |
+
def to_dict(self) -> dict:
|
| 84 |
+
"""Convert result to dictionary"""
|
| 85 |
+
return {
|
| 86 |
+
"timestamp": self.timestamp,
|
| 87 |
+
"summary": {
|
| 88 |
+
"files_scanned": self.files_scanned,
|
| 89 |
+
"total_issues": self.issues_found,
|
| 90 |
+
"by_severity": self.issues_by_severity,
|
| 91 |
+
"by_type": self.issues_by_type,
|
| 92 |
+
"critical_count": len(self.critical_issues),
|
| 93 |
+
"auto_fixable_count": len(self.auto_fixable_issues)
|
| 94 |
+
},
|
| 95 |
+
"critical_issues": [i.to_dict() for i in self.critical_issues],
|
| 96 |
+
"auto_fixable_issues": [i.to_dict() for i in self.auto_fixable_issues],
|
| 97 |
+
"all_issues": [i.to_dict() for i in self.issues]
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
class CodeAnalyzer:
|
| 102 |
+
"""Main code analyzer"""
|
| 103 |
+
|
| 104 |
+
def __init__(self, project_root: str = None):
|
| 105 |
+
self.project_root = Path(project_root) if project_root else Path.cwd()
|
| 106 |
+
self.issues: list[CodeIssue] = []
|
| 107 |
+
self.result = ScanResult()
|
| 108 |
+
|
| 109 |
+
def scan_python(self) -> list[CodeIssue]:
|
| 110 |
+
"""Scan Python files"""
|
| 111 |
+
issues = []
|
| 112 |
+
|
| 113 |
+
# Find Python files
|
| 114 |
+
py_files = list(self.project_root.rglob("*.py"))
|
| 115 |
+
self.result.files_scanned += len(py_files)
|
| 116 |
+
|
| 117 |
+
for py_file in py_files:
|
| 118 |
+
try:
|
| 119 |
+
content = py_file.read_text(encoding='utf-8')
|
| 120 |
+
lines = content.split('\n')
|
| 121 |
+
|
| 122 |
+
for line_num, line in enumerate(lines, 1):
|
| 123 |
+
# Check common formatting errors
|
| 124 |
+
if re.search(r'print\s*\([^)]*\)', line):
|
| 125 |
+
issues.append(CodeIssue(
|
| 126 |
+
file=str(py_file),
|
| 127 |
+
line=line_num,
|
| 128 |
+
column=line.find('print'),
|
| 129 |
+
severity=Severity.LOW,
|
| 130 |
+
issue_type=IssueType.CODE_SMELL,
|
| 131 |
+
message="print() usage for debugging",
|
| 132 |
+
suggestion="Use logger instead of print",
|
| 133 |
+
fixable=True
|
| 134 |
+
))
|
| 135 |
+
|
| 136 |
+
# Check unused variables
|
| 137 |
+
if re.match(r'^\s*_+\w*$', line.strip()):
|
| 138 |
+
issues.append(CodeIssue(
|
| 139 |
+
file=str(py_file),
|
| 140 |
+
line=line_num,
|
| 141 |
+
column=0,
|
| 142 |
+
severity=Severity.INFO,
|
| 143 |
+
issue_type=IssueType.UNUSED_CODE,
|
| 144 |
+
message="Unused variable",
|
| 145 |
+
fixable=True
|
| 146 |
+
))
|
| 147 |
+
|
| 148 |
+
# Check syntax errors
|
| 149 |
+
try:
|
| 150 |
+
import ast
|
| 151 |
+
ast.parse(content)
|
| 152 |
+
except SyntaxError as e:
|
| 153 |
+
issues.append(CodeIssue(
|
| 154 |
+
file=str(py_file),
|
| 155 |
+
line=e.lineno or 1,
|
| 156 |
+
column=e.offset or 0,
|
| 157 |
+
severity=Severity.CRITICAL,
|
| 158 |
+
issue_type=IssueType.SYNTAX_ERROR,
|
| 159 |
+
message=f"Syntax error: {e.msg}",
|
| 160 |
+
suggestion="Review syntax on this line",
|
| 161 |
+
fixable=False
|
| 162 |
+
))
|
| 163 |
+
|
| 164 |
+
# Check security vulnerabilities
|
| 165 |
+
security_patterns = [
|
| 166 |
+
(r"os\.environ\[['\"]\w+['\"]\]", "Direct environment variable access", Severity.HIGH, True),
|
| 167 |
+
(r"eval\s*\(", "Unsafe eval() usage", Severity.CRITICAL, False),
|
| 168 |
+
(r"exec\s*\(", "Unsafe exec() usage", Severity.CRITICAL, False),
|
| 169 |
+
(r"pickle\.load", "pickle.load may be unsafe", Severity.MEDIUM, True),
|
| 170 |
+
(r"yaml\.load", "yaml.load without SafeLoader", Severity.HIGH, True),
|
| 171 |
+
(r"password\s*=", "Password in code", Severity.HIGH, False),
|
| 172 |
+
(r"secret\s*=", "Secret key in code", Severity.HIGH, False),
|
| 173 |
+
(r"api[_-]?key\s*=", "API key in code", Severity.HIGH, False),
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
for pattern, desc, severity, fixable in security_patterns:
|
| 177 |
+
if re.search(pattern, content):
|
| 178 |
+
line_num = self._find_line_with_pattern(lines, pattern)
|
| 179 |
+
issues.append(CodeIssue(
|
| 180 |
+
file=str(py_file),
|
| 181 |
+
line=line_num,
|
| 182 |
+
column=0,
|
| 183 |
+
severity=severity,
|
| 184 |
+
issue_type=IssueType.SECURITY_VULNERABILITY,
|
| 185 |
+
message=f"Security: {desc}",
|
| 186 |
+
suggestion="Move to .env file",
|
| 187 |
+
fixable=fixable
|
| 188 |
+
))
|
| 189 |
+
|
| 190 |
+
except Exception as e:
|
| 191 |
+
print(f"Error reading {py_file}: {e}")
|
| 192 |
+
|
| 193 |
+
return issues
|
| 194 |
+
|
| 195 |
+
def scan_javascript(self) -> list[CodeIssue]:
|
| 196 |
+
"""Scan JavaScript files"""
|
| 197 |
+
issues = []
|
| 198 |
+
js_files = list(self.project_root.rglob("*.js")) + list(self.project_root.rglob("*.ts"))
|
| 199 |
+
|
| 200 |
+
for js_file in js_files:
|
| 201 |
+
try:
|
| 202 |
+
content = js_file.read_text(encoding='utf-8')
|
| 203 |
+
lines = content.split('\n')
|
| 204 |
+
|
| 205 |
+
# Check == instead of ===
|
| 206 |
+
for line_num, line in enumerate(lines, 1):
|
| 207 |
+
if re.search(r'[^=!]==[^=]', line):
|
| 208 |
+
issues.append(CodeIssue(
|
| 209 |
+
file=str(js_file),
|
| 210 |
+
line=line_num,
|
| 211 |
+
column=line.find('=='),
|
| 212 |
+
severity=Severity.MEDIUM,
|
| 213 |
+
issue_type=IssueType.CODE_SMELL,
|
| 214 |
+
message="Use === instead of ==",
|
| 215 |
+
suggestion="Use === for strict comparison",
|
| 216 |
+
fixable=True
|
| 217 |
+
))
|
| 218 |
+
|
| 219 |
+
# Check var instead of let/const
|
| 220 |
+
if re.search(r'\bvar\s+\w+', line):
|
| 221 |
+
issues.append(CodeIssue(
|
| 222 |
+
file=str(js_file),
|
| 223 |
+
line=line_num,
|
| 224 |
+
column=line.find('var'),
|
| 225 |
+
severity=Severity.LOW,
|
| 226 |
+
issue_type=IssueType.DEPRECATED_USAGE,
|
| 227 |
+
message="Use let/const instead of var",
|
| 228 |
+
suggestion="Use let or const",
|
| 229 |
+
fixable=True
|
| 230 |
+
))
|
| 231 |
+
|
| 232 |
+
# Check console.log
|
| 233 |
+
if re.search(r'console\.(log|debug|info)', line):
|
| 234 |
+
issues.append(CodeIssue(
|
| 235 |
+
file=str(js_file),
|
| 236 |
+
line=line_num,
|
| 237 |
+
column=line.find('console'),
|
| 238 |
+
severity=Severity.INFO,
|
| 239 |
+
issue_type=IssueType.CODE_SMELL,
|
| 240 |
+
message="Remaining console.log statement",
|
| 241 |
+
suggestion="Remove or use logger",
|
| 242 |
+
fixable=True
|
| 243 |
+
))
|
| 244 |
+
|
| 245 |
+
except Exception as e:
|
| 246 |
+
print(f"Error reading {js_file}: {e}")
|
| 247 |
+
|
| 248 |
+
return issues
|
| 249 |
+
|
| 250 |
+
def _find_line_with_pattern(self, lines: list[str], pattern: str) -> int:
|
| 251 |
+
"""Find line containing pattern"""
|
| 252 |
+
for line_num, line in enumerate(lines, 1):
|
| 253 |
+
if re.search(pattern, line):
|
| 254 |
+
return line_num
|
| 255 |
+
return 1
|
| 256 |
+
|
| 257 |
+
def run_linters(self) -> list[CodeIssue]:
|
| 258 |
+
"""Run external linting tools"""
|
| 259 |
+
issues = []
|
| 260 |
+
|
| 261 |
+
# Run Flake8 for Python
|
| 262 |
+
try:
|
| 263 |
+
result = subprocess.run(
|
| 264 |
+
['flake8', '.', '--format=json', '--max-line-length=100'],
|
| 265 |
+
capture_output=True,
|
| 266 |
+
text=True,
|
| 267 |
+
cwd=self.project_root
|
| 268 |
+
)
|
| 269 |
+
if result.returncode != 0:
|
| 270 |
+
data = json.loads(result.stdout) if result.stdout else []
|
| 271 |
+
for item in data:
|
| 272 |
+
issues.append(CodeIssue(
|
| 273 |
+
file=item['filename'],
|
| 274 |
+
line=item['line_number'],
|
| 275 |
+
column=item['column_number'],
|
| 276 |
+
severity=self._map_flake8_severity(item['type']),
|
| 277 |
+
issue_type=IssueType.LINTING_ERROR,
|
| 278 |
+
message=item['text'],
|
| 279 |
+
rule_id=item['id'],
|
| 280 |
+
fixable=True
|
| 281 |
+
))
|
| 282 |
+
except Exception as e:
|
| 283 |
+
print(f"Flake8 not available: {e}")
|
| 284 |
+
|
| 285 |
+
# Run ESLint if available
|
| 286 |
+
try:
|
| 287 |
+
result = subprocess.run(
|
| 288 |
+
['npx', 'eslint', '.', '--format=json'],
|
| 289 |
+
capture_output=True,
|
| 290 |
+
text=True,
|
| 291 |
+
cwd=self.project_root,
|
| 292 |
+
timeout=60
|
| 293 |
+
)
|
| 294 |
+
if result.returncode != 0:
|
| 295 |
+
data = json.loads(result.stdout) if result.stdout else []
|
| 296 |
+
for item in data:
|
| 297 |
+
for msg in item.get('messages', []):
|
| 298 |
+
issues.append(CodeIssue(
|
| 299 |
+
file=item['filePath'],
|
| 300 |
+
line=msg['line'],
|
| 301 |
+
column=msg['column'],
|
| 302 |
+
severity=self._map_eslint_severity(msg['severity']),
|
| 303 |
+
issue_type=IssueType.LINTING_ERROR,
|
| 304 |
+
message=msg['message'],
|
| 305 |
+
rule_id=msg['ruleId'],
|
| 306 |
+
fixable=msg.get('fix') is not None
|
| 307 |
+
))
|
| 308 |
+
except Exception as e:
|
| 309 |
+
print(f"ESLint not available: {e}")
|
| 310 |
+
|
| 311 |
+
return issues
|
| 312 |
+
|
| 313 |
+
def _map_flake8_severity(self, code: str) -> Severity:
|
| 314 |
+
"""Map severity from Flake8 code"""
|
| 315 |
+
prefix = code[0] if code else 'W'
|
| 316 |
+
if prefix == 'E':
|
| 317 |
+
return Severity.HIGH
|
| 318 |
+
elif prefix == 'F':
|
| 319 |
+
return Severity.CRITICAL
|
| 320 |
+
elif prefix == 'W':
|
| 321 |
+
return Severity.LOW
|
| 322 |
+
return Severity.MEDIUM
|
| 323 |
+
|
| 324 |
+
def _map_eslint_severity(self, severity: int) -> Severity:
|
| 325 |
+
"""Map severity from ESLint"""
|
| 326 |
+
if severity == 2:
|
| 327 |
+
return Severity.HIGH
|
| 328 |
+
elif severity == 1:
|
| 329 |
+
return Severity.MEDIUM
|
| 330 |
+
return Severity.LOW
|
| 331 |
+
|
| 332 |
+
def analyze(self) -> ScanResult:
|
| 333 |
+
"""Run complete analysis"""
|
| 334 |
+
print("Starting code analysis...")
|
| 335 |
+
|
| 336 |
+
# Collect issues from all sources
|
| 337 |
+
python_issues = self.scan_python()
|
| 338 |
+
js_issues = self.scan_javascript()
|
| 339 |
+
linter_issues = self.run_linters()
|
| 340 |
+
|
| 341 |
+
self.issues = python_issues + js_issues + linter_issues
|
| 342 |
+
self.result.issues = self.issues
|
| 343 |
+
self.result.issues_found = len(self.issues)
|
| 344 |
+
|
| 345 |
+
# Categorize issues
|
| 346 |
+
for issue in self.issues:
|
| 347 |
+
# By severity
|
| 348 |
+
severity_key = issue.severity.value
|
| 349 |
+
self.result.issues_by_severity[severity_key] = \
|
| 350 |
+
self.result.issues_by_severity.get(severity_key, 0) + 1
|
| 351 |
+
|
| 352 |
+
# By type
|
| 353 |
+
type_key = issue.issue_type.value
|
| 354 |
+
self.result.issues_by_type[type_key] = \
|
| 355 |
+
self.result.issues_by_type.get(type_key, 0) + 1
|
| 356 |
+
|
| 357 |
+
# Critical issues
|
| 358 |
+
if issue.severity == Severity.CRITICAL:
|
| 359 |
+
self.result.critical_issues.append(issue)
|
| 360 |
+
|
| 361 |
+
# Auto-fixable issues
|
| 362 |
+
if issue.fixable:
|
| 363 |
+
self.result.auto_fixable_issues.append(issue)
|
| 364 |
+
|
| 365 |
+
# Print summary
|
| 366 |
+
print(f" Files scanned: {self.result.files_scanned}")
|
| 367 |
+
print(f" Issues found: {self.result.issues_found}")
|
| 368 |
+
print(f" Critical issues: {len(self.result.critical_issues)}")
|
| 369 |
+
print(f" Auto-fixable issues: {len(self.result.auto_fixable_issues)}")
|
| 370 |
+
|
| 371 |
+
return self.result
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
def main():
|
| 375 |
+
"""Main function"""
|
| 376 |
+
import argparse
|
| 377 |
+
|
| 378 |
+
parser = argparse.ArgumentParser(description='Auto-Guardian Code Analyzer')
|
| 379 |
+
parser.add_argument('--output', '-o', help='Output file', default='scan-results.json')
|
| 380 |
+
parser.add_argument('--format', '-f', choices=['json', 'sarif'], default='json',
|
| 381 |
+
help='Output format')
|
| 382 |
+
parser.add_argument('--project-root', '-p', help='Project directory')
|
| 383 |
+
|
| 384 |
+
args = parser.parse_args()
|
| 385 |
+
|
| 386 |
+
# Create analyzer and run it
|
| 387 |
+
analyzer = CodeAnalyzer(args.project_root)
|
| 388 |
+
result = analyzer.analyze()
|
| 389 |
+
|
| 390 |
+
# Save results
|
| 391 |
+
output_path = Path(args.output)
|
| 392 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 393 |
+
|
| 394 |
+
if args.format == 'json':
|
| 395 |
+
with open(output_path, 'w', encoding='utf-8') as f:
|
| 396 |
+
json.dump(result.to_dict(), f, indent=2, ensure_ascii=False)
|
| 397 |
+
print(f" Results saved to {output_path}")
|
| 398 |
+
|
| 399 |
+
# Save critical issues file
|
| 400 |
+
if result.critical_issues:
|
| 401 |
+
critical_path = Path("critical-issues.json")
|
| 402 |
+
with open(critical_path, 'w', encoding='utf-8') as f:
|
| 403 |
+
json.dump([i.to_dict() for i in result.critical_issues], f, indent=2, ensure_ascii=False)
|
| 404 |
+
print(f" Critical issues saved to {critical_path}")
|
| 405 |
+
|
| 406 |
+
# Return exit code based on critical issues
|
| 407 |
+
sys.exit(1 if len(result.critical_issues) > 0 else 0)
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
if __name__ == '__main__':
|
| 411 |
+
main()
|
core_system/pyproject.toml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[tool.black]
|
| 2 |
+
line-length = 100
|
| 3 |
+
target-version = ['py39', 'py310', 'py311']
|
| 4 |
+
include = '\.pyi?$'
|
| 5 |
+
extend-exclude = '''
|
| 6 |
+
/(
|
| 7 |
+
\.eggs
|
| 8 |
+
| \.git
|
| 9 |
+
| \.hg
|
| 10 |
+
| \.mypy_cache
|
| 11 |
+
| \.tox
|
| 12 |
+
| \.venv
|
| 13 |
+
| _build
|
| 14 |
+
| buck-out
|
| 15 |
+
| build
|
| 16 |
+
| dist
|
| 17 |
+
)/
|
| 18 |
+
'''
|
| 19 |
+
|
| 20 |
+
[tool.isort]
|
| 21 |
+
profile = "black"
|
| 22 |
+
line_length = 100
|
| 23 |
+
skip = [".venv", "venv", "node_modules"]
|
| 24 |
+
known_first_party = ["app", "src"]
|
| 25 |
+
|
| 26 |
+
[tool.pytest.ini_options]
|
| 27 |
+
testpaths = ["tests"]
|
| 28 |
+
python_files = ["test_*.py"]
|
| 29 |
+
python_functions = ["test_*"]
|
| 30 |
+
addopts = "-v --tb=short"
|
| 31 |
+
|
| 32 |
+
[tool.mypy]
|
| 33 |
+
python_version = "3.11"
|
| 34 |
+
warn_return_any = true
|
| 35 |
+
warn_unused_configs = true
|
| 36 |
+
ignore_missing_imports = true
|
core_system/report-generator.py
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Auto-Guardian: Report Generator
|
| 4 |
+
================================
|
| 5 |
+
Generate detailed reports about code quality and send appropriate notifications
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import json
|
| 9 |
+
import sys
|
| 10 |
+
from dataclasses import dataclass, field
|
| 11 |
+
from datetime import datetime
|
| 12 |
+
from enum import Enum
|
| 13 |
+
from pathlib import Path
|
| 14 |
+
from typing import Optional
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class ReportType(Enum):
|
| 18 |
+
"""Types of reports"""
|
| 19 |
+
PULL_REQUEST = "pull_request"
|
| 20 |
+
DAILY_SUMMARY = "daily_summary"
|
| 21 |
+
SECURITY_ALERT = "security_alert"
|
| 22 |
+
QUALITY_REPORT = "quality_report"
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@dataclass
|
| 26 |
+
class ReportConfig:
|
| 27 |
+
"""Report configuration"""
|
| 28 |
+
scan_results_file: str
|
| 29 |
+
pr_number: Optional[int] = None
|
| 30 |
+
report_type: ReportType = ReportType.PULL_REQUEST
|
| 31 |
+
include_details: bool = True
|
| 32 |
+
include_suggestions: bool = True
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class ReportGenerator:
|
| 36 |
+
"""Report generator"""
|
| 37 |
+
|
| 38 |
+
def __init__(self, config: ReportConfig):
|
| 39 |
+
self.config = config
|
| 40 |
+
self.results = self._load_results()
|
| 41 |
+
|
| 42 |
+
def _load_results(self) -> dict:
|
| 43 |
+
"""Load scan results"""
|
| 44 |
+
with open(self.config.scan_results_file, 'r', encoding='utf-8') as f:
|
| 45 |
+
return json.load(f)
|
| 46 |
+
|
| 47 |
+
def generate_pull_request_comment(self) -> str:
|
| 48 |
+
"""Generate comment for Pull Request"""
|
| 49 |
+
summary = self.results.get('summary', {})
|
| 50 |
+
critical_issues = self.results.get('critical_issues', [])
|
| 51 |
+
auto_fixable = self.results.get('auto_fixable_issues', [])
|
| 52 |
+
all_issues = self.results.get('all_issues', [])
|
| 53 |
+
|
| 54 |
+
# Severity emojis
|
| 55 |
+
severity_emojis = {
|
| 56 |
+
'critical': 'Critical',
|
| 57 |
+
'high': 'High',
|
| 58 |
+
'medium': 'Medium',
|
| 59 |
+
'low': 'Low',
|
| 60 |
+
'info': 'Info'
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
report = []
|
| 64 |
+
|
| 65 |
+
# Title
|
| 66 |
+
report.append("## Quality Scan Report - Auto-Guardian")
|
| 67 |
+
report.append("")
|
| 68 |
+
report.append(f"**Scan Date:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
| 69 |
+
report.append(f"**Files Scanned:** {summary.get('files_scanned', 0)}")
|
| 70 |
+
report.append(f"**Total Issues:** {summary.get('total_issues', 0)}")
|
| 71 |
+
report.append("")
|
| 72 |
+
|
| 73 |
+
# Summary by severity
|
| 74 |
+
report.append("### Issues Summary")
|
| 75 |
+
report.append("")
|
| 76 |
+
report.append("| Severity | Count |")
|
| 77 |
+
report.append("|----------|-------|")
|
| 78 |
+
for severity, count in summary.get('by_severity', {}).items():
|
| 79 |
+
emoji = severity_emojis.get(severity, 'Info')
|
| 80 |
+
report.append(f"| {emoji} | {count} |")
|
| 81 |
+
report.append("")
|
| 82 |
+
|
| 83 |
+
# Auto-fix status
|
| 84 |
+
if auto_fixable:
|
| 85 |
+
report.append("### Auto-Fixes Applied")
|
| 86 |
+
report.append("")
|
| 87 |
+
report.append(f"**{len(auto_fixable)}** issues were fixed automatically:")
|
| 88 |
+
report.append("")
|
| 89 |
+
|
| 90 |
+
for issue in auto_fixable[:10]: # Show first 10 only
|
| 91 |
+
file_path = Path(issue['file']).name
|
| 92 |
+
report.append(f"- Fixed `{file_path}`:{issue['line']} - {issue['message']}")
|
| 93 |
+
|
| 94 |
+
if len(auto_fixable) > 10:
|
| 95 |
+
report.append(f"- ... and **{len(auto_fixable) - 10}** more fixes")
|
| 96 |
+
report.append("")
|
| 97 |
+
|
| 98 |
+
# Issues requiring human intervention
|
| 99 |
+
if critical_issues:
|
| 100 |
+
report.append("### Issues Requiring Human Intervention")
|
| 101 |
+
report.append("")
|
| 102 |
+
report.append("**This code cannot be merged until these issues are resolved:**")
|
| 103 |
+
report.append("")
|
| 104 |
+
|
| 105 |
+
for issue in critical_issues:
|
| 106 |
+
file_path = Path(issue['file']).name
|
| 107 |
+
emoji = severity_emojis.get(issue['severity'], 'Critical')
|
| 108 |
+
report.append(f"- **{emoji} {issue['file']}:{issue['line']}**")
|
| 109 |
+
report.append(f" - Issue: {issue['message']}")
|
| 110 |
+
if issue.get('suggestion'):
|
| 111 |
+
report.append(f" - Suggestion: {issue['suggestion']}")
|
| 112 |
+
report.append("")
|
| 113 |
+
|
| 114 |
+
report.append("---")
|
| 115 |
+
report.append("### Merge Status: Blocked")
|
| 116 |
+
report.append("")
|
| 117 |
+
report.append("**This Pull Request is blocked from merging due to critical issues.**")
|
| 118 |
+
report.append("")
|
| 119 |
+
report.append("Please resolve the issues above and try again.")
|
| 120 |
+
else:
|
| 121 |
+
# No critical issues
|
| 122 |
+
report.append("---")
|
| 123 |
+
report.append("### Merge Status: Approved")
|
| 124 |
+
report.append("")
|
| 125 |
+
report.append("**This code passed all quality checks!**")
|
| 126 |
+
report.append("")
|
| 127 |
+
report.append("You can proceed with merging this Pull Request.")
|
| 128 |
+
|
| 129 |
+
# Footer
|
| 130 |
+
report.append("")
|
| 131 |
+
report.append("---")
|
| 132 |
+
report.append("*Report generated automatically by Auto-Guardian Bot*")
|
| 133 |
+
|
| 134 |
+
return '\n'.join(report)
|
| 135 |
+
|
| 136 |
+
def generate_daily_summary(self) -> dict:
|
| 137 |
+
"""Generate daily summary"""
|
| 138 |
+
summary = self.results.get('summary', {})
|
| 139 |
+
|
| 140 |
+
return {
|
| 141 |
+
"date": datetime.now().isoformat(),
|
| 142 |
+
"total_issues": summary.get('total_issues', 0),
|
| 143 |
+
"critical_issues": summary.get('critical_count', 0),
|
| 144 |
+
"auto_fixed": summary.get('auto_fixable_count', 0),
|
| 145 |
+
"by_severity": summary.get('by_severity', {}),
|
| 146 |
+
"by_type": summary.get('by_type', {})
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
def generate_security_alert(self) -> str:
|
| 150 |
+
"""Generate security alert"""
|
| 151 |
+
critical = self.results.get('critical_issues', [])
|
| 152 |
+
security_issues = [i for i in critical if 'security' in i.get('type', '')]
|
| 153 |
+
|
| 154 |
+
if not security_issues:
|
| 155 |
+
return None
|
| 156 |
+
|
| 157 |
+
alert = []
|
| 158 |
+
alert.append("Security Alert - Auto-Guardian")
|
| 159 |
+
alert.append("")
|
| 160 |
+
alert.append("Security vulnerabilities detected in code:")
|
| 161 |
+
alert.append("")
|
| 162 |
+
|
| 163 |
+
for issue in security_issues:
|
| 164 |
+
alert.append(f"- {issue['file']}:{issue['line']}")
|
| 165 |
+
alert.append(f" {issue['message']}")
|
| 166 |
+
if issue.get('suggestion'):
|
| 167 |
+
alert.append(f" Suggestion: {issue['suggestion']}")
|
| 168 |
+
|
| 169 |
+
return '\n'.join(alert)
|
| 170 |
+
|
| 171 |
+
def save_report(self, content: str, filename: str = "report.md") -> Path:
|
| 172 |
+
"""Save report to file"""
|
| 173 |
+
output_path = Path(filename)
|
| 174 |
+
with open(output_path, 'w', encoding='utf-8') as f:
|
| 175 |
+
f.write(content)
|
| 176 |
+
return output_path
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def main():
|
| 180 |
+
"""Main function"""
|
| 181 |
+
import argparse
|
| 182 |
+
|
| 183 |
+
parser = argparse.ArgumentParser(description='Auto-Guardian Report Generator')
|
| 184 |
+
parser.add_argument('--scan-results', required=True, help='Scan results file')
|
| 185 |
+
parser.add_argument('--pr-number', type=int, help='Pull Request number')
|
| 186 |
+
parser.add_argument('--output', '-o', default="report.md", help='Output file')
|
| 187 |
+
parser.add_argument('--format', choices=['comment', 'summary', 'json'],
|
| 188 |
+
default='comment', help='Report format')
|
| 189 |
+
|
| 190 |
+
args = parser.parse_args()
|
| 191 |
+
|
| 192 |
+
config = ReportConfig(
|
| 193 |
+
scan_results_file=args.scan_results,
|
| 194 |
+
pr_number=args.pr_number,
|
| 195 |
+
report_type=ReportType.PULL_REQUEST
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
generator = ReportGenerator(config)
|
| 199 |
+
|
| 200 |
+
if args.format == 'comment':
|
| 201 |
+
report = generator.generate_pull_request_comment()
|
| 202 |
+
elif args.format == 'summary':
|
| 203 |
+
report = json.dumps(generator.generate_daily_summary(), indent=2)
|
| 204 |
+
else:
|
| 205 |
+
report = generator.generate_pull_request_comment()
|
| 206 |
+
|
| 207 |
+
# Print report
|
| 208 |
+
print(report)
|
| 209 |
+
|
| 210 |
+
# Save report
|
| 211 |
+
generator.save_report(report, args.output)
|
| 212 |
+
print(f"\nReport saved to {args.output}")
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
if __name__ == '__main__':
|
| 216 |
+
main()
|
core_system/requirements.txt
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Analysis and linting tools
|
| 2 |
+
flake8>=6.0.0
|
| 3 |
+
pylint>=2.17.0
|
| 4 |
+
mypy>=1.4.0
|
| 5 |
+
black>=23.0.0
|
| 6 |
+
isort>=5.12.0
|
| 7 |
+
autoflake>=2.0.0
|
| 8 |
+
|
| 9 |
+
# Security tools
|
| 10 |
+
bandit>=1.7.0
|
| 11 |
+
safety>=2.3.0
|
| 12 |
+
|
| 13 |
+
# Testing tools
|
| 14 |
+
pytest>=7.4.0
|
| 15 |
+
pytest-cov>=4.1.0
|
| 16 |
+
|
| 17 |
+
# Helper tools
|
| 18 |
+
pyyaml>=6.0
|
| 19 |
+
rich>=13.0.0
|