"""Upload a MoonWell Launcher installer to S3-compatible storage. Release metadata is supplied by ``deploy_launcher.ps1`` through environment variables. A real Python file avoids Windows PowerShell quoting problems that occur when a multiline program is passed to ``python -c``. """ from __future__ import annotations import os from pathlib import Path import boto3 from botocore.config import Config def required_environment_value(name: str) -> str: value = os.environ.get(name, "").strip() if not value: raise RuntimeError(f"Required environment variable is missing: {name}") return value release_file = Path(required_environment_value("MOONWELL_RELEASE_FILE")) endpoint = required_environment_value("MOONWELL_RELEASE_ENDPOINT") bucket = required_environment_value("MOONWELL_RELEASE_BUCKET") object_key = required_environment_value("MOONWELL_RELEASE_KEY") version = required_environment_value("MOONWELL_RELEASE_VERSION") sha256 = required_environment_value("MOONWELL_RELEASE_SHA256") if not release_file.is_file(): raise FileNotFoundError(f"Installer does not exist: {release_file}") path_style = os.getenv("AWS_USE_PATH_STYLE_ENDPOINT", "true").lower() addressing_style = ( "path" if path_style in ("1", "true", "yes") else "virtual" ) s3 = boto3.client( "s3", endpoint_url=endpoint, region_name=os.getenv("AWS_DEFAULT_REGION", "ru-central1"), config=Config(s3={"addressing_style": addressing_style}), ) s3.upload_file( str(release_file), bucket, object_key, ExtraArgs={ "ACL": "public-read", "ContentType": "application/x-msdownload", "CacheControl": "no-cache, max-age=0", "Metadata": { "launcher-version": version, "sha256": sha256, }, }, ) response = s3.head_object(Bucket=bucket, Key=object_key) local_size = release_file.stat().st_size remote_size = int(response["ContentLength"]) if remote_size != local_size: raise RuntimeError( f"Uploaded object size mismatch: local={local_size}, " f"remote={remote_size}" ) print("S3_VERSION_ID=" + str(response.get("VersionId", ""))) print("S3_CONTENT_LENGTH=" + str(remote_size))