Source code for operators.github_to_s3
from airflow.models import BaseOperator
from airflow.utils.decorators import apply_defaults
from config import Config
import os
import shutil
import subprocess
from tempfile import mkdtemp
DEFAULT_S3_BUCKET = Config.DATA_LAKE_BUCKET
[docs]
class GithubToS3Operator(BaseOperator):
"""
this is a sin
"""
ui_color = "#4287f5"
@apply_defaults
def __init__(
self,
repo_url: str,
s3_key: str,
s3_bucket_name: str = DEFAULT_S3_BUCKET,
*args,
**kwargs,
):
super(GithubToS3Operator, self).__init__(*args, **kwargs)
self.repo_url = repo_url
self.s3_bucket_name = s3_bucket_name
self.s3_key = s3_key
[docs]
def execute(self, context):
"""
Clones a git repository to a temporary directory, uploads it to S3,
then cleans up the temporary files.
"""
import boto3
temp_dir = mkdtemp(dir="/tmp")
repo_path = os.path.join(temp_dir, self.repo_url.split("/")[-1])
git_url = f"git@github.com:{self.repo_url}.git"
try:
# Clone the repository
subprocess.run(
["git", "clone", git_url, repo_path],
check=True,
capture_output=True,
)
# Initialize S3 client
s3_client = boto3.client("s3")
# Upload all files in the cloned repo
for root, _, files in os.walk(repo_path):
for each_file in files:
file_path = os.path.join(root, each_file)
# Calculate relative path for S3 key
relative_path = os.path.relpath(file_path, repo_path)
s3_key = f"{self.s3_key.rstrip('/')}/{relative_path}"
s3_client.upload_file(file_path, self.s3_bucket_name, s3_key)
except subprocess.CalledProcessError as e:
raise Exception(f"Git clone failed: {e.stderr.decode()}")
except Exception as e:
raise Exception(f"Error during process: {str(e)}")
finally:
# Clean up temp directory
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)