From 0f7549cd165b92a3319a168f53bb4cee1c443165 Mon Sep 17 00:00:00 2001 From: Adam Stankiewicz Date: Thu, 30 May 2024 17:45:11 -0400 Subject: [PATCH] feat: upload source maps to Datadog during MFE deploy --- tubular/scripts/frontend_utils.py | 38 +++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/tubular/scripts/frontend_utils.py b/tubular/scripts/frontend_utils.py index 64d61df5..2c7c2345 100755 --- a/tubular/scripts/frontend_utils.py +++ b/tubular/scripts/frontend_utils.py @@ -40,7 +40,7 @@ def __init__(self, common_config_file, env_config_file, app_name, version_file): self.common_cfg, self.env_cfg = self._get_configs() def _get_configs(self): - """Loads configs from their paths""" + """ Loads configs from their paths """ try: with io.open(self.common_config_file, 'r') as contents: common_vars = yaml.safe_load(contents) @@ -130,7 +130,7 @@ def get_npm_private_config(self): return list(set(npm_private_config)) def build_app(self, env_vars, fail_msg): - """ Builds the app with environment variable.""" + """ Builds the app with environment variable. """ proc = subprocess.Popen( ' '.join(env_vars + ['npm run build']), cwd=self.app_name, @@ -189,7 +189,7 @@ def __init__(self, env_config_file, app_name): self.env_cfg = self._get_config() def _get_config(self): - """Loads config from it's path""" + """ Loads config from its path """ try: with io.open(self.env_config_file, 'r') as contents: env_vars = yaml.safe_load(contents) @@ -197,8 +197,8 @@ def _get_config(self): self.FAIL(1, 'Environment config file {} could not be opened.'.format(self.env_config_file)) return env_vars - def deploy_site(self, bucket_name, app_path): - """Deploy files to bucket.""" + def _deploy_to_s3(self, bucket_name, app_path): + """ Deploy files to S3 bucket. """ bucket_uri = 's3://{}'.format(bucket_name) proc = subprocess.Popen( ' '.join(['aws s3 sync', app_path, bucket_uri, '--delete']), @@ -207,6 +207,34 @@ def deploy_site(self, bucket_name, app_path): return_code = proc.wait() if return_code != 0: self.FAIL(1, 'Could not sync app {} with S3 bucket {}.'.format(self.app_name, bucket_uri)) + + def _upload_js_sourcemaps(self, app_path): + """ Upload sourcemaps to Datadog. """ + head_commit_sha = LocalGitAPI(Repo(self.app_name)).get_head_sha() + # Prioritize app-specific version override, if any, before default commit SHA version + version = self.env_cfg.get('DATADOG_VERSION') or head_commit_sha + args = ' '.join([ + f'--service="{self.env_cfg.get('DATADOG_SERVICE')}"', + f'--release-version="{version}"' + '--minified-path-prefix="/"', # Sourcemaps are relative to the root when deployed + ]) + # TODO: ``DATADOG_API_KEY`` must be set as an environment variable before executing the following + # command. The Datadog documentation suggests using a dedicated Datadog API key: + # https://docs.datadoghq.com/real_user_monitoring/guide/upload-javascript-source-maps/ + proc = subprocess.Popen( + ' '.join(['datadog-ci sourcemaps upload', app_path, args]), + cwd=self.app_name, + shell=True, + ) + return_code = proc.wait() + if return_code != 0: + # If failure occurs, log the error and but don't fail the deployment. + self.LOG(1, 'Could not upload source maps to Datadog for app {}.'.format(self.app_name)) + + def deploy_site(self, bucket_name, app_path): + """ Deploy files to bucket. """ + self._deploy_to_s3(bucket_name, app_path) + self._upload_js_sourcemaps(app_path) self.LOG('Frontend application {} successfully deployed to {}.'.format(self.app_name, bucket_name)) @backoff.on_exception(backoff.expo,