From 14ca1da1600b625f318dd7b1919ad4a179043c61 Mon Sep 17 00:00:00 2001 From: antux18 Date: Mon, 29 Jul 2024 15:17:22 +0200 Subject: [PATCH] Now handling the script's own crashes: saving to log and build status file (close #25). --- README.md | 1 + ecg.py | 77 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 497e32f..cde6bdf 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ The following are the possible results of the build: - `baseimage_unavailable`: The base image needed for this container is not available. - `artifact_unavailable`: The artifact could not be downloaded. - `dockerfile_not_found`: No Dockerfile has been found in the location specified in the configuration file. +- `script_crash`: An error has occurred with the script itself. - `unknown_error`: Any other error. ### Artifact hash log diff --git a/ecg.py b/ecg.py index 7e6747f..b0c0f9d 100755 --- a/ecg.py +++ b/ecg.py @@ -21,6 +21,7 @@ import logging import datetime import sys import string +import traceback def trim(url): """ @@ -375,7 +376,8 @@ def main(): description = "ECG is a program that automates software environment checking for scientific artifacts. " "It is meant to be executed periodically to analyze variations in the software environment of the artifact through time." ) - parser.add_argument('-v', '--verbose', + parser.add_argument( + '-v', '--verbose', action = 'store_true', help = "Shows more details on what is being done." ) @@ -409,7 +411,8 @@ def main(): "If not specified, cache is disabled.", required = False ), - parser.add_argument('--docker-cache', + parser.add_argument( + '--docker-cache', action = 'store_true', help = "Use cache for Docker 'build'." ) @@ -433,39 +436,47 @@ def main(): # Parsing the input file including the configuration of the artifact's # image: config_path = args.config - config_file = open(config_path, "r") - config = json.loads(config_file.read()) - # config = yaml.safe_load(config_file) - # print(config) - config_file.close() - - dl_dir = None - # If not using cache, creates a temporary directory: - if cache_dir == None: - tmp_dir = tempfile.TemporaryDirectory() - dl_dir = tmp_dir.name - else: - use_cache = True - dl_dir = cache_dir - artifact_dir = download_sources(config, arthashlog_path, dl_dir, use_cache) status = "" - # If download was successful: - if artifact_dir != "": - artifact_name = os.path.splitext(os.path.basename(config_path))[0] - return_code, build_output = build_image(config, artifact_dir, artifact_name, args.docker_cache) - status = "" - if return_code == 0: - status = "success" - check_env(config, artifact_dir, artifact_name, pkglist_path) - remove_image(config, artifact_name) + try: + config_file = open(config_path, "r") + config = json.loads(config_file.read()) + # config = yaml.safe_load(config_file) + # print(config) + config_file.close() + + dl_dir = None + # If not using cache, creates a temporary directory: + if cache_dir == None: + tmp_dir = tempfile.TemporaryDirectory() + dl_dir = tmp_dir.name else: - status = builderror_identifier(build_output) - # Creates file if not already: - pathlib.Path(pkglist_path).touch() - # If download failed, we need to save the error to the build status log: - else: - logging.fatal("Artifact could not be downloaded!") - status = "artifact_unavailable" + use_cache = True + dl_dir = cache_dir + artifact_dir = download_sources(config, arthashlog_path, dl_dir, use_cache) + # If download was successful: + if artifact_dir != "": + artifact_name = os.path.splitext(os.path.basename(config_path))[0] + return_code, build_output = build_image(config, artifact_dir, artifact_name, args.docker_cache) + if return_code == 0: + status = "success" + check_env(config, artifact_dir, artifact_name, pkglist_path) + remove_image(config, artifact_name) + else: + status = builderror_identifier(build_output) + # Creates file if not already: + pathlib.Path(pkglist_path).touch() + # If download failed, we need to save the error to the build status log: + else: + logging.fatal("Artifact could not be downloaded!") + status = "artifact_unavailable" + except Exception as err: + # Handles any possible script's own crashes: + formatted_err = str(''.join(traceback.format_exception(None, err, err.__traceback__))) + log_file = open(log_path, "a") + log_file.write(formatted_err) + log_file.close() + print(formatted_err) + status = "script_crash" buildresult_saver(status, buildstatus_path, config_path) if __name__ == "__main__":