2026-07-08 22:31:31 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""Create a clean Nexus release tarball with deploy/runtime junk excluded."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import tarfile
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EXCLUDE_NAMES = {
|
|
|
|
|
".git",
|
|
|
|
|
"node_modules",
|
|
|
|
|
".venv",
|
|
|
|
|
".venv-py314",
|
|
|
|
|
".venv-py312-codex",
|
2026-07-09 05:12:54 +08:00
|
|
|
".venv-codex-test",
|
2026-07-08 22:31:31 +08:00
|
|
|
"venv",
|
|
|
|
|
"__pycache__",
|
|
|
|
|
".pytest_cache",
|
|
|
|
|
".ruff_cache",
|
|
|
|
|
".mypy_cache",
|
|
|
|
|
".playwright-mcp",
|
|
|
|
|
".cursor",
|
|
|
|
|
".claude",
|
|
|
|
|
"test-results",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EXCLUDE_SUFFIXES = {".pyc", ".pyo"}
|
|
|
|
|
EXCLUDE_EXACT = {
|
|
|
|
|
".env",
|
|
|
|
|
"SECRETS.md",
|
|
|
|
|
"deploy/nexus-1panel.secrets.sh",
|
|
|
|
|
"docker/.env",
|
|
|
|
|
"docker/.env.prod",
|
|
|
|
|
"docker/runtime",
|
|
|
|
|
"web/data",
|
|
|
|
|
"web/uploads",
|
|
|
|
|
"tmp",
|
|
|
|
|
"2025.2",
|
|
|
|
|
"=2025.2",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def should_include(path: Path, rel: str) -> bool:
|
2026-07-09 05:12:54 +08:00
|
|
|
rel_parts = Path(rel).parts
|
|
|
|
|
parts = set(rel_parts)
|
2026-07-08 22:31:31 +08:00
|
|
|
if parts & EXCLUDE_NAMES:
|
|
|
|
|
return False
|
2026-07-09 05:12:54 +08:00
|
|
|
if any(part.startswith(".venv-") for part in rel_parts):
|
|
|
|
|
return False
|
2026-07-08 22:31:31 +08:00
|
|
|
if rel in EXCLUDE_EXACT:
|
|
|
|
|
return False
|
|
|
|
|
if any(rel == exact or rel.startswith(exact + "/") for exact in EXCLUDE_EXACT):
|
|
|
|
|
return False
|
|
|
|
|
if path.suffix in EXCLUDE_SUFFIXES:
|
|
|
|
|
return False
|
|
|
|
|
if rel.endswith(".bak-"):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> int:
|
|
|
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
|
|
|
parser.add_argument("--root", required=True, type=Path)
|
|
|
|
|
parser.add_argument("--output", required=True, type=Path)
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
root = args.root.resolve()
|
|
|
|
|
output = args.output.resolve()
|
|
|
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
with tarfile.open(output, "w:gz") as tf:
|
|
|
|
|
for path in sorted(root.rglob("*")):
|
|
|
|
|
if not path.is_file():
|
|
|
|
|
continue
|
|
|
|
|
rel = path.relative_to(root).as_posix()
|
|
|
|
|
if path.resolve() == output:
|
|
|
|
|
continue
|
|
|
|
|
if not should_include(path, rel):
|
|
|
|
|
continue
|
|
|
|
|
tf.add(path, arcname=f"nexus-release/{rel}", recursive=False)
|
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
|
|
print(output)
|
|
|
|
|
print(f"files={count}")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
raise SystemExit(main())
|