1#!/usr/bin/env python3
2"""Run the public library regression lane and retain each command's output."""
3import argparse
4from datetime import datetime, timezone
5import json
6import os
7from pathlib import Path
8import subprocess
9import sys
10import time
11
12
13def main():
14 parser = argparse.ArgumentParser(description=__doc__)
15 parser.add_argument('output', type=Path, help='New directory for logs and results')
16 args = parser.parse_args()
17 root = Path(__file__).resolve().parent.parent
18 output = args.output.resolve()
19 output.mkdir(parents=True, exist_ok=False)
20 environment = {key: value for key, value in os.environ.items()
21 if not key.startswith(('ONESTORE_', 'SNOWBOUND_'))}
22 environment['PYTHONPATH'] = str(root / 'tools')
23 environment['CARGO_TARGET_DIR'] = str(root / 'target')
24 commands = [
25 ('python-dependencies', [sys.executable, '-c', 'import PIL, pdfplumber']),
26 ('format', ['cargo', 'fmt', '--all', '--check']),
27 ('rust', ['cargo', 'test', '--locked', '--workspace', '--all-features', '--all-targets']),
28 ('doctests', ['cargo', 'test', '--locked', '--workspace', '--all-features', '--doc']),
29 ('clippy', ['cargo', 'clippy', '--locked', '--workspace', '--all-features', '--all-targets', '--', '-D', 'warnings']),
30 ('tools', ['cargo', 'build', '--locked', '--workspace', '--all-features', '--examples', '--bins']),
31 ('python', [sys.executable, '-m', 'unittest', 'discover', '-s', 'tools', '-p', 'test_*.py', '-v']),
32 ]
33 manifest = {'lane': 'public', 'root': str(root), 'status': 'running',
34 'started': datetime.now(timezone.utc).isoformat(), 'stages': []}
35 result_path = output / 'results.json'
36 result_path.write_text(json.dumps(manifest, indent=2) + '\n')
37 for name, command in commands:
38 print(name, flush=True)
39 started = time.monotonic()
40 log = output / (name + '.log')
41 with log.open('w') as stream:
42 try:
43 status = subprocess.run(command, cwd=root, env=environment,
44 stdout=stream, stderr=subprocess.STDOUT).returncode
45 except OSError as error:
46 stream.write(str(error) + '\n')
47 status = None
48 manifest['stages'].append({'name': name, 'command': command,
49 'exit': status, 'seconds': time.monotonic() - started,
50 'log': log.name})
51 if status != 0:
52 manifest['status'] = 'failed'
53 result_path.write_text(json.dumps(manifest, indent=2) + '\n')
54 if status != 0:
55 raise SystemExit(f'{name} failed: {log}')
56 manifest['status'] = 'passed'
57 result_path.write_text(json.dumps(manifest, indent=2) + '\n')
58 print(result_path)
59
60
61if __name__ == '__main__':
62 main()