Files
troupe-standup/wizard-work/ledger/census_check.py
T

102 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""CHECK: the troupe daily-churn census artifact.
Recomputes the census from the repository (checkins/*.md + replies/*.md filenames
cross-checked against `git log --format=%ad --date=short`) and diffs it against the
committed CSV artifact. Exits 0 iff they are byte-identical in content; nonzero otherwise.
"""
import os
import re
import subprocess
import sys
from collections import Counter
BASE = '/root/troupe-standup'
CSV_PATH = '/root/troupe-standup/wizard-work/ledger/troupe-census.csv'
DATE_RE = re.compile(r'^(\d{4}-\d{2}-\d{2})-(.*)$')
WIZARD_ORDER = ['zephyrus', 'cassian', 'mercury', 'merlin', 'gemini', 'volt',
'argus', 'timmy', 'beam', 'forge', 'ledger', 'null', 'sol', 'spark',
'sphinx']
def parse_files(d):
out = []
for fn in sorted(os.listdir(os.path.join(BASE, d))):
if not fn.endswith('.md'):
continue
m = DATE_RE.match(fn[:-3])
if m:
out.append((m.group(1), m.group(2), fn))
return out
def compute():
c = parse_files('checkins')
r = parse_files('replies')
ciw = Counter()
for date, suf, fn in c:
ciw[(date, suf.split('-', 1)[0])] += 1
rpw = Counter()
for date, suf, fn in r:
assert suf.startswith('to-'), suf
rpw[(date, suf[len('to-'):].split('-', 1)[0])] += 1
git_dates = Counter()
proc = subprocess.run(
['git', '-C', BASE, 'log', '--format=%ad', '--date=short'],
capture_output=True, text=True, check=True)
for d in proc.stdout.strip().splitlines():
git_dates[d] += 1
dates = sorted(set([d for d, _ in ciw.keys()] + [d for d, _ in rpw.keys()]))
rows = []
for date in dates:
for w in WIZARD_ORDER:
ci_n = ciw.get((date, w), 0)
rp_n = rpw.get((date, w), 0)
com = git_dates.get(date, 0)
if ci_n or rp_n or com:
rows.append((date, w, ci_n, rp_n, com))
rows.sort()
return rows, git_dates
def main():
_, git_dates = compute()
expected = compute()[0]
expected_csv = []
for date, w, ci_n, rp_n, com in expected:
expected_csv.append(f'{date},{w},{ci_n},{rp_n},{com}')
if not os.path.exists(CSV_PATH):
print(f'FAIL: artifact CSV missing: {CSV_PATH}')
sys.exit(1)
with open(CSV_PATH) as f:
header = f.readline().strip().split(',')
if header != ['date', 'wizard', 'checkins', 'replies', 'commits']:
print(f'FAIL: bad header {header}')
sys.exit(1)
actual = [line.strip() for line in f if line.strip()]
if expected_csv != actual:
print('FAIL: artifact differs from a fresh extraction')
print(' expected first differing row:')
for e, a in zip(expected_csv, actual):
if e != a:
print(f' expected: {e}')
print(f' actual: {a}')
break
print(f' (expected {len(expected_csv)} rows, got {len(actual)} rows)')
sys.exit(1)
print(f'OK: {len(expected_csv)} rows match a fresh extraction from this repository')
sys.exit(0)
if __name__ == '__main__':
main()