Some checks failed
AITBC CI/CD Pipeline / lint-and-test (3.11) (pull_request) Has been cancelled
AITBC CI/CD Pipeline / lint-and-test (3.12) (pull_request) Has been cancelled
AITBC CI/CD Pipeline / lint-and-test (3.13) (pull_request) Has been cancelled
AITBC CLI Level 1 Commands Test / test-cli-level1 (3.11) (pull_request) Has been cancelled
AITBC CLI Level 1 Commands Test / test-cli-level1 (3.12) (pull_request) Has been cancelled
AITBC CLI Level 1 Commands Test / test-cli-level1 (3.13) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (apps/coordinator-api/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (cli/aitbc_cli) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (packages/py/aitbc-core/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (packages/py/aitbc-crypto/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (packages/py/aitbc-sdk/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (tests) (pull_request) Has been cancelled
Security Scanning / CodeQL Security Analysis (javascript) (pull_request) Has been cancelled
Security Scanning / CodeQL Security Analysis (python) (pull_request) Has been cancelled
Security Scanning / Dependency Security Scan (pull_request) Has been cancelled
Security Scanning / Container Security Scan (pull_request) Has been cancelled
Security Scanning / OSSF Scorecard (pull_request) Has been cancelled
AITBC CI/CD Pipeline / test-cli (pull_request) Has been cancelled
AITBC CI/CD Pipeline / test-services (pull_request) Has been cancelled
AITBC CI/CD Pipeline / test-production-services (pull_request) Has been cancelled
AITBC CI/CD Pipeline / security-scan (pull_request) Has been cancelled
AITBC CI/CD Pipeline / build (pull_request) Has been cancelled
AITBC CI/CD Pipeline / deploy-staging (pull_request) Has been cancelled
AITBC CI/CD Pipeline / deploy-production (pull_request) Has been cancelled
AITBC CI/CD Pipeline / performance-test (pull_request) Has been cancelled
AITBC CI/CD Pipeline / docs (pull_request) Has been cancelled
AITBC CI/CD Pipeline / release (pull_request) Has been cancelled
AITBC CI/CD Pipeline / notify (pull_request) Has been cancelled
AITBC CLI Level 1 Commands Test / test-summary (pull_request) Has been cancelled
Security Scanning / Security Summary Report (pull_request) Has been cancelled
- CLI commands: replace print with click.echo (ensures proper stdout handling) - Coordinator API services: add logging import and logger; replace print with logger.info - Automation scripts: claim-task.py, monitor-prs.py, qa-cycle.py now use logging and have random jitter at startup - Also includes fix for name shadowing in regulatory.py (aliased service imports) which was pending This addresses issue #23 (print statements) and improves error handling. Note: Many bare except clauses (issue #20) remain; will be addressed separately.
121 lines
4.4 KiB
Python
Executable File
121 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os, sys, json, subprocess, tempfile, shutil, glob, re
|
|
import random, time, logging
|
|
from datetime import datetime
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
AGENT = os.getenv("AGENT_NAME", "aitbc")
|
|
LOG_DIR = "/var/log/aitbc"
|
|
QA_LOG = os.path.join(LOG_DIR, "qa_cycle.log")
|
|
|
|
def run_cmd(cmd, capture=True, check=False):
|
|
result = subprocess.run(cmd, shell=True, capture_output=capture, text=True)
|
|
if check and result.returncode != 0:
|
|
logger.error(f"Command failed: {cmd}")
|
|
logger.error(f"stderr: {result.stderr}")
|
|
return None
|
|
return result.stdout if capture else result.returncode
|
|
|
|
def feature_tests():
|
|
logger.info("=== FEATURE TESTS ===")
|
|
for mod in ["aiohttp", "fastapi", "click", "pydantic"]:
|
|
cmd = f"python3 -c 'import {mod}; print({mod}.__version__)'"
|
|
out = run_cmd(cmd)
|
|
if out is None:
|
|
logger.error(f"Import failed: {mod}")
|
|
else:
|
|
logger.info(f"{mod} import OK: {out.strip()}")
|
|
out = run_cmd("/opt/aitbc/cli_venv/bin/aitbc --help")
|
|
if out:
|
|
logger.info("CLI help works")
|
|
else:
|
|
logger.error("CLI help failed")
|
|
out = run_cmd("curl -s http://localhost:8010/health || true")
|
|
if out and 'ok' in out.lower():
|
|
logger.info("Brother chain health endpoint OK")
|
|
else:
|
|
logger.warning("Brother chain health check inconclusive")
|
|
|
|
def bug_sentinel():
|
|
logger.info("=== BUG SENTINEL ===")
|
|
logs = glob.glob("/var/log/aitbc/*.log")
|
|
patterns = ["ERROR", "CRITICAL", "FATAL", "Traceback", "Exception"]
|
|
found = []
|
|
for logfile in logs:
|
|
try:
|
|
with open(logfile) as f:
|
|
lines = f.readlines()[-200:]
|
|
except:
|
|
continue
|
|
for line in lines:
|
|
if any(p in line for p in patterns):
|
|
found.append(f"{logfile}: {line.strip()}")
|
|
if found:
|
|
logger.warning(f"Found {len(found)} error patterns (sample):")
|
|
for item in found[:5]:
|
|
logger.warning(f" {item}")
|
|
else:
|
|
logger.info("No error patterns in recent logs")
|
|
|
|
def code_review():
|
|
logger.info("=== CODE REVIEW ===")
|
|
py_files = run_cmd("find /opt/aitbc -name '*.py' -type f | head -30").splitlines()
|
|
issues = []
|
|
for f in py_files:
|
|
try:
|
|
with open(f) as fp:
|
|
content = fp.read()
|
|
except:
|
|
continue
|
|
if re.search(r'except\s*:', content):
|
|
issues.append(f"{f}: bare except")
|
|
if re.search(r'def\s+\w+\s*\([^)]*=\s*[\[\{\}]', content):
|
|
issues.append(f"{f}: mutable default argument")
|
|
if 'print(' in content and 'if __name__' not in content:
|
|
issues.append(f"{f}: print statement in library code")
|
|
if re.search(r'(password|secret|key)\s*=\s*[\'"][^\'"]+[\'"]', content, re.IGNORECASE):
|
|
issues.append(f"{f}: possible hardcoded secret")
|
|
if issues:
|
|
logger.warning(f"Found {len(issues)} code quality issues (sample):")
|
|
for i in issues[:5]:
|
|
logger.warning(f" {i}")
|
|
else:
|
|
logger.info("No obvious code quality issues detected")
|
|
|
|
def scenario_runner():
|
|
logger.info("=== SCENARIO RUNNER ===")
|
|
tmp = tempfile.mkdtemp(prefix="aitbc_qa_")
|
|
try:
|
|
run_cmd(f"git init {tmp}", check=True)
|
|
run_cmd(f"git -C {tmp} config user.email 'qa@aitbc'", check=True)
|
|
run_cmd(f"git -C {tmp} config user.name 'QA Agent'", check=True)
|
|
run_cmd(f"echo 'test' > {tmp}/test.txt", check=True)
|
|
run_cmd(f"git -C {tmp} add .", check=True)
|
|
run_cmd(f"git -C {tmp} commit -m 'initial'", check=True)
|
|
run_cmd(f"git -C {tmp} checkout -b claim/123", check=True)
|
|
run_cmd(f"git -C {tmp} commit --allow-empty -m 'Claim issue 123'", check=True)
|
|
logger.info("Git workflow test passed")
|
|
except Exception as e:
|
|
logger.error(f"Git workflow test failed: {e}")
|
|
finally:
|
|
shutil.rmtree(tmp, ignore_errors=True)
|
|
|
|
def main():
|
|
logger.info(f"QA CYCLE STARTED for {AGENT}")
|
|
start = datetime.now()
|
|
# Jitter: 0-900 seconds (15 minutes)
|
|
jitter = random.randint(0, 900)
|
|
logger.info(f"Sleeping {jitter}s before start...")
|
|
time.sleep(jitter)
|
|
feature_tests()
|
|
bug_sentinel()
|
|
code_review()
|
|
scenario_runner()
|
|
elapsed = datetime.now() - start
|
|
logger.info(f"QA CYCLE COMPLETED in {elapsed.total_seconds():.1f}s")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|