37 lines
1.4 KiB
Python
37 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
class DeploymentContractTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls) -> None:
|
|
cls.compose = (ROOT / "compose.yaml").read_text(encoding="utf-8")
|
|
cls.dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8")
|
|
cls.dockerignore = (ROOT / ".dockerignore").read_text(encoding="utf-8")
|
|
cls.gitignore = (ROOT / ".gitignore").read_text(encoding="utf-8")
|
|
|
|
def test_compose_exposes_only_requested_lan_port(self):
|
|
self.assertIn('"0.0.0.0:8765:8765/tcp"', self.compose)
|
|
self.assertIn("read_only: true", self.compose)
|
|
self.assertIn("target: /app/data", self.compose)
|
|
self.assertIn("no-new-privileges:true", self.compose)
|
|
|
|
def test_image_runs_as_non_root_with_healthcheck(self):
|
|
self.assertIn("USER xiaobai", self.dockerfile)
|
|
self.assertIn("HEALTHCHECK", self.dockerfile)
|
|
self.assertIn('"--host", "0.0.0.0", "--port", "8765"', self.dockerfile)
|
|
|
|
def test_secrets_and_runtime_data_are_not_copied_into_image(self):
|
|
for pattern in (".env", "data/private-mentor-skills/", "data/*.db", "data/*.db-wal", "data/*.db-shm"):
|
|
self.assertIn(pattern, self.dockerignore)
|
|
self.assertIn("data/private-mentor-skills/", self.gitignore)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|