Files
Nexus/scripts/generate_release_bundle.py
2026-07-09 05:12:54 +08:00

93 lines
2.2 KiB
Python

#!/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",
".venv-codex-test",
"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:
rel_parts = Path(rel).parts
parts = set(rel_parts)
if parts & EXCLUDE_NAMES:
return False
if any(part.startswith(".venv-") for part in rel_parts):
return False
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())