diff --git a/install_and_test_tool_shed_repositories.sh b/install_and_test_tool_shed_repositories.sh deleted file mode 100644 index 7897d583a96..00000000000 --- a/install_and_test_tool_shed_repositories.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/sh - -# Enable verbose test errors for install and test framework. -GALAXY_TEST_VERBOSE_ERRORS="True" -export GALAXY_TEST_VERBOSE_ERRORS - -# A good place to look for nose info: http://somethingaboutorange.com/mrl/projects/nose/ - -# The test/install_and_test_tool_shed_repositories/functional_tests.py cannot be executed directly because it must -# have certain functional test definitions in sys.argv. Running it through this shell script is the best way to -# ensure that it has the required definitions. - -# This script requires setting of the following environment variables: -# GALAXY_INSTALL_TEST_TOOL_SHED_API_KEY - must be set to the API key for the tool shed that is being checked. -# GALAXY_INSTALL_TEST_TOOL_SHED_URL - must be set to a URL that the tool shed is listening on. - -# If the tool shed url is not specified in tool_sheds_conf.xml, GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF must be set to -# a tool sheds configuration file that does specify that url or repository installation will fail. - -# This script accepts the command line option -w to select which set of tests to run. The default behavior is to test -# first tool_dependency_definition repositories and then repositories with tools. Provide the value 'dependencies' -# to test only tool_dependency_definition repositories or 'tools' to test only repositories with tools. - -if [ -z $GALAXY_INSTALL_TEST_TOOL_SHED_API_KEY ] ; then - echo "This script requires the GALAXY_INSTALL_TEST_TOOL_SHED_API_KEY environment variable to be set and non-empty." - exit 1 -fi - -if [ -z $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR ] ; then - echo "This script requires the GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR environment variable to be set to your configured tool dependency path." - exit 1 -fi - -if [ -z $GALAXY_INSTALL_TEST_TOOL_SHED_URL ] ; then - echo "This script requires the GALAXY_INSTALL_TEST_TOOL_SHED_URL environment variable to be set and non-empty." - exit 1 -fi - -if [ -z "$GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF" ] ; then - if grep --quiet $GALAXY_INSTALL_TEST_TOOL_SHED_URL config/tool_sheds_conf.xml.sample; then - echo "Tool sheds configuration tool_sheds_conf.xml ok, proceeding." - else - echo "ERROR: Tool sheds configuration tool_sheds_conf.xml does not have an entry for $GALAXY_INSTALL_TEST_TOOL_SHED_URL." - exit 1 - fi -else - if grep --quiet $GALAXY_INSTALL_TEST_TOOL_SHED_URL $GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF; then - echo "Tool sheds configuration $GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF ok, proceeding." - else - echo "ERROR: Tool sheds configuration $GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF does not have an entry for $GALAXY_INSTALL_TEST_TOOL_SHED_URL" - exit 1 - fi -fi - -if [ -z $GALAXY_INSTALL_TEST_SHED_TOOL_PATH ] ; then - export GALAXY_INSTALL_TEST_SHED_TOOL_PATH='/tmp/shed_tools' -fi - -if [ ! -d $GALAXY_INSTALL_TEST_SHED_TOOL_PATH ] ; then - mkdir -p $GALAXY_INSTALL_TEST_SHED_TOOL_PATH -fi - -if [ ! -d $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR ] ; then - mkdir -p $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR -fi - -test_tool_dependency_definitions () { - # Test installation of repositories of type tool_dependency_definition. - if [ -f $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR/stage_1_complete ] ; then - rm $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR/stage_1_complete - fi - echo "Starting stage 1, tool dependency definitions." - python test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py $* -v --with-nosehtml --html-report-file \ - test/install_and_test_tool_shed_repositories/tool_dependency_definitions/run_functional_tests.html \ - test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py \ - test/functional/test_toolbox.py - echo "Stage 1 complete, exit code $?" - touch $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR/stage_1_complete -} - -test_repositories_with_tools () { - if [ ! -f $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR/stage_1_complete ] ; then - echo 'Stage 1 did not complete its run, exiting.' - exit 1 - fi - echo "Starting stage 2, repositories with tools." - # Test installation of repositories that contain valid tools with defined functional tests and a test-data directory containing test files. - python test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py $* -v --with-nosehtml --html-report-file \ - test/install_and_test_tool_shed_repositories/repositories_with_tools/run_functional_tests.html \ - test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py \ - test/functional/test_toolbox.py - echo "Stage 2 complete, exit code $?" - rm $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR/stage_1_complete -} - -which='both' - -while getopts "w:" arg; do - case $arg in - w) - which=$OPTARG - ;; - esac -done - -case $which in - # Use "-w tool_dependency_definitions" when you want to test repositories of type tool_dependency_definition. - tool_dependency_definitions) - test_tool_dependency_definitions - ;; - # Use "-w repositories_with_tools" parameter when you want to test repositories that contain tools. - repositories_with_tools) - touch $GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR/stage_1_complete - test_repositories_with_tools - ;; - # No received parameters or any received parameter not in [ tool_dependency_definitions, repositories_with_tools ] - # will execute both scripts. - *) - test_tool_dependency_definitions - test_repositories_with_tools - ;; -esac diff --git a/scripts/tool_shed/check_repositories_for_functional_tests.py b/scripts/tool_shed/check_repositories_for_functional_tests.py deleted file mode 100644 index 5759847d290..00000000000 --- a/scripts/tool_shed/check_repositories_for_functional_tests.py +++ /dev/null @@ -1,456 +0,0 @@ -#!/usr/bin/env python - -import ConfigParser -import logging -import os -import shutil -import sys -import tempfile -import time -from optparse import OptionParser -from time import strftime - -sys.path[1:1] = [ os.path.join( os.path.dirname( __file__ ), os.pardir, os.pardir ), - os.path.join( os.path.dirname( __file__ ), os.pardir, os.pardir, os.pardir, 'test' ) ] - -from mercurial import __version__ -from sqlalchemy import and_, false, true - -import galaxy.webapps.tool_shed.config as tool_shed_config -import tool_shed.util.shed_util_common as suc -from galaxy.util import listify -from install_and_test_tool_shed_repositories.base.util import get_database_version -from install_and_test_tool_shed_repositories.base.util import get_repository_current_revision -from install_and_test_tool_shed_repositories.base.util import RepositoryMetadataApplication -from tool_shed.util import hg_util - -log = logging.getLogger( 'check_repositories_for_functional_tests' ) -assert sys.version_info[ :2 ] >= ( 2, 6 ) - - -def check_and_update_repository_metadata( app, info_only=False, verbosity=1 ): - """ - This method will iterate through all records in the repository_metadata - table, checking each one for tool metadata, then checking the tool - metadata for tests. Each tool's metadata should look something like: - { - "add_to_tool_panel": true, - "description": "", - "guid": "toolshed.url:9009/repos/owner/name/tool_id/1.2.3", - "id": "tool_wrapper", - "name": "Map with Tool Wrapper", - "requirements": [], - "tests": [], - "tool_config": "database/community_files/000/repo_1/tool_wrapper.xml", - "tool_type": "default", - "version": "1.2.3", - "version_string_cmd": null - } - If the "tests" attribute is missing or empty, this script will mark the metadata record (which is specific to a changeset revision of a repository) - not to be tested. If each "tools" attribute has at least one valid "tests" entry, this script will do nothing, and leave it available for the install - and test repositories script to process. If the tested changeset revision does not have a test-data directory, this script will also mark the revision - not to be tested. - """ - start = time.time() - skip_metadata_ids = [] - checked_repository_ids = [] - tool_count = 0 - has_tests = 0 - no_tests = 0 - valid_revisions = 0 - invalid_revisions = 0 - records_checked = 0 - # Do not check metadata records that have an entry in the skip_tool_tests table, since they won't be tested anyway. - print '# -------------------------------------------------------------------------------------------' - print '# The skip_tool_test setting has been set for the following repository revision, so they will not be tested.' - skip_metadata_ids = [] - for skip_tool_test in app.sa_session.query( app.model.SkipToolTest ): - print '# repository_metadata_id: %s, changeset_revision: %s' % \ - ( str( skip_tool_test.repository_metadata_id ), str( skip_tool_test.initial_changeset_revision ) ) - print 'reason: %s' % str( skip_tool_test.comment ) - skip_metadata_ids.append( skip_tool_test.repository_metadata_id ) - # Get the list of metadata records to check for functional tests and test data. Limit this to records that have not been flagged do_not_test, - # since there's no need to check them again if they won't be tested anyway. Also filter out changeset revisions that are not downloadable, - # because it's redundant to test a revision that a user can't install. - for repository_metadata in app.sa_session.query( app.model.RepositoryMetadata ) \ - .filter( and_( app.model.RepositoryMetadata.table.c.downloadable == true(), - app.model.RepositoryMetadata.table.c.includes_tools == true(), - app.model.RepositoryMetadata.table.c.do_not_test == false() ) ): - # Initialize some items. - missing_test_components = [] - revision_has_test_data = False - testable_revision = False - repository = repository_metadata.repository - records_checked += 1 - # Check the next repository revision. - changeset_revision = str( repository_metadata.changeset_revision ) - name = repository.name - owner = repository.user.username - metadata = repository_metadata.metadata - repository = repository_metadata.repository - if repository.id not in checked_repository_ids: - checked_repository_ids.append( repository.id ) - print '# -------------------------------------------------------------------------------------------' - print '# Checking revision %s of %s owned by %s.' % ( changeset_revision, name, owner ) - if repository_metadata.id in skip_metadata_ids: - print'# Skipping revision %s of %s owned by %s because the skip_tool_test setting has been set.' % ( changeset_revision, name, owner ) - continue - # If this changeset revision has no tools, we don't need to do anything here, the install and test script has a filter for returning - # only repositories that contain tools. - tool_dicts = metadata.get( 'tools', None ) - if tool_dicts is not None: - # Clone the repository up to the changeset revision we're checking. - repo_dir = repository.repo_path( app ) - hg_util.get_repo_for_repository( app, repository=None, repo_path=repo_dir, create=False ) - work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-cafr" ) - cloned_ok, error_message = hg_util.clone_repository( repo_dir, work_dir, changeset_revision ) - if cloned_ok: - # Iterate through all the directories in the cloned changeset revision and determine whether there's a - # directory named test-data. If this directory is not present update the metadata record for the changeset - # revision we're checking. - for root, dirs, files in os.walk( work_dir ): - if '.hg' in dirs: - dirs.remove( '.hg' ) - if 'test-data' in dirs: - revision_has_test_data = True - test_data_path = os.path.join( root, dirs[ dirs.index( 'test-data' ) ] ) - break - if revision_has_test_data: - print '# Test data directory found in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) - else: - print '# Test data directory missing in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) - print '# Checking for functional tests in changeset revision %s of %s, owned by %s.' % \ - ( changeset_revision, name, owner ) - # Inspect each tool_dict for defined functional tests. If there - # are no tests, this tool should not be tested, since the tool - # functional tests only report failure if the test itself fails, - # not if it's missing or undefined. Filtering out those - # repositories at this step will reduce the number of "false - # negatives" the automated functional test framework produces. - for tool_dict in tool_dicts: - failure_reason = '' - problem_found = False - tool_has_defined_tests = False - tool_has_test_files = False - missing_test_files = [] - tool_count += 1 - tool_id = tool_dict[ 'id' ] - tool_version = tool_dict[ 'version' ] - tool_guid = tool_dict[ 'guid' ] - if verbosity >= 1: - print "# Checking tool ID '%s' in changeset revision %s of %s." % ( tool_id, changeset_revision, name ) - defined_test_dicts = tool_dict.get( 'tests', None ) - if defined_test_dicts is not None: - # We need to inspect the tags because the following tags... - # - # - # ...will produce the following metadata: - # "tests": [] - # And the following tags... - # - # - # - # - # ...will produce the following metadata: - # "tests": - # [{"inputs": [], "name": "Test-1", "outputs": [], "required_files": []}] - for defined_test_dict in defined_test_dicts: - inputs = defined_test_dict.get( 'inputs', [] ) - outputs = defined_test_dict.get( 'outputs', [] ) - if inputs and outputs: - # At least one tool within the repository has a valid tag. - tool_has_defined_tests = True - break - if tool_has_defined_tests: - print "# Tool ID '%s' in changeset revision %s of %s has one or more valid functional tests defined." % \ - ( tool_id, changeset_revision, name ) - has_tests += 1 - else: - print '# No functional tests defined for %s.' % tool_id - no_tests += 1 - if tool_has_defined_tests and revision_has_test_data: - missing_test_files = check_for_missing_test_files( defined_test_dicts, test_data_path ) - if missing_test_files: - print "# Tool id '%s' in changeset revision %s of %s is missing one or more required test files: %s" % \ - ( tool_id, changeset_revision, name, ', '.join( missing_test_files ) ) - else: - tool_has_test_files = True - if not revision_has_test_data: - failure_reason += 'Repository does not have a test-data directory. ' - problem_found = True - if not tool_has_defined_tests: - failure_reason += 'Functional test definitions missing for %s. ' % tool_id - problem_found = True - if missing_test_files: - failure_reason += 'One or more test files are missing for tool %s: %s' % ( tool_id, ', '.join( missing_test_files ) ) - problem_found = True - test_errors = dict( tool_id=tool_id, tool_version=tool_version, tool_guid=tool_guid, missing_components=failure_reason ) - # Only append this error dict if it hasn't already been added. - if problem_found: - if test_errors not in missing_test_components: - missing_test_components.append( test_errors ) - if tool_has_defined_tests and tool_has_test_files: - print '# Revision %s of %s owned by %s is a testable revision.' % ( changeset_revision, name, owner ) - testable_revision = True - # Remove the cloned repository path. This has to be done after the check for required test files, for obvious reasons. - if os.path.exists( work_dir ): - shutil.rmtree( work_dir ) - if not missing_test_components: - valid_revisions += 1 - print '# All tools have functional tests in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) - else: - invalid_revisions += 1 - print '# Some tools have problematic functional tests in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) - if verbosity >= 1: - for missing_test_component in missing_test_components: - if 'missing_components' in missing_test_component: - print '# %s' % missing_test_component[ 'missing_components' ] - if not info_only: - # Get or create the list of tool_test_results dictionaries. - if repository_metadata.tool_test_results is not None: - # We'll listify the column value in case it uses the old approach of storing the results of only a single test run. - tool_test_results_dicts = listify( repository_metadata.tool_test_results ) - else: - tool_test_results_dicts = [] - if tool_test_results_dicts: - # Inspect the tool_test_results_dict for the last test run in case it contains only a test_environment - # entry. This will occur with multiple runs of this script without running the associated - # install_and_test_tool_sed_repositories.sh script which will further populate the tool_test_results_dict. - tool_test_results_dict = tool_test_results_dicts[ 0 ] - if len( tool_test_results_dict ) <= 1: - # We can re-use the mostly empty tool_test_results_dict for this run because it is either empty or it contains only - # a test_environment entry. If we use it we need to temporarily eliminate it from the list of tool_test_results_dicts - # since it will be re-inserted later. - tool_test_results_dict = tool_test_results_dicts.pop( 0 ) - elif (len( tool_test_results_dict ) == 2 and - 'test_environment' in tool_test_results_dict and 'missing_test_components' in tool_test_results_dict): - # We can re-use tool_test_results_dict if its only entries are "test_environment" and "missing_test_components". - # In this case, some tools are missing tests components while others are not. - tool_test_results_dict = tool_test_results_dicts.pop( 0 ) - else: - # The latest tool_test_results_dict has been populated with the results of a test run, so it cannot be used. - tool_test_results_dict = {} - else: - # Create a new dictionary for the most recent test run. - tool_test_results_dict = {} - test_environment_dict = tool_test_results_dict.get( 'test_environment', {} ) - # Add the current time as the approximate time that this test run occurs. A similar value will also be - # set to the repository_metadata.time_last_tested column, but we also store it here because the Tool Shed - # may be configured to store multiple test run results, so each must be associated with a time stamp. - now = time.strftime( "%Y-%m-%d %H:%M:%S" ) - test_environment_dict[ 'time_tested' ] = now - test_environment_dict[ 'tool_shed_database_version' ] = get_database_version( app ) - test_environment_dict[ 'tool_shed_mercurial_version' ] = __version__.version - test_environment_dict[ 'tool_shed_revision' ] = get_repository_current_revision( os.getcwd() ) - tool_test_results_dict[ 'test_environment' ] = test_environment_dict - # The repository_metadata.time_last_tested column is not changed by this script since no testing is performed here. - if missing_test_components: - # If functional test definitions or test data are missing, set do_not_test = True if no tool with valid tests has been - # found in this revision, and: - # a) There are multiple downloadable revisions, and the revision being tested is not the most recent downloadable revision. - # In this case, the revision will never be updated with the missing components, and re-testing it would be redundant. - # b) There are one or more downloadable revisions, and the provided changeset revision is the most recent downloadable - # revision. In this case, if the repository is updated with test data or functional tests, the downloadable - # changeset revision that was tested will either be replaced with the new changeset revision, or a new downloadable - # changeset revision will be created, either of which will be automatically checked and flagged as appropriate. - # In the install and test script, this behavior is slightly different, since we do want to always run functional - # tests on the most recent downloadable changeset revision. - if should_set_do_not_test_flag( app, repository, changeset_revision, testable_revision ): - print "# Setting do_not_test to True on revision %s of %s owned by %s because it is missing test components" % ( - changeset_revision, name, owner - ) - print "# and it is not the latest downloadable revision." - repository_metadata.do_not_test = True - if not testable_revision: - # Even though some tools may be missing test components, it may be possible to test other tools. Since the - # install and test framework filters out repositories marked as missing test components, we'll set it only if - # no tools can be tested. - print '# Setting missing_test_components to True for revision %s of %s owned by %s because all tools are missing test components.' % ( - changeset_revision, name, owner - ) - repository_metadata.missing_test_components = True - print "# Setting tools_functionally_correct to False on revision %s of %s owned by %s because it is missing test components" % ( - changeset_revision, name, owner - ) - repository_metadata.tools_functionally_correct = False - tool_test_results_dict[ 'missing_test_components' ] = missing_test_components - # Store only the configured number of test runs. - num_tool_test_results_saved = int( app.config.num_tool_test_results_saved ) - if len( tool_test_results_dicts ) >= num_tool_test_results_saved: - test_results_index = num_tool_test_results_saved - 1 - new_tool_test_results_dicts = tool_test_results_dicts[ :test_results_index ] - else: - new_tool_test_results_dicts = [ d for d in tool_test_results_dicts ] - # Insert the new element into the first position in the list. - new_tool_test_results_dicts.insert( 0, tool_test_results_dict ) - repository_metadata.tool_test_results = new_tool_test_results_dicts - app.sa_session.add( repository_metadata ) - app.sa_session.flush() - stop = time.time() - print '# -------------------------------------------------------------------------------------------' - print '# Checked %d repositories with %d tools in %d changeset revisions.' % ( len( checked_repository_ids ), tool_count, records_checked ) - print '# %d revisions found with functional tests and test data for all tools.' % valid_revisions - print '# %d revisions found with one or more tools missing functional tests and/or test data.' % invalid_revisions - print '# Found %d tools without functional tests.' % no_tests - print '# Found %d tools with functional tests.' % has_tests - if info_only: - print '# Database not updated, info_only set.' - print "# Elapsed time: ", stop - start - print "#############################################################################" - - -def check_for_missing_test_files( test_definition, test_data_path ): - '''Process the tool's functional test definitions and check for each file specified as an input or output.''' - missing_test_files = [] - required_test_files = [] - for test_dict in test_definition: - for required_file in test_dict[ 'required_files' ]: - if required_file not in required_test_files: - required_test_files.append( required_file ) - # Make sure each specified file actually does exist in the test data path of the cloned repository. - for required_file in required_test_files: - required_file_full_path = os.path.join( test_data_path, required_file ) - if not os.path.exists( required_file_full_path ): - missing_test_files.append( required_file ) - return missing_test_files - - -def main(): - '''Script that checks repositories to see if the tools contained within them have functional tests defined.''' - parser = OptionParser() - parser.add_option( "-i", "--info_only", action="store_true", dest="info_only", help="info about the requested action", default=False ) - parser.add_option( "-s", "--section", action="store", dest="section", default='server:main', - help=".ini file section from which to to extract the host and port" ) - parser.add_option( "-v", "--verbose", action="count", dest="verbosity", default=1, help="Control the amount of detail in the log output.") - parser.add_option( "--verbosity", action="store", dest="verbosity", metavar='VERBOSITY', type="int", - help="Control the amount of detail in the log output. --verbosity=1 is the same as -v" ) - ( options, args ) = parser.parse_args() - try: - ini_file = args[ 0 ] - except IndexError: - print "Usage: python %s [options]" % sys.argv[ 0 ] - sys.exit( 127 ) - config_parser = ConfigParser.ConfigParser( { 'here': os.getcwd() } ) - config_parser.read( ini_file ) - config_dict = {} - for key, value in config_parser.items( "app:main" ): - config_dict[ key ] = value - config = tool_shed_config.Configuration( **config_dict ) - config_section = options.section - now = strftime( "%Y-%m-%d %H:%M:%S" ) - - print "#############################################################################" - print "# %s - Checking repositories for tools with functional tests." % now - print "# This tool shed is configured to listen on %s:%s." % ( config_parser.get( config_section, 'host' ), - config_parser.get( config_section, 'port' ) ) - app = RepositoryMetadataApplication( config ) - if options.info_only: - print "# Displaying info only ( --info_only )" - if options.verbosity: - print "# Displaying extra information ( --verbosity = %d )" % options.verbosity - check_and_update_repository_metadata( app, info_only=options.info_only, verbosity=options.verbosity ) - - -def should_set_do_not_test_flag( app, repository, changeset_revision, testable_revision ): - """ - The received testable_revision is True if the tool has defined tests and test files are in the repository - This method returns True if the received repository has multiple downloadable revisions and the received - changeset_revision is not the most recent downloadable revision and the received testable_revision is False. - In this case, the received changeset_revision will never be updated with correct data, and re-testing it - would be redundant. - """ - if not testable_revision: - repo = hg_util.get_repo_for_repository( app, repository=repository, repo_path=None, create=False ) - changeset_revisions = [ revision[ 1 ] for revision in suc.get_metadata_revisions( repository, repo ) ] - if len( changeset_revisions ) > 1: - latest_downloadable_revision = changeset_revisions[ -1 ] - if changeset_revision != latest_downloadable_revision: - return True - return False - -if __name__ == "__main__": - # The repository_metadata.tool_test_results json value should have the following list structure: - # [ - # { - # "test_environment": - # { - # "galaxy_revision": "9001:abcd1234", - # "galaxy_database_version": "114", - # "tool_shed_revision": "9001:abcd1234", - # "tool_shed_mercurial_version": "2.3.1", - # "tool_shed_database_version": "17", - # "python_version": "2.7.2", - # "architecture": "x86_64", - # "system": "Darwin 12.2.0" - # }, - # "passed_tests": - # [ - # { - # "test_id": "The test ID, generated by twill", - # "tool_id": "The tool ID that was tested", - # "tool_version": "The tool version that was tested", - # }, - # ] - # "failed_tests": - # [ - # { - # "test_id": "The test ID, generated by twill", - # "tool_id": "The tool ID that was tested", - # "tool_version": "The tool version that was tested", - # "stderr": "The output of the test, or a more detailed description of what was tested and what the outcome was." - # "traceback": "The captured traceback." - # }, - # ] - # "installation_errors": - # { - # 'tool_dependencies': - # [ - # { - # 'type': 'Type of tool dependency, e.g. package, set_environment, etc.', - # 'name': 'Name of the tool dependency.', - # 'version': 'Version if this is a package, otherwise blank.', - # 'error_message': 'The error message returned when installation was attempted.', - # }, - # ], - # 'repository_dependencies': - # [ - # { - # 'tool_shed': 'The tool shed that this repository was installed from.', - # 'name': 'The name of the repository that failed to install.', - # 'owner': 'Owner of the failed repository.', - # 'changeset_revision': 'Changeset revision of the failed repository.', - # 'error_message': 'The error message that was returned when the repository failed to install.', - # }, - # ], - # 'current_repository': - # [ - # { - # 'tool_shed': 'The tool shed that this repository was installed from.', - # 'name': 'The name of the repository that failed to install.', - # 'owner': 'Owner of the failed repository.', - # 'changeset_revision': 'Changeset revision of the failed repository.', - # 'error_message': 'The error message that was returned when the repository failed to install.', - # }, - # ], - # { - # "name": "The name of the repository.", - # "owner": "The owner of the repository.", - # "changeset_revision": "The changeset revision of the repository.", - # "error_message": "The message stored in tool_dependency.error_message." - # }, - # } - # "missing_test_components": - # [ - # { - # "tool_id": "The tool ID that missing components.", - # "tool_version": "The version of the tool." - # "tool_guid": "The guid of the tool." - # "missing_components": "Which components are missing, e.g. the test data filename, or the test-data directory." - # }, - # ] - # } - # ] - # - # Optionally, "traceback" may be included in a test_errors dict, if it is relevant. No script should overwrite anything other - # than the list relevant to what it is testing. - main() diff --git a/scripts/tool_shed/check_tool_dependency_definition_repositories.py b/scripts/tool_shed/check_tool_dependency_definition_repositories.py deleted file mode 100644 index 94352fb1bca..00000000000 --- a/scripts/tool_shed/check_tool_dependency_definition_repositories.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python - -import ConfigParser -import logging -import os -import sys -import time -from optparse import OptionParser -from time import strftime - -sys.path[1:1] = [ os.path.join( os.path.dirname( __file__ ), os.pardir, os.pardir ), - os.path.join( os.path.dirname( __file__ ), os.pardir, os.pardir, os.pardir, 'test' ) ] - -from mercurial import __version__ -from sqlalchemy import and_, false, not_, select, true - -import galaxy.webapps.tool_shed.config as tool_shed_config - -from galaxy.util import listify -from install_and_test_tool_shed_repositories.base.util import get_database_version -from install_and_test_tool_shed_repositories.base.util import get_repository_current_revision -from install_and_test_tool_shed_repositories.base.util import RepositoryMetadataApplication -from tool_shed.repository_types.util import TOOL_DEPENDENCY_DEFINITION - -log = logging.getLogger() -log.setLevel( 10 ) -log.addHandler( logging.StreamHandler( sys.stdout ) ) - -assert sys.version_info[ :2 ] >= ( 2, 6 ) - - -def main(): - '''Script that validates all repositories of type tool_dependency_definition.''' - parser = OptionParser() - parser.add_option( "-i", "--info_only", action="store_true", dest="info_only", help="info about the requested action", default=False ) - parser.add_option( "-s", "--section", action="store", dest="section", default='server:main', - help=".ini file section from which to extract the host and port" ) - parser.add_option( "-v", "--verbose", action="count", dest="verbosity", default=1, help="Control the amount of detail in the log output." ) - parser.add_option( "--verbosity", action="store", dest="verbosity", metavar='VERBOSITY', type="int", - help="Control the amount of detail in the log output, --verbosity=1 is the same as -v" ) - ( options, args ) = parser.parse_args() - try: - ini_file = args[ 0 ] - except IndexError: - print "Usage: python %s [options]" % sys.argv[ 0 ] - sys.exit( 127 ) - config_parser = ConfigParser.ConfigParser( { 'here': os.getcwd() } ) - config_parser.read( ini_file ) - config_dict = {} - for key, value in config_parser.items( "app:main" ): - config_dict[ key ] = value - config = tool_shed_config.Configuration( **config_dict ) - config_section = options.section - - now = strftime( "%Y-%m-%d %H:%M:%S" ) - print "#############################################################################" - print "# %s - Validating repositories of type %s" % ( now, TOOL_DEPENDENCY_DEFINITION ) - print "# This tool shed is configured to listen on %s:%s" % ( config_parser.get( config_section, 'host' ), - config_parser.get( config_section, 'port' ) ) - - app = RepositoryMetadataApplication( config ) - if options.info_only: - print "# Displaying info only ( --info_only )" - if options.verbosity: - print "# Displaying extra information ( --verbosity = %d )" % options.verbosity - validate_repositories( app, info_only=options.info_only, verbosity=options.verbosity ) - - -def validate_repositories( app, info_only=False, verbosity=1 ): - """ - Inspect records in the repository_metadata table that are associated with repositories of type TOOL_DEPENDENCY_DEFINITION - to ensure they are valid and set the repository_metadata.do_not_test column value to True if the metadata is invalid. - Each repository's metadata should look something like: - "{"tool_dependencies": - {"libpng/1.2.5": {"name": "libpng", - "readme": "README content", - "type": "package", - "version": "1.2.5"}}}" - or: - "{"repository_dependencies": - {"description": null, - "repository_dependencies": - [["http://localhost:9009", "package_libpng_1_2", "iuc", "5788512d4c0a", "True", "False"]]}, - "tool_dependencies": - {"libgd/2.1.0": - {"name": "libgd", "readme": "text"}, - "libpng/1.2.5": - {"name": "libpng", "type": "package", "version": "1.2.5"}}}" - """ - invalid_metadata = 0 - records_checked = 0 - skip_metadata_ids = [] - start = time.time() - valid_metadata = 0 - # Restrict testing to repositories of type TOOL_DEPENDENCY_DEFINITION - tool_dependency_defintion_repository_ids = [] - for repository in app.sa_session.query( app.model.Repository ) \ - .filter( and_( app.model.Repository.table.c.deleted == false(), - app.model.Repository.table.c.type == TOOL_DEPENDENCY_DEFINITION ) ): - tool_dependency_defintion_repository_ids.append( repository.id ) - # Do not check metadata records that have an entry in the skip_tool_tests table, since they won't be tested anyway. - skip_metadata_ids = select( [ app.model.SkipToolTest.table.c.repository_metadata_id ] ) - # Get the list of metadata records to check, restricting it to records that have not been flagged do_not_test. - for repository_metadata in \ - app.sa_session.query( app.model.RepositoryMetadata ) \ - .filter( and_( app.model.RepositoryMetadata.table.c.downloadable == true(), - app.model.RepositoryMetadata.table.c.do_not_test == false(), - app.model.RepositoryMetadata.table.c.repository_id.in_( tool_dependency_defintion_repository_ids ), - not_( app.model.RepositoryMetadata.table.c.id.in_( skip_metadata_ids ) ) ) ): - records_checked += 1 - # Check the next repository revision. - changeset_revision = str( repository_metadata.changeset_revision ) - name = repository.name - owner = repository.user.username - metadata = repository_metadata.metadata - repository = repository_metadata.repository - if verbosity >= 1: - print '# -------------------------------------------------------------------------------------------' - print '# Checking revision %s of %s owned by %s.' % ( changeset_revision, name, owner ) - if metadata: - # Valid metadata will undoubtedly have a tool_dependencies entry or repository_dependencies entry. - repository_dependencies = metadata.get( 'repository_dependencies', None ) - tool_dependencies = metadata.get( 'tool_dependencies', None ) - if repository_dependencies or tool_dependencies: - print 'Revision %s of %s owned by %s has valid metadata.' % ( changeset_revision, name, owner ) - valid_metadata += 1 - else: - if verbosity >= 1: - print 'Revision %s of %s owned by %s has invalid metadata.' % ( changeset_revision, name, owner ) - invalid_metadata += 1 - if not info_only: - # Create the tool_test_results_dict dictionary, using the dictionary from the previous test run if available. - if repository_metadata.tool_test_results is not None: - # We'll listify the column value in case it uses the old approach of storing the results of only a single test run. - tool_test_results_dicts = listify( repository_metadata.tool_test_results ) - else: - tool_test_results_dicts = [] - if tool_test_results_dicts: - # Inspect the tool_test_results_dict for the last test run in case it contains only a test_environment - # entry. This will occur with multiple runs of this script without running the associated - # install_and_test_tool_sed_repositories.sh script which will further populate the tool_test_results_dict. - tool_test_results_dict = tool_test_results_dicts[ 0 ] - if len( tool_test_results_dict ) <= 1: - # We can re-use the mostly empty tool_test_results_dict for this run because it is either empty or it contains only - # a test_environment entry. If we use it we need to temporarily eliminate it from the list of tool_test_results_dicts - # since it will be re-inserted later. - tool_test_results_dict = tool_test_results_dicts.pop( 0 ) - elif len( tool_test_results_dict ) == 2 and \ - 'test_environment' in tool_test_results_dict and \ - 'missing_test_components' in tool_test_results_dict: - # We can re-use tool_test_results_dict if its only entries are "test_environment" and "missing_test_components". - # In this case, some tools are missing tests components while others are not. - tool_test_results_dict = tool_test_results_dicts.pop( 0 ) - else: - # The latest tool_test_results_dict has been populated with the results of a test run, so it cannot be used. - tool_test_results_dict = {} - else: - # Create a new dictionary for the most recent test run. - tool_test_results_dict = {} - # Initialize the tool_test_results_dict dictionary with the information about the current test environment. - test_environment_dict = tool_test_results_dict.get( 'test_environment', {} ) - test_environment_dict[ 'tool_shed_database_version' ] = get_database_version( app ) - test_environment_dict[ 'tool_shed_mercurial_version' ] = __version__.version - test_environment_dict[ 'tool_shed_revision' ] = get_repository_current_revision( os.getcwd() ) - tool_test_results_dict[ 'test_environment' ] = test_environment_dict - # Store only the configured number of test runs. - num_tool_test_results_saved = int( app.config.num_tool_test_results_saved ) - if len( tool_test_results_dicts ) >= num_tool_test_results_saved: - test_results_index = num_tool_test_results_saved - 1 - new_tool_test_results_dicts = tool_test_results_dicts[ :test_results_index ] - else: - new_tool_test_results_dicts = [ d for d in tool_test_results_dicts ] - # Insert the new element into the first position in the list. - new_tool_test_results_dicts.insert( 0, tool_test_results_dict ) - repository_metadata.tool_test_results = new_tool_test_results_dicts - app.sa_session.add( repository_metadata ) - app.sa_session.flush() - stop = time.time() - print '# -------------------------------------------------------------------------------------------' - print '# Checked %d repository revisions.' % records_checked - print '# %d revisions found with valid tool dependency definition metadata.' % valid_metadata - print '# %d revisions found with invalid tool dependency definition metadata.' % invalid_metadata - if info_only: - print '# Database not updated with any information from this run.' - print "# Elapsed time: ", stop - start - print "#############################################################################" - -if __name__ == "__main__": - main()