CI was a workflow that could not run its own tests: pytest is not a dependency of anything, so a fresh clone fails with "No module named pytest". Test tooling now lives in the backend's dev extra, so CI and a new contributor install the same tools, and ruff is pinned there instead of drifting as a bare version in a workflow step. backup, restore and doctor move the store. Backup uses SQLite's own online API so a running server is safe, and the manifest records the schema version, row counts, sha256 and size read back from the copy. Restore verifies the digest, integrity_check, required tables and schema age before it touches the live file, and keeps what it replaces as .before-restore. Doctor separates broken from degraded. On the 906 MB baseline store (165,973 atoms) it reports no problems and one true warning: 21,362 picture atoms with no CLIP snapshot configured, so those atoms are findable only by the text already on them. The first version called that store healthy because it only complained about paths that were set and missing, never about a sense the store needs and never had. AGPL-3.0-only, because PyMuPDF is dual-licensed AGPL-or-commercial and the repository is public. A permissive license needs the Artifex commercial license bought first; the README says so rather than hiding it. Gates: 253 tests pass; ruff clean repo-wide (17 errors at HEAD); mypy unchanged from HEAD on touched files; pyright 0 errors on the new files; backup 4.0s and restore 2.8s on real data with counts verified equal.
69 lines
1.8 KiB
YAML
69 lines
1.8 KiB
YAML
name: ci
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
backend:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
cache: pip
|
|
# pytest and ruff come from the dev extra, so CI matches a fresh clone.
|
|
- run: pip install -e "./backend[dev]"
|
|
- run: python -m pytest -q
|
|
- run: ruff check backend/src bench
|
|
|
|
mcp:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-go@v5
|
|
with:
|
|
go-version: "1.25"
|
|
cache-dependency-path: ely-eye-mcp/go.sum
|
|
- name: Build, vet and test
|
|
working-directory: ely-eye-mcp
|
|
run: go build ./... && go vet ./... && go test ./...
|
|
- name: gofmt is clean
|
|
working-directory: ely-eye-mcp
|
|
run: test -z "$(gofmt -l .)"
|
|
|
|
interface:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: npm
|
|
cache-dependency-path: frontend/package-lock.json
|
|
- run: npm ci && npm run build
|
|
working-directory: frontend
|
|
|
|
image:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Build the image from a clean clone
|
|
run: docker build -t ely-eye:ci .
|
|
- name: The container answers on both faces
|
|
run: |
|
|
docker run -d --name elyeye -p 8765:8765 ely-eye:ci
|
|
url=http://127.0.0.1:8765/api/status
|
|
for attempt in $(seq 1 30); do
|
|
curl -fsS "$url" -o /tmp/status.json && break
|
|
sleep 2
|
|
done
|
|
cat /tmp/status.json
|
|
curl -fsS http://127.0.0.1:8765/ | grep -q '<div id="root">'
|
|
docker logs elyeye
|