2026-10-15 20:08:15 +08:00
|
|
|
#!/usr/bin/env python3
|
2026-10-17 13:13:26 +08:00
|
|
|
"""Build deployment images inside Docker; no host Rust or Haskell tools required."""
|
2026-10-15 20:08:15 +08:00
|
|
|
import argparse
|
2026-10-17 14:21:52 +08:00
|
|
|
import os
|
2026-10-15 20:08:15 +08:00
|
|
|
from pathlib import Path
|
|
|
|
|
import shutil
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
root = Path(__file__).resolve().parents[1]
|
|
|
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
2026-10-17 13:13:26 +08:00
|
|
|
parser.add_argument('--env-file', type=Path, help='Compose environment file (default: .env, or .env.example when absent)')
|
|
|
|
|
parser.add_argument('--build-database', action='store_true', help='compatibility option; database is always built inside Docker')
|
|
|
|
|
parser.add_argument('--sources-env-file', type=Path, help='optional second Compose env file overriding build download sources')
|
2026-10-17 14:21:52 +08:00
|
|
|
parser.add_argument('--project-name', help='Compose project name')
|
2026-10-15 20:08:15 +08:00
|
|
|
args = parser.parse_args()
|
2026-10-17 13:13:26 +08:00
|
|
|
if shutil.which('docker') is None:
|
|
|
|
|
parser.error('Docker with the Compose plugin is required; see docs/deployment.md.')
|
|
|
|
|
for manifest in ['external/ChuSQL-RustDriver/Cargo.toml', 'external/ChuSQL/chusql-core/storage/Cargo.toml']:
|
|
|
|
|
if not (root / manifest).is_file():
|
2026-10-17 14:21:52 +08:00
|
|
|
parser.error('Initialize external dependencies with python3 scripts/fetch-deps.py first.')
|
2026-10-17 13:13:26 +08:00
|
|
|
envfile = args.env_file or (root / '.env' if (root / '.env').is_file() else root / '.env.example')
|
|
|
|
|
if not envfile.is_file():
|
|
|
|
|
parser.error(f'Environment file does not exist: {envfile}')
|
|
|
|
|
command = ['docker', 'compose', '--env-file', str(envfile.resolve())]
|
|
|
|
|
if args.sources_env_file:
|
|
|
|
|
if not args.sources_env_file.is_file():
|
|
|
|
|
parser.error(f'Source configuration does not exist: {args.sources_env_file}')
|
|
|
|
|
command.extend(['--env-file', str(args.sources_env_file.resolve())])
|
2026-10-17 14:21:52 +08:00
|
|
|
if args.project_name:
|
|
|
|
|
command.extend(['-p', args.project_name])
|
2026-10-17 13:13:26 +08:00
|
|
|
command.extend([
|
|
|
|
|
'-f', str(root / 'deploy/compose.yaml'),
|
|
|
|
|
'build', 'init', 'api', 'ssh', 'db', 'db-init', 'web',
|
|
|
|
|
])
|
2026-10-17 14:21:52 +08:00
|
|
|
# Build-only parsing needs values even before deploy.sh creates runtime credentials.
|
|
|
|
|
build_env = os.environ.copy()
|
|
|
|
|
for key in ['CHUSQL_ROOT_PASSWORD', 'CHUSQL_PASSWORD']:
|
|
|
|
|
build_env[key] = build_env.get(key) or 'unused-build-placeholder'
|
2026-10-17 13:13:26 +08:00
|
|
|
try:
|
2026-10-17 14:21:52 +08:00
|
|
|
subprocess.run(command, cwd=root, check=True, env=build_env)
|
2026-10-17 13:13:26 +08:00
|
|
|
except subprocess.CalledProcessError as error:
|
|
|
|
|
raise SystemExit(error.returncode) from None
|
|
|
|
|
print('Deployment images built inside Docker. No host binaries were created.')
|