Initial deploy setup
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-21 14:00:00 +02:00
commit b8091e59bd
285 changed files with 27854 additions and 0 deletions
+138
View File
@@ -0,0 +1,138 @@
#!/usr/bin/env python
from __future__ import annotations
import argparse
import hashlib
import json
import sys
import zipfile
from pathlib import PurePosixPath
from typing import Any
ROOT_NAME = "VacatureRadar_Project"
MANIFEST_PATH = f"{ROOT_NAME}/PROJECT_MANIFEST.json"
REQUIRED_PATHS = {
f"{ROOT_NAME}/README.md",
f"{ROOT_NAME}/CODEX_START_HERE.md",
f"{ROOT_NAME}/AGENTS.md",
f"{ROOT_NAME}/docs/ai/BACKLOG.yaml",
f"{ROOT_NAME}/docs/ai/PROJECT_STATE.md",
f"{ROOT_NAME}/scripts/codex_bootstrap.sh",
f"{ROOT_NAME}/scripts/codex_verify.sh",
f"{ROOT_NAME}/uv.lock",
MANIFEST_PATH,
}
FORBIDDEN_PARTS = {
".git",
".venv",
".pytest_cache",
".ruff_cache",
"__pycache__",
"backups",
"logs",
"media",
"staticfiles",
}
FORBIDDEN_NAMES = {".env", ".coverage", "db.sqlite3", "celerybeat-schedule"}
class PackageError(ValueError):
pass
def digest(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def load_manifest(archive: zipfile.ZipFile) -> dict[str, Any]:
try:
payload = json.loads(archive.read(MANIFEST_PATH))
except KeyError as exc:
raise PackageError("PROJECT_MANIFEST.json ontbreekt") from exc
except json.JSONDecodeError as exc:
raise PackageError(f"PROJECT_MANIFEST.json is ongeldig: {exc}") from exc
if not isinstance(payload, dict) or not isinstance(payload.get("files"), list):
raise PackageError("PROJECT_MANIFEST.json heeft een ongeldig schema")
return payload
def validate_names(names: list[str]) -> None:
if len(names) != len(set(names)):
raise PackageError("ZIP bevat dubbele padnamen")
missing = sorted(REQUIRED_PATHS - set(names))
if missing:
raise PackageError(f"Verplichte paden ontbreken: {missing}")
for name in names:
path = PurePosixPath(name)
if path.is_absolute() or ".." in path.parts:
raise PackageError(f"Onveilig ZIP-pad: {name}")
if not path.parts or path.parts[0] != ROOT_NAME:
raise PackageError(f"Bestand staat buiten projectroot: {name}")
if any(part in FORBIDDEN_PARTS for part in path.parts):
raise PackageError(f"Runtime/cachepad hoort niet in ZIP: {name}")
if path.name in FORBIDDEN_NAMES:
raise PackageError(f"Runtime/secretbestand hoort niet in ZIP: {name}")
if path.suffix in {".pyc", ".pyo"}:
raise PackageError(f"Bytecode hoort niet in ZIP: {name}")
def validate_manifest(archive: zipfile.ZipFile, payload: dict[str, Any]) -> None:
entries = payload["files"]
expected_paths: set[str] = set()
total_bytes = 0
for entry in entries:
if not isinstance(entry, dict):
raise PackageError("Manifestentry is geen mapping")
relative = entry.get("path")
expected_size = entry.get("bytes")
expected_hash = entry.get("sha256")
if not isinstance(relative, str) or not relative:
raise PackageError("Manifestentry mist path")
archive_path = f"{ROOT_NAME}/{relative}"
if archive_path in expected_paths:
raise PackageError(f"Dubbele manifestentry: {relative}")
expected_paths.add(archive_path)
try:
data = archive.read(archive_path)
except KeyError as exc:
raise PackageError(f"Manifestbestand ontbreekt in ZIP: {relative}") from exc
if len(data) != expected_size:
raise PackageError(f"Grootte wijkt af voor {relative}")
if digest(data) != expected_hash:
raise PackageError(f"SHA-256 wijkt af voor {relative}")
total_bytes += len(data)
actual_paths = {
name for name in archive.namelist() if not name.endswith("/") and name != MANIFEST_PATH
}
if expected_paths != actual_paths:
extra = sorted(actual_paths - expected_paths)
missing = sorted(expected_paths - actual_paths)
raise PackageError(f"Manifest/ZIP-paden verschillen; extra={extra}, missing={missing}")
if payload.get("file_count_excluding_manifest") != len(entries):
raise PackageError("Manifest file_count klopt niet")
if payload.get("total_bytes_excluding_manifest") != total_bytes:
raise PackageError("Manifest total_bytes klopt niet")
def main() -> int:
parser = argparse.ArgumentParser(description="Verifieer een VacatureRadar-project-ZIP")
parser.add_argument("zip_path")
args = parser.parse_args()
try:
with zipfile.ZipFile(args.zip_path) as archive:
corrupt = archive.testzip()
if corrupt:
raise PackageError(f"CRC-fout in {corrupt}")
names = [name for name in archive.namelist() if not name.endswith("/")]
validate_names(names)
validate_manifest(archive, load_manifest(archive))
except (OSError, zipfile.BadZipFile, PackageError) as exc:
print(f"Packagevalidatiefout: {exc}", file=sys.stderr)
return 1
print(f"Project-ZIP geldig: {args.zip_path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())