name: CI on: push: branches: [master] pull_request: branches: [master] jobs: syntax-check: runs-on: linux_amd64 steps: - name: Checkout run: | git clone --depth 1 --branch "${GITHUB_REF_NAME}" \ "https://oauth2:${{ github.token }}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git" . - name: Python 2 syntax check run: | echo "Checking Python 2 syntax..." failed=0 for f in ppf.py proxywatchd.py scraper.py httpd.py \ config.py dbs.py fetch.py connection_pool.py \ engines.py translations.py http2.py \ mysqlite.py misc.py comboparse.py soup_parser.py; do if [ -f "$f" ]; then if python2 -m py_compile "$f" 2>/dev/null; then echo "OK $f" else echo "FAIL $f" failed=1 fi fi done exit $failed - name: Python 3 syntax check run: | echo "Checking Python 3 syntax..." for f in *.py; do python3 -m py_compile "$f" 2>/dev/null && echo "OK $f" || echo "WARN $f" done memory-leak-check: runs-on: linux_amd64 container: image: python:2.7-slim steps: - name: Checkout run: | apt-get update && apt-get install -y git git clone --depth 1 --branch "${GITHUB_REF_NAME}" \ "https://oauth2:${{ github.token }}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git" . - name: Install dependencies run: | pip install --quiet objgraph || true - name: Check for memory leak patterns run: | echo "Scanning for common memory leak patterns..." failed=0 # Check for unbounded list/dict growth without limits echo "Checking for unbounded collections..." for f in ppf.py proxywatchd.py scraper.py httpd.py; do if [ -f "$f" ]; then # Look for .append() without corresponding size limits if grep -n "\.append(" "$f" | grep -v "# bounded" | grep -v "_max\|max_\|limit\|[:]\|pop(" > /tmp/unbounded 2>/dev/null; then count=$(wc -l < /tmp/unbounded) if [ "$count" -gt 20 ]; then echo "WARN $f: $count potential unbounded appends" fi fi fi done # Check for circular references echo "Checking for potential circular references..." for f in ppf.py proxywatchd.py scraper.py httpd.py connection_pool.py; do if [ -f "$f" ]; then if grep -n "self\.\w* = self" "$f" 2>/dev/null; then echo "WARN $f: potential self-reference" fi fi done # Check for __del__ methods (often problematic) echo "Checking for __del__ methods..." for f in *.py; do if grep -n "def __del__" "$f" 2>/dev/null; then echo "WARN $f: has __del__ method (may cause leaks)" fi done # Check that gc is imported where needed echo "Checking gc module usage..." for f in proxywatchd.py httpd.py; do if [ -f "$f" ]; then if ! grep -q "^import gc" "$f" && ! grep -q "^from gc" "$f"; then echo "INFO $f: gc module not imported" fi fi done echo "Memory leak pattern scan complete" - name: Static import check run: | echo "Verifying imports..." python2 -c " import sys sys.path.insert(0, '.') try: import config print('OK config') except Exception as e: print('FAIL config:', e) try: import misc print('OK misc') except Exception as e: print('FAIL misc:', e) try: import mysqlite print('OK mysqlite') except Exception as e: print('FAIL mysqlite:', e) "