diff --git a/planemo/commands/cmd_run.py b/planemo/commands/cmd_run.py index 5700a0768..da4161c31 100644 --- a/planemo/commands/cmd_run.py +++ b/planemo/commands/cmd_run.py @@ -28,6 +28,9 @@ @options.run_output_directory_option() @options.run_output_json_option() @options.run_download_outputs_option() +@options.run_upload_instance_url_option() +@options.run_upload_api_key_option() +@options.write_run_archive_to_file_option() @options.engine_options() @options.test_options() @command_function diff --git a/planemo/galaxy/activity.py b/planemo/galaxy/activity.py index 0eafdcffd..907b1a80e 100644 --- a/planemo/galaxy/activity.py +++ b/planemo/galaxy/activity.py @@ -1,6 +1,8 @@ """Module provides generic interface to running Galaxy tools and workflows.""" import os +import requests +import shutil import sys import tempfile import time @@ -42,7 +44,11 @@ ) from planemo.galaxy.api import summarize_history -from planemo.io import wait_on +from planemo.io import ( + error, + wait_on, + warn, +) from planemo.runnable import ( ErrorRunResponse, get_outputs, @@ -236,6 +242,47 @@ def _execute( # noqa C901 ctx.vlog("collecting outputs from run...") run_response.collect_outputs(output_directory) ctx.vlog("collecting outputs complete") + + if kwds.get("upload_instance_url") or kwds.get("archive_file"): + ctx.vlog(f"Preparing galaxy run export, history {history_id}.") + archive_file = kwds.get("archive_file") + + jeha_id = user_gi.histories.export_history( + history_id=history_id, + wait=True, + maxwait=3600, + ) + + with tempfile.TemporaryDirectory() as temp_dir: + archive_file_output = os.path.join(temp_dir, "archive.tar.gz") + + with open(archive_file_output, 'bw') as archive: + user_gi.histories.download_history( + history_id=history_id, + jeha_id=jeha_id, + outf=archive + ) + + if kwds.get("archive_file"): + shutil.copy(archive_file_output, archive_file) + ctx.vlog(f"Archive {kwds.get('arhicve_file')} created.") + + if kwds.get("upload_instance_url"): + upload_url = kwds.get("upload_instance_url", None) + upload_key = kwds.get("upload_api_key", None) + + upload_url = f"{upload_url}/api/histories" + if upload_key is None: + warn("No API key provided") + else: + upload_url = f"{upload_url}?key={upload_key}" + + response = requests.post(upload_url, files={'archive_file': open(archive_file_output, 'rb')}) + if response.status_code == 200: + ctx.vlog(f"Upload run to {kwds.get('upload_instance_url')}") + else: + error(f"Failed to upload run to {kwds.get('upload_instance_url')}, status code: {response.status_code}, error {response.text}") + return run_response diff --git a/planemo/options.py b/planemo/options.py index 3f3058569..a01a72432 100644 --- a/planemo/options.py +++ b/planemo/options.py @@ -314,6 +314,48 @@ def run_download_outputs_option(): ) +def run_upload_instance_url_option(): + return planemo_option( + "--upload_instance_url", + type=str, + default=None, + help=( + "Upload run to a galaxy instance located at the provided url." + "Ex: https://usegalaxy.org." + ), + ) + + +def run_upload_api_key_option(): + return planemo_option( + "--upload_api_key", + type=str, + default=None, + help=( + "API key used to upload run to separate instance" + ), + ) + + +def validate_archive_type_callback(ctx, param, value): + if value is not None and not value.endswith('.tar.gz'): + ctx.fail(f"archive_file ({value}), filename must end with tar.gz") + return value + + +def write_run_archive_to_file_option(): + return planemo_option( + "--archive_file", + type=click.Path(exists=False, file_okay=True, dir_okay=False, resolve_path=True), + default=None, + help=( + "Compress the run and write it to the provided file path." + "The archive can be imported to a Galaxy instance" + ), + callback=validate_archive_type_callback + ) + + def publish_dockstore_option(): return planemo_option( "--publish/--no_publish", diff --git a/tests/test_run.py b/tests/test_run.py index 51ff42271..a99d484de 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -6,6 +6,7 @@ CliTestCase, CWL_DRAFT3_DIR, mark, + run_verbosely, PROJECT_TEMPLATES_DIR, skip_if_environ, target_galaxy_branch, @@ -115,3 +116,24 @@ def test_run_output_directory(self): assert os.path.exists(output_path) with open(output_path) as fh: assert fh.read().startswith(" 16 198 1111") + + @skip_if_environ("PLANEMO_SKIP_GALAXY_TESTS") + def test_run_download_archived_history(self): + with self._isolate() as f: + archive_file = os.path.join(f, "demo.tar.gz") + cat = os.path.join(PROJECT_TEMPLATES_DIR, "demo", "cat.xml") + test_workflow = os.path.join(TEST_DATA_DIR, "wf2.ga") + test_job = os.path.join(TEST_DATA_DIR, "wf2-job.yml") + test_command = ["--verbose", "run"] if run_verbosely() else ["run"] + test_command += [ + "--no_dependency_resolution", + "--extra_tools", + cat, + test_workflow, + test_job, + "--archive_file", + archive_file, + ] + + self._check_exit_code(test_command, exit_code=0) + assert os.path.exists(archive_file), f"Archive file {archive_file} does not exist"