|
1 | 1 | import os |
2 | 2 | import subprocess |
3 | 3 | from logging import Logger |
| 4 | +from pathlib import Path |
| 5 | + |
| 6 | +from codeclash.constants import DIR_LOGS |
4 | 7 |
|
5 | 8 |
|
6 | 9 | def is_running_in_aws_batch() -> bool: |
@@ -56,3 +59,45 @@ def pull_game_container_aws_ecr(*, game_name: str, image_name: str, logger: Logg |
56 | 59 | raise RuntimeError(f"Failed to pull and tag Docker image: {result.stderr}") |
57 | 60 |
|
58 | 61 | logger.info(f"✅ Pulled and tagged Docker image {image_name}") |
| 62 | + |
| 63 | + |
| 64 | +def s3_log_sync(local_output_dir: Path, *, logger: Logger) -> None: |
| 65 | + """Sync local logs to S3 bucket. |
| 66 | +
|
| 67 | + Args: |
| 68 | + local_output_dir: Local directory containing logs to sync |
| 69 | + logger: Logger instance for debug output |
| 70 | +
|
| 71 | + Raises: |
| 72 | + AssertionError: If required environment variables are not set |
| 73 | + RuntimeError: If aws s3 sync fails |
| 74 | + """ |
| 75 | + aws_s3_bucket = os.getenv("AWS_S3_BUCKET") |
| 76 | + aws_s3_prefix = os.getenv("AWS_S3_PREFIX") |
| 77 | + |
| 78 | + assert aws_s3_bucket is not None, "AWS_S3_BUCKET environment variable must be set" |
| 79 | + assert aws_s3_prefix is not None, "AWS_S3_PREFIX environment variable must be set" |
| 80 | + |
| 81 | + # Construct S3 path: s3://bucket/prefix/logs/relative_path |
| 82 | + # where relative_path is local_output_dir relative to DIR_LOGS |
| 83 | + try: |
| 84 | + relative_path = local_output_dir.relative_to(DIR_LOGS) |
| 85 | + except ValueError: |
| 86 | + # If local_output_dir is not under DIR_LOGS, use the full path |
| 87 | + relative_path = local_output_dir |
| 88 | + |
| 89 | + s3_path = f"s3://{aws_s3_bucket}/{aws_s3_prefix}/logs/{relative_path}" |
| 90 | + |
| 91 | + logger.debug(f"Syncing {local_output_dir} to {s3_path}") |
| 92 | + |
| 93 | + result = subprocess.run( |
| 94 | + ["aws", "s3", "sync", str(local_output_dir), s3_path, "--exclude", "*/rounds/*"], |
| 95 | + capture_output=True, |
| 96 | + text=True, |
| 97 | + ) |
| 98 | + |
| 99 | + if result.returncode != 0: |
| 100 | + logger.critical(f"❌ Failed to sync logs to S3: {result.stderr}\n{result.stdout}") |
| 101 | + raise RuntimeError(f"Failed to sync logs to S3: {result.stderr}") |
| 102 | + |
| 103 | + logger.info(f"✅ Successfully synced logs to {s3_path}") |
0 commit comments