Spaces:
Sleeping
Sleeping
File size: 6,669 Bytes
c5292d8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | """Static code analysis checks."""
import re
from datetime import datetime
from pathlib import Path
from typing import Any
import git
import requests
from bs4 import BeautifulSoup
from shared.logger import setup_logger
logger = setup_logger(__name__)
class StaticChecker:
"""Perform static checks on repository."""
def __init__(self, repo_url: str, commit_sha: str, clone_dir: Path) -> None:
"""Initialize static checker.
Args:
repo_url: Repository URL
commit_sha: Commit SHA to check
clone_dir: Directory to clone repo
"""
self.repo_url = repo_url
self.commit_sha = commit_sha
self.clone_dir = clone_dir
self.repo = None
def clone_repo(self) -> None:
"""Clone repository and checkout specific commit."""
logger.info(f"Cloning {self.repo_url} to {self.clone_dir}")
# Clean up if exists
if self.clone_dir.exists():
import shutil
shutil.rmtree(self.clone_dir)
# Clone
self.repo = git.Repo.clone_from(self.repo_url, self.clone_dir)
# Checkout specific commit
self.repo.git.checkout(self.commit_sha)
logger.info(f"Checked out commit {self.commit_sha}")
def check_created_after_task(self, task_timestamp: datetime) -> dict[str, Any]:
"""Check if repo was created after task was sent.
Args:
task_timestamp: When task was sent
Returns:
Check result
"""
try:
# Get first commit timestamp
commits = list(self.repo.iter_commits())
if not commits:
return {
"passed": False,
"score": 0.0,
"reason": "No commits found",
}
first_commit = commits[-1]
first_commit_time = datetime.fromtimestamp(first_commit.committed_date)
if first_commit_time > task_timestamp:
return {
"passed": True,
"score": 1.0,
"reason": f"Repo created after task ({first_commit_time} > {task_timestamp})",
}
else:
return {
"passed": False,
"score": 0.0,
"reason": f"Repo existed before task ({first_commit_time} <= {task_timestamp})",
}
except Exception as e:
logger.error(f"Error checking repo creation time: {e}")
return {"passed": False, "score": 0.0, "reason": f"Error: {e}"}
def check_mit_license(self) -> dict[str, Any]:
"""Check if repo has MIT LICENSE in root.
Returns:
Check result
"""
try:
license_path = self.clone_dir / "LICENSE"
if not license_path.exists():
return {
"passed": False,
"score": 0.0,
"reason": "No LICENSE file found in root",
}
content = license_path.read_text()
if "MIT License" in content or "MIT" in content[:200]:
return {
"passed": True,
"score": 1.0,
"reason": "MIT LICENSE found",
}
else:
return {
"passed": False,
"score": 0.0,
"reason": "LICENSE file exists but is not MIT",
}
except Exception as e:
logger.error(f"Error checking LICENSE: {e}")
return {"passed": False, "score": 0.0, "reason": f"Error: {e}"}
def check_readme(self) -> dict[str, Any]:
"""Check README.md quality.
Returns:
Check result
"""
try:
readme_path = self.clone_dir / "README.md"
if not readme_path.exists():
return {
"passed": False,
"score": 0.0,
"reason": "No README.md found",
}
content = readme_path.read_text()
# Basic quality checks
has_title = bool(re.search(r"^#\s+.+", content, re.MULTILINE))
has_sections = content.count("#") >= 3
has_enough_content = len(content) >= 200
has_code_blocks = "```" in content
score = sum([has_title, has_sections, has_enough_content, has_code_blocks]) / 4
return {
"passed": score >= 0.75,
"score": score,
"reason": f"README quality: {score:.0%} (title={has_title}, "
f"sections={has_sections}, content={has_enough_content}, code={has_code_blocks})",
}
except Exception as e:
logger.error(f"Error checking README: {e}")
return {"passed": False, "score": 0.0, "reason": f"Error: {e}"}
def check_no_secrets(self) -> dict[str, Any]:
"""Check for common secret patterns in git history.
Returns:
Check result
"""
try:
# Check for common secret patterns
secret_patterns = [
r"sk-[a-zA-Z0-9]{32,}", # API keys
r"ghp_[a-zA-Z0-9]{36,}", # GitHub tokens
r"AKIA[0-9A-Z]{16}", # AWS keys
r"password\s*=\s*['\"][^'\"]{8,}", # Hardcoded passwords
]
found_secrets = []
# Check all files in current commit
for item in self.clone_dir.rglob("*"):
if item.is_file() and not item.name.startswith(".git"):
try:
content = item.read_text(errors="ignore")
for pattern in secret_patterns:
if re.search(pattern, content, re.IGNORECASE):
found_secrets.append(str(item.relative_to(self.clone_dir)))
except Exception:
pass
if found_secrets:
return {
"passed": False,
"score": 0.0,
"reason": f"Potential secrets found in: {', '.join(found_secrets[:3])}",
}
else:
return {
"passed": True,
"score": 1.0,
"reason": "No obvious secrets detected",
}
except Exception as e:
logger.error(f"Error checking secrets: {e}")
return {"passed": True, "score": 1.0, "reason": "Could not check secrets"}
|