diff --git a/Dockerfile b/Dockerfile index 05e4233..e6f287b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libxcomposite1 libxdamage1 libxrandr2 libgbm1 \ libpango-1.0-0 libcairo2 libasound2 \ tesseract-ocr tesseract-ocr-eng \ - curl \ && rm -rf /var/lib/apt/lists/* COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages @@ -43,9 +42,12 @@ COPY stealth_scripts/ ./stealth_scripts/ COPY templates/ ./templates/ RUN mkdir -p /app/sessions /root/.pry +RUN useradd --create-home --shell /bin/bash --uid 1000 pry && chown -R pry:pry /app +USER pry + EXPOSE 8002 HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \ - CMD curl -sf http://localhost:8002/health || exit 1 + CMD python3 -c "import urllib.request, sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8002/health', timeout=2).status == 200 else 1)" || exit 1 ENTRYPOINT ["docker-entrypoint.sh"] CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8002", \ diff --git a/docker-compose.yml b/docker-compose.yml index ce76403..574d9bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,7 @@ services: environment: - PYTHONUNBUFFERED=1 - PRY_TIMEOUT=60 - - FLARESOLVERR_URL=http://flaresolverr:8191/v1 + - PRY_FLARESOLVERR_URL=http://flaresolverr:8191/v1 - TOR_ENABLED=0 - TOR_SOCKS5_HOST=tor - TOR_SOCKS5_PORT=9050 @@ -27,7 +27,7 @@ services: - MIN_QUALITY=20 - RATE_LIMIT_RPM=120 healthcheck: - test: ["CMD", "curl", "-sf", "http://localhost:8002/health"] + test: ["CMD", "python3", "-c", "import urllib.request, sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8002/health', timeout=2).status == 200 else 1)"] interval: 15s timeout: 5s retries: 3 diff --git a/pyproject.toml b/pyproject.toml index 77acc0a..eb1c769 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,13 @@ dependencies = [ "prometheus-client>=0.21.0", "opentelemetry-api>=1.29.0", "opentelemetry-sdk>=1.29.0", + "cloudscraper>=1.2.0", + "aiohttp-socks[aiohttp]>=0.8.0", + "aiohttp>=3.9.0", + "undetected-chromedriver>=3.5.0", + "pyjwt>=2.8.0", + "apify>=2.0.0", + "playwright-stealth>=1.0.0", ] [project.optional-dependencies] @@ -64,6 +71,8 @@ dev = [ "mypy>=1.12.0", "pre-commit>=4.0.0", "alembic>=1.14.0", + "respx>=0.21.0", + "commitizen>=3.12.0", ] [project.scripts] @@ -146,3 +155,30 @@ ignore_missing_imports = true [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] + +[tool.coverage.run] +branch = true +source = ["api", "cli", "extractor", "parser", "scraper", "monitor", "network", "cache", "auth", "errors", "paths", "settings", "db", "tasks", "quality", "reports", "extraction", "x402", "x402_middleware"] +omit = [ + "tests/*", + "browser-extension/*", + "shopify-app/*", + "wordpress-plugin/*", + "*/templates/*", + "*/profiles/*", + "*/stealth_scripts/*", + "pry.egg-info/*", + "build/*", + "dist/*", +] + +[tool.coverage.report] +fail_under = 45 # gradual path: current is ~47%; raise to 60, 70, 75, 80 in successive PRs +precision = 1 +show_missing = true +exclude_lines = [ + "pragma: no cover", + "if __name__ == .__main__.:", + "raise NotImplementedError", + "pass", +] diff --git a/requirements.txt b/requirements.txt index ad5d64e..4641c15 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,3 +30,10 @@ alembic>=1.14.0 prometheus-client>=0.21.0 opentelemetry-api>=1.29.0 opentelemetry-sdk>=1.29.0 +cloudscraper>=1.2.0 +aiohttp-socks[aiohttp]>=0.8.0 +aiohttp>=3.9.0 +undetected-chromedriver>=3.5.0 +pyjwt>=2.8.0 +apify>=2.0.0 +playwright-stealth>=1.0.0