diff --git a/README.md b/README.md index eb0863161..af28d433c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Loop Habit Tracker - + - - Coverage via Codecov + + Loop is a simple Android app that helps you create and maintain good habits, diff --git a/build.sh b/build.sh index 1f6aab495..d14961bfc 100755 --- a/build.sh +++ b/build.sh @@ -156,6 +156,11 @@ parse_instrumentation_results() { java -jar tools/automator-log-converter-1.5.0.jar ${OUTPUTS_DIR}/instrument.txt || fail } +generate_coverage_badge() { + log_info "Generating code coverage badge" + python tools/coverage-badge/badge.py -i app/build/reports/jacoco/coverageReport/coverageReport.xml -o ${OUTPUTS_DIR}/coverage-badge +} + fetch_artifacts() { log_info "Fetching generated artifacts" mkdir -p ${OUTPUTS_DIR}/failed @@ -195,6 +200,7 @@ run_local_tests() { fetch_artifacts fetch_logcat run_jvm_tests + generate_coverage_badge uninstall_test_apk } diff --git a/tools/coverage-badge/badge.py b/tools/coverage-badge/badge.py new file mode 100644 index 000000000..f3cc09f35 --- /dev/null +++ b/tools/coverage-badge/badge.py @@ -0,0 +1,155 @@ +""" +Generate coverage badges for Coverage.py. +Forked from https://github.com/dbrgn/coverage-badge +""" +# -*- coding: utf-8 -*- +from __future__ import print_function, division, absolute_import, unicode_literals + +import os +import sys +import argparse +import pkg_resources +from bs4 import BeautifulSoup + +__version__ = '0.2.0-uhabits' + + +DEFAULT_COLOR = '#a4a61d' +COLORS = { + 'brightgreen': '#4c1', + 'green': '#97CA00', + 'yellowgreen': '#a4a61d', + 'yellow': '#dfb317', + 'orange': '#fe7d37', + 'red': '#e05d44', + 'lightgrey': '#9f9f9f', +} + +COLOR_RANGES = [ + (95, 'brightgreen'), + (90, 'green'), + (75, 'yellowgreen'), + (60, 'yellow'), + (40, 'orange'), + (0, 'red'), +] + + +class Devnull(object): + """ + A file like object that does nothing. + """ + def write(self, *args, **kwargs): + pass + + +def get_total(report): + doc = BeautifulSoup(file(report), 'xml') + tag = doc.select("report > counter[type^INST]")[0] + missed = int(tag['missed']) + covered = int(tag['covered']) + total = int((covered * 10000 / (missed + covered)) / 100) + return str(total) + +def get_color(total): + """ + Return color for current coverage precent + """ + try: + xtotal = int(total) + except ValueError: + return COLORS['lightgrey'] + for range_, color in COLOR_RANGES: + if xtotal >= range_: + return COLORS[color] + + +def get_badge(total, color=DEFAULT_COLOR): + """ + Read the SVG template from the package, update total, return SVG as a + string. + """ + template_path = os.path.join('templates', 'flat.svg') + template = pkg_resources.resource_string(__name__, template_path).decode('utf8') + return template.replace('{{ total }}', total).replace('{{ color }}', color) + + +def parse_args(argv=None): + """ + Parse the command line arguments. + """ + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('-o', dest='filepath', + help='Save the file to the specified path.') + parser.add_argument('-p', dest='plain_color', action='store_true', + help='Plain color mode. Standard green badge.') + parser.add_argument('-f', dest='force', action='store_true', + help='Force overwrite image, use with -o key.') + parser.add_argument('-q', dest='quiet', action='store_true', + help='Don\'t output any non-error messages.') + parser.add_argument('-v', dest='print_version', action='store_true', + help='Show version.') + parser.add_argument('-i', dest='reportFilename', + help='Jacoco report') + + # If arguments have been passed in, use them. + if argv: + return parser.parse_args(argv) + + # Otherwise, just use sys.argv directly. + else: + return parser.parse_args() + + +def save_badge(badge, filepath, force=False): + """ + Save badge to the specified path. + """ + # Validate path (part 1) + if filepath.endswith('/'): + print('Error: Filepath may not be a directory.') + sys.exit(1) + + # Get absolute filepath + path = os.path.abspath(filepath) + if not path.lower().endswith('.svg'): + path += '.svg' + + # Validate path (part 2) + if not force and os.path.exists(path): + print('Error: "{}" already exists.'.format(path)) + sys.exit(1) + + # Write file + with open(path, 'w') as f: + f.write(badge) + + return path + + +def main(argv=None): + """ + Console scripts entry point. + """ + args = parse_args(argv) + + # Print version + if args.print_version: + print('coverage-badge v{}'.format(__version__)) + sys.exit(0) + + total = get_total(args.reportFilename) + color = DEFAULT_COLOR if args.plain_color else get_color(total) + badge = get_badge(total, color) + + # Show or save output + if args.filepath: + path = save_badge(badge, args.filepath, args.force) + if not args.quiet: + print('Saved badge to {}'.format(path)) + else: + print(badge, end='') + + +if __name__ == '__main__': + main() diff --git a/tools/coverage-badge/templates/flat.svg b/tools/coverage-badge/templates/flat.svg new file mode 100644 index 000000000..169cd8d67 --- /dev/null +++ b/tools/coverage-badge/templates/flat.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + coverage + coverage + {{ total }}% + {{ total }}% + +