ci: replace broken default workflows with compile/unit/integration CI

The two scaffold workflows (Python application / Python package) failed on
every PR: they installed deps from a non-existent requirements.txt, ran
flake8/pytest over the vendored yt_dlp fork (new syntax under the 3.8/3.9
matrix), and collected ad-hoc root scripts — notably test_ai.py, which is
an invalid pasted object dump (not Python).

- Remove python-app.yml / python-package.yml and the junk root scripts
  (test.py, test_ai.py, test_time.py)
- Add .github/workflows/ci.yml with three PR-check jobs:
  * compile     — py_compile every first-party .py (no deps)
  * unit        — pytest on pure logic (conanjurer_functions, constants)
  * integration — boot the Flask services and assert the X-Conjurer-Api-Key
                  auth contract (communication_subroutine + conjurer_musician)
- Add tests/ suite, pytest.ini (testpaths=tests) and conftest.py (sys.path)

Fixes surfaced by the compile gate / needed for the integration job:
- conjurer_librarian/search_bot.py + search_bot2.py: f-string reused the
  same quote ({item["exists"]}) -> SyntaxError on Python < 3.12
- conjurer_musician/media_search_functions.py: made import-safe
  (env-overridable paths, lazy DB load / mkdir) so the service can be
  imported and tested off the Pi

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Michal Tuszowski
2026-06-29 11:57:40 +02:00
committed by Michał Tuszowski
parent a32bbdd03c
commit a6c20a0054
15 changed files with 310 additions and 137 deletions
+56
View File
@@ -0,0 +1,56 @@
"""Integration: the bot's communication Flask layer enforces the shared key,
and the key the bot would *send* (constants.service_headers) is accepted.
"""
import constants
import communication_subroutine as cs
def _client(key="test-secret"):
cs.API_KEY = key
return cs.app.test_client()
def test_prepped_tracks_rejected_without_key():
client = _client()
resp = client.post(
"/prepped_tracks", data='["all", "x"]', content_type="application/json"
)
assert resp.status_code == 401
def test_prepped_tracks_accepted_with_key():
client = _client()
resp = client.post(
"/prepped_tracks",
data='["all", "x"]',
headers={"X-Conjurer-Api-Key": "test-secret"},
content_type="application/json",
)
assert resp.status_code == 200
def test_conjurer_get_is_open():
client = _client()
assert client.get("/conjurer").status_code == 200
def test_open_when_key_unset():
client = _client(key=None)
resp = client.post(
"/prepped_tracks", data='["all", "x"]', content_type="application/json"
)
assert resp.status_code == 200
def test_bot_service_headers_accepted_by_service(monkeypatch):
# End-to-end auth contract: the header constants.service_headers() produces
# is exactly what communication_subroutine._authorize_request() expects.
monkeypatch.setattr(constants, "API_SHARED_KEY", "shared-xyz")
cs.API_KEY = "shared-xyz"
resp = cs.app.test_client().post(
"/prepped_tracks",
data='["all", "x"]',
headers=constants.service_headers(),
content_type="application/json",
)
assert resp.status_code == 200