Skip to content

Testing and CI

Workflows

Workflow Trigger What it checks
CI (ci.yml) push, PR shellcheck, hadolint, Compose validation (all files + GPU overlays), bats unit tests, mkdocs --strict, image build; image fails fast without a key, runs as UID 10001, ships CPU-only torch and no CUDA packages
Smoke test (smoke-test.yml) push/PR touching the image, weekly, manual Builds the image, downloads gliformer-base-v1, runs the real server for both torch and onnx int8 and tests: healthy status, 401 on missing/wrong key, 422 on invalid payload, score/choice/noul answers, /stats backend, restart without re-download, 429 rate limiting; plus a full docker compose up --build --wait run checking named volumes, persistence across down/up and localhost-only port binding
Publish image (publish.yml) push to main (image paths), v*.*.* tags, manual Multi-arch build and push to GHCR with SBOM/provenance/attestation, GitHub Release for tags, then pulls the published digest on native amd64 and arm64 runners and verifies architecture, imports, CPU torch, fail-fast and the attestation
Deploy docs (docs.yml) push touching docs Builds and publishes this site
Stale (stale.yml) daily Marks inactive issues/PRs

The weekly smoke test catches upstream Jeff changes that would break the image before you redeploy.

Unit tests

tests/test_entrypoint.bats covers the entrypoint without network or model (Hugging Face CLI stubbed): mandatory key, explicit no-auth mode, missing model, one-time download and marker, forced re-download, manually provisioned models, JEFF_MODEL export, boolean normalization, dropping empty variables, thread variables.

Running everything locally

Only Docker is required:

./tests/run-tests.sh            # full suite incl. image build
SKIP_BUILD=1 ./tests/run-tests.sh

Or individual tools:

bats tests/test_entrypoint.bats
shellcheck docker/entrypoint.sh
docker run --rm -i hadolint/hadolint < docker/Dockerfile

Manual end-to-end test

cp .env.example .env
sed -i -e "s/^JEFF_API_KEYS=.*/JEFF_API_KEYS=test/" \
       -e "s|^JEFF_MODEL_ID=.*|JEFF_MODEL_ID=knowledgator/gliformer-base-v1|" \
       -e "s|^JEFF_MODEL_PATH=.*|JEFF_MODEL_PATH=/models/gliformer-base-v1|" \
       -e "s/^JEFF_NOUL_MODE=.*/JEFF_NOUL_MODE=single/" .env
docker compose up -d --build --wait
curl -s localhost:8000/v1/systemone -H 'Authorization: Bearer test' \
  -H 'Content-Type: application/json' \
  -d '{"state":"Login fails","model":"jev-latest","questions":{"q":{"type":"noul"}}}'