From a1cab89851863fce23ee8016f590e7aec8f0a07a Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Wed, 13 May 2026 11:40:47 +0200 Subject: [PATCH 1/2] fix: reject deploy of dead services and gate release on CI Block deployment of services with status "dead" (e.g. peer2profit) with a 400 error. Add deprecation notice to peer2profit guide. Ensure the release workflow only publishes after lint and tests pass by adding a ci job dependency. Closes cp-gjea, cp-2wbv --- .github/workflows/release.yml | 16 ++++++++++++++++ app/main.py | 2 ++ docs/guides/peer2profit.md | 3 +++ 3 files changed, 21 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 89d2a79..420e711 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,23 @@ permissions: packages: write jobs: + ci: + name: Verify CI passes + runs-on: [self-hosted, linux, x64] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install dependencies + run: pip install -r requirements.txt -r requirements-dev.txt ruff + - name: Lint + run: ruff check . && ruff format --check . + - name: Test + run: pytest + release: + needs: ci name: Bump version and release runs-on: [self-hosted, linux, x64] if: "!contains(github.event.head_commit.message, '[skip ci]')" diff --git a/app/main.py b/app/main.py index 66c4b65..c6cfc09 100644 --- a/app/main.py +++ b/app/main.py @@ -796,6 +796,8 @@ async def api_deploy(request: Request, slug: str, body: DeployRequest, worker_id svc = catalog.get_service(slug) if not svc: raise HTTPException(status_code=404, detail=f"Service '{slug}' not found") + if svc.get("status") == "dead": + raise HTTPException(status_code=400, detail=f"Service '{slug}' is no longer available (dead/discontinued)") docker_conf = svc.get("docker", {}) image = docker_conf.get("image") diff --git a/docs/guides/peer2profit.md b/docs/guides/peer2profit.md index 8cad891..9563194 100644 --- a/docs/guides/peer2profit.md +++ b/docs/guides/peer2profit.md @@ -1,5 +1,8 @@ # Peer2Profit +> [!CAUTION] +> **Deprecated:** Peer2Profit is no longer operational and has been marked as dead in CashPilot. Deployment is blocked. This guide is kept for reference only. + > **Category:** Bandwidth Sharing | **Status:** Dead > **Website:** [https://peer2profit.com](https://peer2profit.com) From 4ae66e4162aaf81c6fa51df769e949e76cb9f987 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Wed, 13 May 2026 12:13:45 +0200 Subject: [PATCH 2/2] fix: address review findings (dead service 410, pin ruff, add test, pip cache) - Change dead service response from 400 to 410 (Gone) for correct REST semantics - Add ruff to requirements-dev.txt instead of unpinned install in CI - Add pip cache to CI setup-python step - Add test for deploy of dead service returning 410 --- .github/workflows/release.yml | 3 ++- app/main.py | 2 +- requirements-dev.txt | 1 + tests/test_main_deploy_routes.py | 11 +++++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 420e711..9ae1357 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,8 +26,9 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.12' + cache: 'pip' - name: Install dependencies - run: pip install -r requirements.txt -r requirements-dev.txt ruff + run: pip install -r requirements.txt -r requirements-dev.txt --quiet - name: Lint run: ruff check . && ruff format --check . - name: Test diff --git a/app/main.py b/app/main.py index c6cfc09..2025915 100644 --- a/app/main.py +++ b/app/main.py @@ -797,7 +797,7 @@ async def api_deploy(request: Request, slug: str, body: DeployRequest, worker_id if not svc: raise HTTPException(status_code=404, detail=f"Service '{slug}' not found") if svc.get("status") == "dead": - raise HTTPException(status_code=400, detail=f"Service '{slug}' is no longer available (dead/discontinued)") + raise HTTPException(status_code=410, detail=f"Service '{slug}' is no longer available (dead/discontinued)") docker_conf = svc.get("docker", {}) image = docker_conf.get("image") diff --git a/requirements-dev.txt b/requirements-dev.txt index f362c0e..ca01fbc 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,5 @@ pytest>=8.0 pytest-asyncio>=0.23 pytest-cov>=5.0 +ruff>=0.11.0 tzdata>=2024.1 diff --git a/tests/test_main_deploy_routes.py b/tests/test_main_deploy_routes.py index d1925e3..ede5a44 100644 --- a/tests/test_main_deploy_routes.py +++ b/tests/test_main_deploy_routes.py @@ -125,6 +125,17 @@ def test_deploy_no_image(self, client): resp = client.post("/api/deploy/grass", json={}) assert resp.status_code == 400 + def test_deploy_dead_service(self, client): + svc = {"slug": "peer2profit", "name": "Peer2Profit", "status": "dead", "docker": {"image": "x"}} + with ( + _auth_owner(), + patch("app.main.database.list_workers", new_callable=AsyncMock, return_value=[_online_worker()]), + patch("app.main.catalog.get_service", return_value=svc), + ): + resp = client.post("/api/deploy/peer2profit", json={}) + assert resp.status_code == 410 + assert "no longer available" in resp.json()["detail"] + def test_deploy_no_auth(self, client): with _no_auth(): resp = client.post("/api/deploy/honeygain", json={})