From 24764cd89885b706a324035a224c7db8d42fac85 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Thu, 23 Feb 2017 16:23:21 -0500 Subject: [PATCH] Add functionality and documentation for building Conda pacakges. - Add documentation that links out to external sources for building Conda recipes - recommending specific docs and a specific order. - Allow Planemo to work with locally built Conda packages using the ``--conda_use_local`` command. - Add an exercise to the documentation that requires building a package and the use of ``--conda_use_local``. This uses a new project template that adds a tool targeting the package https://github.com/jmchilton/fleeqtk I forked from seqtk for this purpose. - Update galaxy-lib dependency for the required library functionality to use ``--conda_use_local``. - Add test case that follows the example in the documentation targeting the fleeqtk package. It builds a fleetqk recipe, uses conda_install --conda_use_local on a tool that requires it, and finally runs planemo test to ensure that Galaxy properly uses the resulting package. --- docs/_writing_dependencies_conda.rst | 78 ++++++++++++-- planemo/commands/cmd_conda_build.py | 21 ++++ planemo/commands/cmd_conda_init.py | 4 +- planemo/commands/cmd_conda_search.py | 4 +- planemo/conda.py | 4 + planemo/options.py | 11 +- .../exercise_1/.shed.yml | 0 .../exercise_1/pear.xml | 0 .../exercise_1/test-data/forward.fastq | 0 .../test-data/pear_assembled_results1.fastq | 0 .../pear_unassembled_forward_results1.fastq | 0 .../exercise_1/test-data/reverse.fastq | 0 .../exercise_1/tool_dependencies.xml | 0 .../exercise_2/fleeqtk_seq.xml | 99 +++++++++++++++++ .../exercise_2/test-data/2.fasta | 6 ++ .../exercise_2/test-data/2.fastq | 12 +++ requirements.txt | 2 +- tests/data/recipes/fleeqtk/build.sh | 8 ++ tests/data/recipes/fleeqtk/meta.yaml | 29 +++++ .../conda_exercises_fleeqtk/fleeqtk_seq.xml | 102 ++++++++++++++++++ .../conda_exercises_fleeqtk/test-data/2.fasta | 6 ++ .../conda_exercises_fleeqtk/test-data/2.fastq | 12 +++ tests/test_cmd_test_conda.py | 28 ++++- 23 files changed, 411 insertions(+), 15 deletions(-) create mode 100644 planemo/commands/cmd_conda_build.py rename project_templates/{conda_exercise => conda_exercises}/exercise_1/.shed.yml (100%) rename project_templates/{conda_exercise => conda_exercises}/exercise_1/pear.xml (100%) rename project_templates/{conda_exercise => conda_exercises}/exercise_1/test-data/forward.fastq (100%) rename project_templates/{conda_exercise => conda_exercises}/exercise_1/test-data/pear_assembled_results1.fastq (100%) rename project_templates/{conda_exercise => conda_exercises}/exercise_1/test-data/pear_unassembled_forward_results1.fastq (100%) rename project_templates/{conda_exercise => conda_exercises}/exercise_1/test-data/reverse.fastq (100%) rename project_templates/{conda_exercise => conda_exercises}/exercise_1/tool_dependencies.xml (100%) create mode 100644 project_templates/conda_exercises/exercise_2/fleeqtk_seq.xml create mode 100644 project_templates/conda_exercises/exercise_2/test-data/2.fasta create mode 100644 project_templates/conda_exercises/exercise_2/test-data/2.fastq create mode 100644 tests/data/recipes/fleeqtk/build.sh create mode 100644 tests/data/recipes/fleeqtk/meta.yaml create mode 100644 tests/data/repos/conda_exercises_fleeqtk/fleeqtk_seq.xml create mode 100644 tests/data/repos/conda_exercises_fleeqtk/test-data/2.fasta create mode 100644 tests/data/repos/conda_exercises_fleeqtk/test-data/2.fastq diff --git a/docs/_writing_dependencies_conda.rst b/docs/_writing_dependencies_conda.rst index 156e0c07b..c061ea04a 100644 --- a/docs/_writing_dependencies_conda.rst +++ b/docs/_writing_dependencies_conda.rst @@ -267,12 +267,13 @@ Use the ``project_init`` command to download this exercise. :: - $ planemo project_init --template conda_exercise conda_exercise - $ cd conda_exercise + $ planemo project_init --template conda_exercises conda_exercises + $ cd conda_exercises/exercise1 $ ls pear.xml test-data -This will download a tool for `PEAR - Paired-End reAd mergeR +This project template contains a few exercises. The first uses an adapted +version of an IUC tool for `PEAR - Paired-End reAd mergeR `__. This tool however has no ``requirement`` tags and so will not work properly. @@ -301,18 +302,79 @@ general Bioconda_ is usually the correct starting point. been accepted into Bioconda_ - including tools for image analysis, natural language processing, and cheminformatics. -At this time, the most relevant source for information on building Conda packages for Galaxy -is probably the Bioconda_ documentation - in particular check out the `contributing documentation -`__. +To get quickly learn to write Conda_ recipes for typical Galaxy tools, +please read the following pieces of external documentation. + +- `Contributing to Bioconda `__ in particular focusing on + + - `One time setup `__ + - `Contributing a recipe `__ (through "Write a Recipe") +- `Building conda packages `__ in particular + + - `Building conda packages with conda skeleton `__ (the best approach for common scripting languages such as R and Python) + - `Building conda packages from scratch `__ + - `Building conda packages for general code projects `__ + - `Using conda build `__ +- Then return to the Bioconda documentation and read + + - The rest of "Contributing a recipe" continuing from `Testing locally `__ + - And finally `Guidelines for bioconda recipes `__ + +These guidelines in particular can be skimmed depending on your recipe type, for +instance that document provides specific advice for: + +- `Python `__ +- `R (CRAN) `__ +- `R (Bioconductor) `__ +- `Perl `__ +- `C/C++ `__ + +To go a little deeper, you may want to read: + +- `Specification for meta.yaml `__ +- `Environment variables `__ +- `Custom channels `__ + +And finally to debug problems the `Bioconda troubleshooting `__ +documentation may prove useful. ---------------------------------------------------------------- Exercise - Build a Recipe ---------------------------------------------------------------- -1. Build a recipe for Bioconda. -2. Open a pull request to contribute it. +If you have just completed the exercise above - this exercise can be found in parent folder. Get +there with ``cd ../exercise2``. If not, the exercise can be downloaded with +:: + $ planemo project_init --template conda_exercises conda_exercises + $ cd conda_exercises/exercise2 + $ ls + fleeqtk_seq.xml test-data + +This is the skeleton of a tool wrapping the parody bioinformatics software package fleeqtk_. +fleeqtk is a fork of the project seqtk that many Planemo tutorials are built around and the +example tool ``fleeqtk_seq.xml`` should be fairly familiar. fleeqtk version 1.3 can be downloaded +from `here `__ and built using +``make``. The result of ``make`` includes a single executable ``fleeqtk``. + +1. Clone and branch Bioconda_. +2. Build a recipe for fleeqtk version 1.3. You may wish to use ``conda skeleton``, start from + scratch, or copy the recipe of seqtk and work from there - any of these strategies should work. +3. Use ``conda build`` or Bioconda tooling to build the recipe. +4. Run ``planemo conda_install --conda_use_local fleeqtk_seq.xml`` to verify the resulting package + can be built into a Galaxy environment. +5. Run ``planemo test fleeqtk_seq.xml`` to verify the resulting package works as expected. + +.. note: The planemo flag ``--conda_use_local`` causes planemo and Galaxy to use locally built + packages during dependency resolution and related commands. + +Congratulations on writing a Conda recipe and building a package. Upon succesfully building +and testing such a Bioconda package, you would normally push your branch to Github +and open a pull request. This step is skipped here as to not pollute Bioconda with unneeded +software packages. + +.. _fleeqtk: https://github.com/jmchilton/fleeqtk .. _Bioconda: https://github.com/bioconda/bioconda-recipes .. _Conda: https://conda.io/docs/ .. _Anaconda: https://anaconda.org/ diff --git a/planemo/commands/cmd_conda_build.py b/planemo/commands/cmd_conda_build.py new file mode 100644 index 000000000..3a9c66340 --- /dev/null +++ b/planemo/commands/cmd_conda_build.py @@ -0,0 +1,21 @@ +"""Module describing the planemo ``conda_build`` command.""" +from __future__ import print_function + +import click + +from planemo import options +from planemo.cli import command_function +from planemo.conda import build_conda_context + + +@click.command('conda_build') +@options.conda_target_options(include_local=False) # No reason to expose local, we have to use it. +@options.recipe_arg(multiple=True) +@command_function +def cli(ctx, paths, **kwds): + """Perform conda build with Planemo's conda.""" + # Force conda_use_local for building... + kwds["conda_use_local"] = True + conda_context = build_conda_context(ctx, handle_auto_init=True, **kwds) + build_args = list(paths) + conda_context.exec_command("build", build_args) diff --git a/planemo/commands/cmd_conda_init.py b/planemo/commands/cmd_conda_init.py index de960f2cf..a59d033d1 100644 --- a/planemo/commands/cmd_conda_init.py +++ b/planemo/commands/cmd_conda_init.py @@ -16,7 +16,7 @@ @click.command('conda_init') -@options.conda_target_options() +@options.conda_target_options(include_local=False) # Always use local during init. @command_function def cli(ctx, **kwds): """Download and install conda. @@ -36,7 +36,7 @@ def cli(ctx, **kwds): warn(MESSAGE_ERROR_ALREADY_EXISTS % conda_context.conda_exec) exit = EXIT_CODE_ALREADY_EXISTS else: - exit = conda_util.install_conda(conda_context=conda_context) + exit = conda_util.install_conda(conda_context=conda_context, force_conda_build=True) if exit: warn(MESSAGE_ERROR_FAILED % conda_context.conda_exec) else: diff --git a/planemo/commands/cmd_conda_search.py b/planemo/commands/cmd_conda_search.py index 36f19dd87..2003e39b5 100644 --- a/planemo/commands/cmd_conda_search.py +++ b/planemo/commands/cmd_conda_search.py @@ -9,7 +9,7 @@ @click.command('conda_search') -@options.conda_target_options() +@options.conda_target_options(include_local=False) @click.argument( "term", metavar="TERM", @@ -22,5 +22,5 @@ def cli(ctx, term, **kwds): Implicitly adds channels Planemo is configured with. """ - conda_context = build_conda_context(ctx, use_planemo_shell_exec=False, **kwds) + conda_context = build_conda_context(ctx, handle_auto_init=True, **kwds) conda_context.exec_command("search", [term]) diff --git a/planemo/conda.py b/planemo/conda.py index 72fb9a391..194c1be38 100644 --- a/planemo/conda.py +++ b/planemo/conda.py @@ -28,10 +28,12 @@ def build_conda_context(ctx, **kwds): use_planemo_shell = kwds.get("use_planemo_shell_exec", True) ensure_channels = kwds.get("conda_ensure_channels", "") condarc_override = kwds.get("condarc", condarc_override_default) + use_local = kwds.get("conda_use_local", False) shell_exec = shell if use_planemo_shell else None conda_context = conda_util.CondaContext(conda_prefix=conda_prefix, ensure_channels=ensure_channels, condarc_override=condarc_override, + use_local=use_local, shell_exec=shell_exec) handle_auto_init = kwds.get("handle_auto_init", False) if handle_auto_init and not conda_context.is_installed(): @@ -50,6 +52,8 @@ def build_conda_context(ctx, **kwds): if failed: raise ExitCodeException(EXIT_CODE_FAILED_DEPENDENCIES) + if handle_auto_init: + conda_context.ensure_conda_build_installed_if_needed() return conda_context diff --git a/planemo/options.py b/planemo/options.py index 44066178f..3736102e5 100644 --- a/planemo/options.py +++ b/planemo/options.py @@ -446,6 +446,14 @@ def conda_debug_option(): ) +def conda_use_local_option(): + return planemo_option( + "--conda_use_local", + is_flag=True, + help="Use locally built packages while building Conda environments." + ) + + def conda_ensure_channels_option(): return planemo_option( "conda_ensure_channels", @@ -874,12 +882,13 @@ def shed_target_options(): ) -def conda_target_options(): +def conda_target_options(include_local=True): return _compose( conda_prefix_option(), conda_exec_option(), conda_debug_option(), conda_ensure_channels_option(), + conda_use_local_option(), ) diff --git a/project_templates/conda_exercise/exercise_1/.shed.yml b/project_templates/conda_exercises/exercise_1/.shed.yml similarity index 100% rename from project_templates/conda_exercise/exercise_1/.shed.yml rename to project_templates/conda_exercises/exercise_1/.shed.yml diff --git a/project_templates/conda_exercise/exercise_1/pear.xml b/project_templates/conda_exercises/exercise_1/pear.xml similarity index 100% rename from project_templates/conda_exercise/exercise_1/pear.xml rename to project_templates/conda_exercises/exercise_1/pear.xml diff --git a/project_templates/conda_exercise/exercise_1/test-data/forward.fastq b/project_templates/conda_exercises/exercise_1/test-data/forward.fastq similarity index 100% rename from project_templates/conda_exercise/exercise_1/test-data/forward.fastq rename to project_templates/conda_exercises/exercise_1/test-data/forward.fastq diff --git a/project_templates/conda_exercise/exercise_1/test-data/pear_assembled_results1.fastq b/project_templates/conda_exercises/exercise_1/test-data/pear_assembled_results1.fastq similarity index 100% rename from project_templates/conda_exercise/exercise_1/test-data/pear_assembled_results1.fastq rename to project_templates/conda_exercises/exercise_1/test-data/pear_assembled_results1.fastq diff --git a/project_templates/conda_exercise/exercise_1/test-data/pear_unassembled_forward_results1.fastq b/project_templates/conda_exercises/exercise_1/test-data/pear_unassembled_forward_results1.fastq similarity index 100% rename from project_templates/conda_exercise/exercise_1/test-data/pear_unassembled_forward_results1.fastq rename to project_templates/conda_exercises/exercise_1/test-data/pear_unassembled_forward_results1.fastq diff --git a/project_templates/conda_exercise/exercise_1/test-data/reverse.fastq b/project_templates/conda_exercises/exercise_1/test-data/reverse.fastq similarity index 100% rename from project_templates/conda_exercise/exercise_1/test-data/reverse.fastq rename to project_templates/conda_exercises/exercise_1/test-data/reverse.fastq diff --git a/project_templates/conda_exercise/exercise_1/tool_dependencies.xml b/project_templates/conda_exercises/exercise_1/tool_dependencies.xml similarity index 100% rename from project_templates/conda_exercise/exercise_1/tool_dependencies.xml rename to project_templates/conda_exercises/exercise_1/tool_dependencies.xml diff --git a/project_templates/conda_exercises/exercise_2/fleeqtk_seq.xml b/project_templates/conda_exercises/exercise_2/fleeqtk_seq.xml new file mode 100644 index 000000000..cc5124613 --- /dev/null +++ b/project_templates/conda_exercises/exercise_2/fleeqtk_seq.xml @@ -0,0 +1,99 @@ + + + + + '$output1' + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | + +Options: -q INT mask bases with quality lower than INT [0] + -X INT mask bases with quality higher than INT [255] + -n CHAR masked bases converted to CHAR; 0 for lowercase [0] + -l INT number of residues per line; 0 for 2^32-1 [0] + -Q INT quality shift: ASCII-INT gives base quality [33] + -s INT random seed (effective with -f) [11] + -f FLOAT sample FLOAT fraction of sequences [1] + -M FILE mask regions in BED or name list FILE [null] + -L INT drop sequences with length shorter than INT [0] + -c mask complement region (effective with -M) + -r reverse complement + -A force FASTA output (discard quality) + -C drop comments at the header lines + -N drop sequences containing ambiguous bases + -1 output the 2n-1 reads only + -2 output the 2n reads only + -V shift quality by '(-Q) - 33' + -U convert all bases to uppercases + + + ]]> + + +@misc{githubfleeqtk, + author = {LastTODO, FirstTODO}, + year = {TODO}, + title = {fleeqtk}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/jmchilton/fleeqtk}, +} + + diff --git a/project_templates/conda_exercises/exercise_2/test-data/2.fasta b/project_templates/conda_exercises/exercise_2/test-data/2.fasta new file mode 100644 index 000000000..ec265d6ac --- /dev/null +++ b/project_templates/conda_exercises/exercise_2/test-data/2.fasta @@ -0,0 +1,6 @@ +>EAS54_6_R1_2_1_413_324 +CCCTTCTTGTCTTCAGCGTTTCTCC +>EAS54_6_R1_2_1_540_792 +TTGGCAGGCCAAGGCCGATGGATCA +>EAS54_6_R1_2_1_443_348 +GTTGCTTCTGGCGTGGGTGGGGGGG diff --git a/project_templates/conda_exercises/exercise_2/test-data/2.fastq b/project_templates/conda_exercises/exercise_2/test-data/2.fastq new file mode 100644 index 000000000..436c05ff2 --- /dev/null +++ b/project_templates/conda_exercises/exercise_2/test-data/2.fastq @@ -0,0 +1,12 @@ +@EAS54_6_R1_2_1_413_324 +CCCTTCTTGTCTTCAGCGTTTCTCC ++ +;;3;;;;;;;;;;;;7;;;;;;;88 +@EAS54_6_R1_2_1_540_792 +TTGGCAGGCCAAGGCCGATGGATCA ++ +;;;;;;;;;;;7;;;;;-;;;3;83 +@EAS54_6_R1_2_1_443_348 +GTTGCTTCTGGCGTGGGTGGGGGGG ++EAS54_6_R1_2_1_443_348 +;;;;;;;;;;;9;7;;.7;393333 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 13adaef67..27d1a3ee7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,6 +13,6 @@ virtualenv lxml gxformat2>=0.1.1 ephemeris>=0.2.0 -galaxy-lib>=17.5.2 +galaxy-lib>=17.5.5 html5lib>=0.9999999,!=0.99999999,!=0.999999999,!=1.0b10,!=1.0b09 ; python_version == '2.7' cwltool==1.0.20160726135535 ; python_version == '2.7' diff --git a/tests/data/recipes/fleeqtk/build.sh b/tests/data/recipes/fleeqtk/build.sh new file mode 100644 index 000000000..51bef4e89 --- /dev/null +++ b/tests/data/recipes/fleeqtk/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +export C_INCLUDE_PATH=${PREFIX}/include +export LIBRARY_PATH=${PREFIX}/lib + +make all +mkdir -p $PREFIX/bin +cp -f fleeqtk $PREFIX/bin/ diff --git a/tests/data/recipes/fleeqtk/meta.yaml b/tests/data/recipes/fleeqtk/meta.yaml new file mode 100644 index 000000000..9b3affba6 --- /dev/null +++ b/tests/data/recipes/fleeqtk/meta.yaml @@ -0,0 +1,29 @@ +package: + name: fleeqtk + version: 1.3 + +source: + fn: v1.3.tar.gz + url: https://github.com/jmchilton/fleeqtk/archive/v1.3.tar.gz + md5: 015daf2e21789519eea4e156fc155272 + +build: + number: 0 + +requirements: + build: + - gcc # [not osx] + - llvm # [osx] + - zlib + run: + - zlib + + +about: + home: https://github.com/jmchilton/fleeqtk + license: MIT License + summary: fleeqtk - those sequences are on fleeqtk + +test: + commands: + - fleeqtk seq diff --git a/tests/data/repos/conda_exercises_fleeqtk/fleeqtk_seq.xml b/tests/data/repos/conda_exercises_fleeqtk/fleeqtk_seq.xml new file mode 100644 index 000000000..6df899f82 --- /dev/null +++ b/tests/data/repos/conda_exercises_fleeqtk/fleeqtk_seq.xml @@ -0,0 +1,102 @@ + + + + + + fleeqtk + + '$output1' + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | + +Options: -q INT mask bases with quality lower than INT [0] + -X INT mask bases with quality higher than INT [255] + -n CHAR masked bases converted to CHAR; 0 for lowercase [0] + -l INT number of residues per line; 0 for 2^32-1 [0] + -Q INT quality shift: ASCII-INT gives base quality [33] + -s INT random seed (effective with -f) [11] + -f FLOAT sample FLOAT fraction of sequences [1] + -M FILE mask regions in BED or name list FILE [null] + -L INT drop sequences with length shorter than INT [0] + -c mask complement region (effective with -M) + -r reverse complement + -A force FASTA output (discard quality) + -C drop comments at the header lines + -N drop sequences containing ambiguous bases + -1 output the 2n-1 reads only + -2 output the 2n reads only + -V shift quality by '(-Q) - 33' + -U convert all bases to uppercases + + + ]]> + + +@misc{githubfleeqtk, + author = {LastTODO, FirstTODO}, + year = {TODO}, + title = {fleeqtk}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/jmchilton/fleeqtk}, +} + + diff --git a/tests/data/repos/conda_exercises_fleeqtk/test-data/2.fasta b/tests/data/repos/conda_exercises_fleeqtk/test-data/2.fasta new file mode 100644 index 000000000..ec265d6ac --- /dev/null +++ b/tests/data/repos/conda_exercises_fleeqtk/test-data/2.fasta @@ -0,0 +1,6 @@ +>EAS54_6_R1_2_1_413_324 +CCCTTCTTGTCTTCAGCGTTTCTCC +>EAS54_6_R1_2_1_540_792 +TTGGCAGGCCAAGGCCGATGGATCA +>EAS54_6_R1_2_1_443_348 +GTTGCTTCTGGCGTGGGTGGGGGGG diff --git a/tests/data/repos/conda_exercises_fleeqtk/test-data/2.fastq b/tests/data/repos/conda_exercises_fleeqtk/test-data/2.fastq new file mode 100644 index 000000000..436c05ff2 --- /dev/null +++ b/tests/data/repos/conda_exercises_fleeqtk/test-data/2.fastq @@ -0,0 +1,12 @@ +@EAS54_6_R1_2_1_413_324 +CCCTTCTTGTCTTCAGCGTTTCTCC ++ +;;3;;;;;;;;;;;;7;;;;;;;88 +@EAS54_6_R1_2_1_540_792 +TTGGCAGGCCAAGGCCGATGGATCA ++ +;;;;;;;;;;;7;;;;;-;;;3;83 +@EAS54_6_R1_2_1_443_348 +GTTGCTTCTGGCGTGGGTGGGGGGG ++EAS54_6_R1_2_1_443_348 +;;;;;;;;;;;9;7;;.7;393333 \ No newline at end of file diff --git a/tests/test_cmd_test_conda.py b/tests/test_cmd_test_conda.py index de9f8e22a..76471388c 100644 --- a/tests/test_cmd_test_conda.py +++ b/tests/test_cmd_test_conda.py @@ -5,6 +5,8 @@ CliTestCase, PROJECT_TEMPLATES_DIR, skip_if_environ, + TEST_RECIPES_DIR, + TEST_REPOS_DIR, TEST_TOOLS_DIR, ) @@ -82,7 +84,7 @@ def test_conda_dependencies_verify_branch_testing_properly(self): @skip_if_environ("PLANEMO_SKIP_GALAXY_TESTS") def test_conda_dependencies_version(self): - """Test testing a simple workflow with Galaxy.""" + """Test tool with wrong version and ensure it fails.""" with self._isolate(): # Try a failing test to ensure the primary test above isn't just passing spuriously. bwa_test = os.path.join(TEST_TOOLS_DIR, "bwa_wrong_version.xml") @@ -95,3 +97,27 @@ def test_conda_dependencies_version(self): bwa_test, ] self._check_exit_code(test_command, exit_code=1) + + @skip_if_environ("PLANEMO_SKIP_GALAXY_TESTS") + def test_local_conda_dependencies_version(self): + """Test a tool that requires local package builds.""" + with self._isolate(): + fleeqtk_recipe = os.path.join(TEST_RECIPES_DIR, "fleeqtk") + build_command = [ + "conda_build", + fleeqtk_recipe, + ] + self._check_exit_code(build_command) + fleeqtk_tool = os.path.join(TEST_REPOS_DIR, "conda_exercises_fleeqtk", "fleeqtk_seq.xml") + conda_install_command = [ + "conda_install", + "--conda_use_local", + fleeqtk_tool, + ] + self._check_exit_code(conda_install_command) + test_command = [ + "test", + "--galaxy_branch", "release_17.01", + fleeqtk_tool, + ] + self._check_exit_code(test_command)