Anton Shestakov <av6@dwimlabs.net>, Sat, 25 Jun 2016 18:16:39 +0800
models: drop Check.raw field (not worth storing in the same table)
Replaying checks can be done (and is easier) when storing checker output in
plain files, so let's lighten up the load on the database.
checker.py
Permissions: -rwxr-xr-x
from __future__ import print_function from argparse import ArgumentParser, FileType from datetime import datetime from shutil import rmtree from subprocess import check_call, check_output, CalledProcessError from tempfile import mkdtemp rel = lambda *x: os.path.abspath(os.path.join(os.path.dirname(__file__), *x)) def run_ignore_codes(fn, args, codes): except CalledProcessError as e: if e.returncode not in codes: def run(args, silent=False, get_output=False, ignore_codes=None): print('$ ' + ' '.join(args)) result = run_ignore_codes(fn, args, ignore_codes) print('# C&O error: {}'.format(e)) print('# C&O job failed') return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S+00:00') def read_linter_config(name, path=rel('linters')): fd = open(os.path.join(path, '{}.yml'.format(name))) print("# C&O couldn't load linter config: {}".format(e)) return yaml.safe_load(fd) print("# C&O couldn't parse linter config: {}".format(e)) print('# C&O job started: {}'.format(now())) tmp = mkdtemp(prefix='candolint.') print('# C&O task: clone') print('# C&O project URL: {}'.format(config['url'])) if ok and not run(['hg', 'clone', config['url'], source]): print('$ cd {}'.format(source)) if ok and not run(['hg', 'sum']): template = (r'# C&O commit: {rev}:{node} {branch}\n' r'# C&O commit date: {date|isodatesec}\n' r'# C&O commit author: {author|person}\n' r'# C&O commit message: {desc|firstline}\n') if not run(['hg', 'log', '-r', '.', '-T', template], silent=True): print('# C&O task: setup') for linter in config['linters']: if name in linter_config: lc = read_linter_config(name) if lc is None or 'exec' not in lc: for item in lc.get('setup', []): if 'version' in lc and not run(lc['exec'] + lc['version']): print('# C&O task: checks') for linter in config['linters']: if 'name' not in linter or 'include' not in linter: if linter['name'] not in linter_config: for pat in linter['include']: for pat in linter.get('exclude', []): files = run(cmd, silent=True, get_output=True, ignore_codes=(1,)) lc = linter_config[linter['name']] for f in files.splitlines(): flags = lc.get('flags', []) + linter.get('flags', []) pf = lc.get('post_flags', []) + linter.get('post_flags', []) codes = lc.get('codes', (1,)) if not run(cmd + flags + [f] + pf, ignore_codes=codes): print('# C&O task: cleanup') print('# C&O job finished: {}'.format(now())) print('# C&O job failed (exception not caught)') print('# C&O job finished: {}'.format(now())) parser = ArgumentParser() parser.add_argument('config', help='configuration file (YAML)', type=FileType('r')) args = parser.parse_args() config = yaml.safe_load(args.config) if __name__ == '__main__':