def update_repository(repository_dir, git_url, revision="origin/master"): """Get the latest version of a revision or clone the repository""" should_clone = True if io.exists(repository_dir): # If the target directory already exists remote_url = None try: remote_url = get_remote_url(repository_dir) except Exception: # pylint: disable=broad-except # If the directory is not a git repository, `get_remote_url` will throw pass if remote_url == git_url: # If the remotes are the same, clean and fetch io.execute("git clean -dfx", repository_dir) io.execute("git fetch --all", repository_dir) # No need to clone should_clone = False else: # If the remotes mismatch, remove the old one io.remove(repository_dir) if should_clone: io.execute(f"git clone {git_url} {repository_dir}") io.execute(f"git reset --hard {revision}", repository_dir)
def test_remove_should_raise_if_failure(self, shutil_mock, os_mock): exception = OSError() shutil_mock.rmtree.side_effect = exception with self.assertRaises(OSError) as context: io.remove("path/to/remove") self.assertEqual(exception, context.exception) shutil_mock.rmtree.assert_called_once_with("path/to/remove") os_mock.remove.assert_not_called()
def non_blocking_clean(path: str, *, message_prefix: str = None): """Try to clean directory/file at path but don't raise an error if it fails (only log it).""" message = "Error trying to clean temporary directory / file" if message_prefix is not None: message = message_prefix.strip() + f" {message}" try: io.remove(path) # pylint: disable=broad-except except Exception as err: Logger.warn({"path": path, "err": str(err)}, message)
def write_and_deploy_configuration(cluster_name: str, yaml_config: str) -> None: """Write the kubernetes configuration into a local file and apply it on the cluster with the cli.""" output_directory = io.create_temporary_directory() yaml_path = os.path.join(output_directory, "config.yaml") try: io.write(yaml_path, yaml_config) cli.apply_config(cluster_name, yaml_path) finally: io.remove(output_directory)
def test_remove_directory_with_content(): fixtures_directory_path = Path(os.path.dirname(__file__), "..", "__fixtures__").resolve() destination_path = Path(os.path.dirname(__file__), "..", "__fixtures__copy").resolve() shutil.copytree(fixtures_directory_path, destination_path) assert os.path.isdir(destination_path) io.remove(destination_path) assert not os.path.isdir(destination_path)
def test_remove_single_file(): fixtures_directory_path = Path(os.path.dirname(__file__), "..", "__fixtures__", "example.yaml").resolve() destination_path = Path(os.path.dirname(__file__), "..", "__fixtures__", "example_copy.yaml").resolve() shutil.copyfile(fixtures_directory_path, destination_path) assert os.path.isfile(destination_path) io.remove(destination_path) assert not os.path.isfile(destination_path)
def test_remove_directory_with_content(self, shutil_mock, os_mock): shutil_mock.rmtree.side_effect = OSError(errno.ENOTDIR, "some reason") io.remove("path/to/remove") shutil_mock.rmtree.assert_called_once_with("path/to/remove") os_mock.remove.assert_called_once_with("path/to/remove")
def test_remove_single_file(self, shutil_mock, os_mock): io.remove("path/to/remove") shutil_mock.rmtree.assert_called_once_with("path/to/remove") os_mock.remove.assert_not_called()
def _differed_build(app_name: str): config_dir = None app_dir = None try: # Retrieve app's configuration config_dir = config.create_temporary_config_copy() config.change_environment(Configuration.get_config_default_branch(), config_dir) app_config = config.get_app_config(app_name, config_dir) Logger.debug( {"app": app_name, "config_directory": config_dir}, "[/api/builds/:app] Application's configuration retrieved", ) # Retrieve app's repository app_dir = git.create_working_repository(app_name, app_config["git"]["origin"]) git.branch(app_dir, app_config["workflow"][0]) Logger.debug( {"app": app_name, "working_directory": app_dir}, "[/api/builds/:app] Application's repository retrieved", ) try: # Create a new tag version = app.get_version(app_dir) git_tag = git.tag(app_dir, version) Logger.debug( {"app": app_name, "tag": git_tag}, "[/api/builds/:app] New tag created", ) except Exception as err: # The tag may already exist Logger.warn( {"app": app_name, "err": err}, "[/api/builds/:app] Error while tagging the app" ) # Build and publish the new docker image image_tag = docker.build(app_name, app_dir, app_config) Logger.debug( {"app": app_name, "image": image_tag}, "[/api/builds/:app] Docker image created" ) docker.push(app_name, image_tag, app_config) Logger.debug( {"app": app_name, "image": image_tag}, "[/api/builds/:app] Docker image published on registry", ) # Send the new tag to git git.push(app_dir) Logger.debug({"app": app_name}, "[/api/builds/:app] Tag pushed to Git") except Exception as err: Logger.error( {"app": app_name, "err": err}, "[/api/builds/:app] Error while tagging and building the app", ) # Clean up temporary directories try: if config_dir is not None: io.remove(config_dir) if app_dir is not None: io.remove(app_dir) except Exception as err: Logger.error({"app": app_name, "err": err}, "[/api/builds/:app] Error during cleanup")
def test_remove_should_raise_if_failure(): with pytest.raises(Exception): not_existing_path = Path(os.path.dirname(__file__), "..", "__abcdefg").resolve() io.remove(not_existing_path)
def init_workflow(organization, app): """Initialize the workflow of an application.""" Logger.info( {"app": app, "organization": organization}, "[/api/workflow/init/:org/:app] Workflow initialization started", ) report = None try: # Retrieve project configuration config_dir = config_lib.create_temporary_config_copy() config_lib.change_environment(Configuration.get_config_default_branch(), config_dir) project_config = config_lib.get_project_config(config_dir) git_provider = get_git_provider(project_config) report_status, report = workflow_lib.init_workflow(organization, app, git_provider) if report_status == workflow_lib.WorkflowInitStatus.FAIL: status = HTTPStatus.INTERNAL_SERVER_ERROR message = "Workflow initialization failed" elif report_status == workflow_lib.WorkflowInitStatus.SUCCESS: status = HTTPStatus.OK message = "Workflow initialization succeeded" else: raise ValueError(f"Unexpected status: '{report_status}'") # Clean the temporary directory try: io_lib.remove(config_dir) # pylint: disable=broad-except except Exception as err: Logger.warn( {"config_dir": config_dir, "err": err}, "Failed to clean temporary config dir" ) # HTTP Response Logger.info( {"organization": organization, "app": app, "report": report}, f"[/api/workflow/init/:org/:app] {message}", ) return ( {"organization": organization, "app": app, "report": report, "message": message}, status, ) # pylint: disable=broad-except except Exception as err: Logger.error( {"organization": organization, "app": app, "report": report, "err": str(err)}, "[/api/workflow/init/:org/:app] Workflow initialization failed", ) # HTTP Response return ( { "organization": organization, "app": app, "err": str(err), "message": "Workflow initialization failed", }, HTTPStatus.INTERNAL_SERVER_ERROR, )