Files
jobtrackingapp/dev/enable_local_workers.py
T

75 lines
4.5 KiB
Python

"""Guard and apply worker settings to the existing isolated local development stack."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import subprocess
ROOT = Path(__file__).resolve().parent.parent
SIDECAR = "sha256:8a29cb90fcc2817b0d784826d55a172c943f5ad7e1b6105e690a2d79ee15fe87"
def capture(arguments, environment):
return subprocess.check_output(["rtk", "proxy", *arguments], env=environment, text=True)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--checkout", type=Path, required=True)
parser.add_argument("--bart-artifact", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--apply", action="store_true")
args = parser.parse_args()
checkout = args.checkout.resolve()
artifact = args.bart_artifact.resolve()
environment = {**os.environ, "JOBTRACKER_DEV_BART_ARTIFACT": str(artifact)}
manifest = json.loads((ROOT / "docs/redesign/phase-9/p9-sec-02/full-model/ARTIFACTS.json").read_text())["weights-only"]
for row in manifest["files"]:
path = artifact / row["file"]
assert path.is_file() and path.stat().st_size == row["bytes"], "Local model file missing or wrong size"
with path.open("rb") as stream:
assert hashlib.file_digest(stream, "sha256").hexdigest() == row["sha256"], "Local model integrity mismatch"
assert json.loads((ROOT / ".artifacts/pre-phase10-ux/local-ai/verification.json").read_text())["status"] == "PASS"
compose = ["docker", "compose", "--project-directory", str(checkout), "--env-file", str(checkout / ".env.dev"),
"-f", str(checkout / "docker-compose.dev.yml"), "-f", str(ROOT / "dev/local-workers.override.yml")]
config = json.loads(capture([*compose, "config", "--format", "json"], environment))
assert config["name"] == "jobjakt-dev", "Only the local development project is permitted"
backend = config["services"]["backend"]
sidecar = config["services"]["ai-service"]
settings = backend["environment"]
assert settings["ASPNETCORE_ENVIRONMENT"] == "Development"
connection = settings["ConnectionStrings__JobTracker"].lower()
assert "server=mariadb;" in connection and "database=jobtracker_dev;" in connection
assert settings["Ai__ExternalProcessingEnabled"].lower() == "false"
assert settings["Email__SmtpHost"] == "mailpit" and settings["Email__SmtpPort"] == "1025"
assert not settings["Email__SmtpUser"] and not settings["Email__SmtpPassword"]
assert all(port.get("host_ip") == "127.0.0.1" for port in backend.get("ports", []))
assert sidecar["environment"]["HF_HUB_OFFLINE"] == "1"
assert sidecar["environment"]["TRANSFORMERS_OFFLINE"] == "1"
assert sidecar["environment"]["EXTERNAL_AI_ENABLED"].lower() == "false"
assert sidecar["environment"]["OLLAMA_BASE_URL"] == "http://jobjakt-dev-ollama:11434"
assert any(volume.get("source") == str(artifact) and volume.get("read_only") for volume in sidecar["volumes"])
assert json.loads(capture(["docker", "image", "inspect", sidecar["image"]], environment))[0]["Id"] == SIDECAR
current = json.loads(capture(["docker", "inspect", "jobjakt-dev-backend-1"], environment))[0]
assert current["Config"]["Labels"]["com.docker.compose.project"] == "jobjakt-dev"
assert json.loads(capture(["docker", "image", "inspect", backend["image"]], environment))[0]["Id"] == current["Image"], "This operation changes worker configuration, not backend code"
record = {"project": config["name"], "verifiedBartRevision": manifest["sourceRevision"], "sidecarImage": SIDECAR,
"enabledWorkers": {key: value for key, value in settings.items() if key.startswith("Workers__")},
"emailSink": "Mailpit", "externalAI": False, "applied": False}
args.output.parent.mkdir(parents=True, exist_ok=True)
if args.apply:
with args.output.with_suffix(".log").open("w", encoding="utf-8") as log:
result = subprocess.run(["rtk", "proxy", *compose, "up", "-d", "--no-deps", "--no-build", "--pull", "never",
"--wait", "--wait-timeout", "120", "backend", "ai-service"], env=environment, stdout=log, stderr=subprocess.STDOUT)
record["exitCode"] = result.returncode
record["applied"] = result.returncode == 0
args.output.write_text(json.dumps(record, indent=2) + "\n", encoding="utf-8")
print(json.dumps(record))
if args.apply:
raise SystemExit(record["exitCode"])
if __name__ == "__main__":
main()