118 lines
3.8 KiB
Python
Executable File
118 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Packages the client-side scripts and their dependencies into a distributable .tar.gz archive.
|
|
|
|
This script should be run from the root of the project repository.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tarfile
|
|
from pathlib import Path
|
|
|
|
try:
|
|
# Assumes yt_ops_services/version.py exists and is importable
|
|
from yt_ops_services.version import get_version as get_api_version
|
|
except ImportError:
|
|
print("Error: Could not import get_version from yt_ops_services.version.", file=sys.stderr)
|
|
print("Please ensure yt_ops_services/version.py exists and run this script from the project root.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
def get_client_version():
|
|
"""Reads the client version from the VERSION.client file."""
|
|
try:
|
|
return Path('VERSION.client').read_text(encoding='utf-8').strip()
|
|
except FileNotFoundError:
|
|
print("Error: VERSION.client file not found in the project root.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
# --- Configuration ---
|
|
|
|
# Defines the content of the package.
|
|
# Keys are source paths relative to the project root.
|
|
# Values are destination paths inside the archive.
|
|
PACKAGE_CONTENT = {
|
|
'get_info_json_client.py': 'get_info_json_client.py',
|
|
'list_formats.py': 'list_formats.py',
|
|
'format_download.py': 'format_download.py',
|
|
'stress_test_formats.py': 'stress_test_formats.py',
|
|
'cli.config': 'cli.config',
|
|
'README.client.md': 'README.md', # Rename for convention
|
|
'formats.md': 'formats.md',
|
|
'VERSION.client': 'VERSION.client',
|
|
'yt_ops_services': 'yt_ops_services',
|
|
'thrift_model/gen_py': 'thrift_model/gen_py',
|
|
}
|
|
|
|
# Client-side Python requirements
|
|
CLIENT_REQUIREMENTS = [
|
|
'thrift==0.16.0',
|
|
]
|
|
|
|
|
|
def main():
|
|
"""Main entry point"""
|
|
parser = argparse.ArgumentParser(description="Package the yt-ops-services client tools.")
|
|
parser.add_argument('--output-dir', default='dist', help='Directory to save the package file (default: dist).')
|
|
args = parser.parse_args()
|
|
|
|
api_version = get_api_version()
|
|
client_version = get_client_version()
|
|
package_name = f"yt-ops-services-client-{api_version}-{client_version}"
|
|
archive_filename = f"{package_name}.tar.gz"
|
|
|
|
os.makedirs(args.output_dir, exist_ok=True)
|
|
archive_path = os.path.join(args.output_dir, archive_filename)
|
|
|
|
staging_dir = Path(args.output_dir) / f"{package_name}-staging"
|
|
|
|
print(f"Creating client package: {archive_filename}")
|
|
|
|
if staging_dir.exists():
|
|
shutil.rmtree(staging_dir)
|
|
staging_dir.mkdir(parents=True)
|
|
|
|
package_root = staging_dir / package_name
|
|
package_root.mkdir()
|
|
|
|
try:
|
|
print("Staging files...")
|
|
for src, dest in PACKAGE_CONTENT.items():
|
|
src_path = Path(src)
|
|
dest_path = package_root / dest
|
|
|
|
if not src_path.exists():
|
|
print(f"Warning: Source not found, skipping: {src_path}", file=sys.stderr)
|
|
continue
|
|
|
|
dest_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
if src_path.is_dir():
|
|
shutil.copytree(src_path, dest_path)
|
|
else:
|
|
shutil.copy2(src_path, dest_path)
|
|
|
|
# Create __init__.py to ensure thrift_model is a package
|
|
(package_root / 'thrift_model/__init__.py').touch()
|
|
|
|
print("Creating requirements.txt...")
|
|
(package_root / 'requirements.txt').write_text('\n'.join(CLIENT_REQUIREMENTS) + '\n', encoding='utf-8')
|
|
|
|
print(f"Creating archive at {archive_path}...")
|
|
with tarfile.open(archive_path, "w:gz") as tar:
|
|
tar.add(package_root, arcname=package_name)
|
|
|
|
print("\nPackage created successfully!")
|
|
print(f" -> {archive_path}")
|
|
|
|
finally:
|
|
if staging_dir.exists():
|
|
print("Cleaning up staging directory...")
|
|
shutil.rmtree(staging_dir)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|