#!/usr/bin/env python3 # This is the entry point of the Verificarlo CI command line interface, which is # based on argparse and this article : # https://mike.depalatis.net/blog/simplifying-argparse.html # From here, 3 subcommands can be called : # - setup : create a vfc_ci branch and workflow on the current Git repo # - test : run and export test results according to the vfc_tests_config.json # - serve : launch a Bokeh server to visualize run results import argparse ########################################################################## # Parameters validation helpers def is_port(string): value = int(string) if value < 0 or value > 65535: raise argparse.ArgumentTypeError("Value has to be between 0 and 65535") return value def is_directory(string): import os isdir = os.path.isdir(string) if not isdir: raise argparse.ArgumentTypeError("Directory does not exist") return string ########################################################################## # Subcommand decorator cli = argparse.ArgumentParser( description="Define, run, automatize, and visualize custom Verificarlo tests." ) subparsers = cli.add_subparsers(dest="subcommand") def subcommand(description="", args=[], parent=subparsers): def decorator(func): parser = parent.add_parser(func.__name__, description=description) for arg in args: parser.add_argument(*arg[0], **arg[1]) parser.set_defaults(func=func) return decorator def argument(*name_or_flags, **kwargs): return ([*name_or_flags], kwargs) ########################################################################## # "setup" subcommand @subcommand( description="Create an automated workflow to execute Verificarlo tests.", args=[ argument( "git_host", help=""" specify where your repository is hosted """, choices=["github", "gitlab"] ) ] ) def setup(args): import ci.setup ci.setup.setup(args.git_host) # "test" subcommand @subcommand( description="Execute predefined Verificarlo tests and save their results.", args=[ argument( "-g", "--is-git-commit", help=""" When specified, the last Git commit of the local repository (working directory) will be fetched and associated with the run. """, action="store_true" ), argument( "-r", "--export-raw-results", help=""" Specify if an additional HDF5 file containing the raw results must be exported. """, action="store_true" ), argument( "-d", "--dry-run", help=""" Perform a dry run by not saving the test results. """, action="store_true" ) ] ) def test(args): import ci.test ci.test.run(args.is_git_commit, args.export_raw_results, args.dry_run) # "serve" subcommand @subcommand( description=""" Start a server to visualize Verificarlo test results. """, args=[ argument( "-s", "--show", help=""" Specify if the report must be opened in the browser at server startup. """, action="store_true" ), argument( "-gd", "--git-directory", help=""" Path to a local Git repository. The report will be linked to the remote URL (GitHub and GitLab are supported). """, type=is_directory ), argument( "-gu", "--git-url", help=""" GitHub or GitLab repository URL. The report will be linked to this URL. """, type=str ), argument( "-p", "--port", help=""" The port on which the server will run. Defaults to 8080. """, type=is_port, default=8080 ), argument( "-a", "--allow-origin", help=""" The origin (URL) from which the report will be accessible. Port number must not be specified. Defaults to * (allow everything). """, type=str, default="*" ), argument( "-l", "--logo", help=""" Specify the URL of an image to be displayed in the report header. """, type=str ) ] ) def serve(args): # git_directory and git_url are supposed to be exclusive if args.git_directory is not None and args.git_url is not None: raise argparse.ArgumentTypeError( "\"-gd\" / \"--git-directory\" and \"-gu\" / \"--git-url\" are " "mutually exclusive. Please make sure to use at most one of them." ) import ci.serve ci.serve.serve( args.show, args.git_directory, args.git_url, args.port, args.allow_origin, args.logo ) ############################################################################### # Main command group and entry point if __name__ == "__main__": args = cli.parse_args() if args.subcommand is None: cli.print_help() else: args.func(args)