diff --git a/src/pyarcanist/__init__.py b/src/pyarcanist/__init__.py index 757856e..514ec32 100644 --- a/src/pyarcanist/__init__.py +++ b/src/pyarcanist/__init__.py @@ -1,9 +1,10 @@ from .cache import cache from . import cli # make sure these are imported after cli, since some # cache config may occur in there from . import whoami from . import diff +from . import harbormaster __all__ = (cli, whoami, diff, cache) diff --git a/src/pyarcanist/harbormaster.py b/src/pyarcanist/harbormaster.py new file mode 100644 index 0000000..fd8af41 --- /dev/null +++ b/src/pyarcanist/harbormaster.py @@ -0,0 +1,84 @@ +import click +from . import cli + + +validators = { + 'unit': [ + ('name', True, None), + ('result', True, + ('pass', 'fail', 'skip', 'broken', 'unsound')), + ('namespace', False, None), + ('engine', False, None), + ('duration', False, float), + ('path', False, None), + ('coverage', False, None), + ('details', False, None), + ('format', False, None), + ], + 'lint': [ + ('name', True, None), + ('code', True, None), + ('severity', True, + ('advice', 'autofix', 'warning', 'error', 'disabled')), + ('path', True, None), + ('line', False, int), + ('char', False, int), + ('description', False, None), + ], +} + + +def check_validator(validator, value): + if not validator: + return True + if isinstance(validator, tuple): + return value in validator + if callable(validator): + try: + validator(value) + except Exception: + return False + return True + + +def validate(params, report_type): + if isinstance(params, str): + params = dict(x.strip().split('=', 1) for x in params.split(',')) + for k, mandatory, validator in validators[report_type]: + if mandatory and not k in params: + raise ValueError( + 'Parameter {} is mandatory for a {} report'.format( + k, report_type)) + if k in params and not check_validator(validator, params[k]): + raise ValueError( + 'Parameter {} has an invalid value "{}"'.format(k, params[k])) + return params + + +@cli.pyarc.command() +@click.argument('message-type', type=click.Choice(['pass', 'fail', 'work'])) +@click.argument('phid') +@click.option('-u', '--unit', multiple=True) +@click.option('-l', '--lint', multiple=True) +@click.pass_context +def send_message(ctx, message_type, phid, unit, lint): + '''Send a harbormaster message''' + + options = ctx.obj['options'] + + kw = {'type': message_type, + 'buildTargetPHID': phid} + try: + if unit: + kw['unit'] = [validate(u, 'unit') for u in unit] + if lint: + kw['lint'] = [validate(l, 'lint') for l in lint] + except ValueError as e: + + ctx.fail('Invalid parameter: {}'. format(e)) + + if options.verbose: + click.echo('Sending message to harbormaster:') + for k, v in kw.items(): + click.echo(" {}: {}".format(k, v)) + cli.cnx.harbormaster.sendmessage(**kw)