@@ -49,10 +49,54 @@ jobs:
4949 shell : bash
5050 run : |
5151 set -euxo pipefail
52- mkdir -p ci/metrics/complete_profile/runs
52+ ts_dir="ci/metrics/complete_profile"
53+ ts_csv="${ts_dir}/complete_profile_timeseries.csv"
54+ mkdir -p "${ts_dir}"
5355
54- stamp="$(date -u +%Y%m%dT%H%M%SZ)_${GITHUB_RUN_NUMBER}_${GITHUB_SHA::8}"
55- cp build/complete_profile.csv "ci/metrics/complete_profile/runs/${stamp}.csv"
56+ python3 - <<'PY'
57+ import csv, os
58+ from pathlib import Path
59+ from datetime import datetime
60+
61+ run = os.environ.get("GITHUB_RUN_NUMBER","")
62+ sha = os.environ.get("GITHUB_SHA","")[:8]
63+ ts_path = Path("ci/metrics/complete_profile/complete_profile_timeseries.csv")
64+ src_path = Path("build/complete_profile.csv")
65+
66+ if not src_path.exists():
67+ raise SystemExit("missing build/complete_profile.csv")
68+
69+ # Read first row and header from source csv
70+ with src_path.open(newline="") as fh:
71+ reader = csv.DictReader(fh)
72+ rows = list(reader)
73+ if not rows:
74+ raise SystemExit("empty complete_profile.csv")
75+ row = rows[0]
76+
77+ # Build a new row with date, run, sha, and all original cols
78+ new_line = {"date": datetime.utcnow().isoformat(timespec="seconds"),
79+ "run": run, "sha": sha}
80+ for key, val in row.items():
81+ try:
82+ new_line[key] = int(val)
83+ except Exception:
84+ new_line[key] = val
85+
86+ # Ensure header is consistent
87+ write_header = not ts_path.exists()
88+ if write_header:
89+ header = ["date","run","sha"] + list(row.keys())
90+ else:
91+ with ts_path.open(newline="") as fh:
92+ header = next(csv.reader(fh))
93+ with ts_path.open("a", newline="") as out:
94+ w = csv.DictWriter(out, fieldnames=header)
95+ if write_header:
96+ w.writeheader()
97+ w.writerow(new_line)
98+ print(f"appended to {ts_path}")
99+ PY
56100
57101 git config user.name "github-actions"
58102 git config user.email "github-actions@github.com"
61105 git fetch origin "${BR}" || true
62106 git checkout -B "${BR}"
63107
64- git add ci/metrics/complete_profile/runs/
65- git diff --cached --quiet || git commit -m "metrics: complete_profile run ${GITHUB_RUN_NUMBER} (${GITHUB_SHA::8})"
108+ git add ci/metrics/complete_profile/complete_profile_timeseries.csv
109+ git diff --cached --quiet || git commit -m "metrics: append run ${GITHUB_RUN_NUMBER} (${GITHUB_SHA::8})"
66110 git push -f origin "${BR}"
67111
68112 - name : Generate plots
@@ -74,46 +118,47 @@ jobs:
74118 from pathlib import Path
75119 import matplotlib.pyplot as plt
76120
77- runs_dir = Path("ci/metrics/complete_profile/runs ")
78- out_png = Path("build/complete_profile_last30.png")
121+ ts_csv = Path("ci/metrics/complete_profile/complete_profile_timeseries.csv ")
122+ out_png = Path("build/complete_profile_last30.png")
79123 out_png.parent.mkdir(parents=True, exist_ok=True)
80124
81- files = sorted(runs_dir.glob("*.csv"))[-30:] # last 30 by filename (timestamp prefix)
82- if not files:
83- raise SystemExit("No historical CSVs found")
84-
85- # Dict of series per column
86- series = {}
87-
88- for f in files:
89- with f.open(newline="") as fh:
90- reader = csv.DictReader(fh)
91- row = next(reader, None)
92- if row is None:
93- continue
94- # Initialize keys on first file
95- if not series:
96- for key in row.keys():
97- series[key] = []
98- # Append values
99- for key in series:
100- val = row.get(key)
101- try:
102- series[key].append(int(val))
103- except Exception:
104- series[key].append(0)
105-
106- if not any(series.values()):
107- raise SystemExit("No numeric values found")
108-
109- x = range(1, len(files)+1)
125+ if not ts_csv.exists():
126+ raise SystemExit("time-series CSV not found")
127+
128+ rows = []
129+ with ts_csv.open(newline="") as fh:
130+ reader = csv.DictReader(fh)
131+ header = reader.fieldnames or []
132+ for r in reader:
133+ rows.append(r)
134+
135+ if not rows:
136+ raise SystemExit("No rows in time-series CSV")
137+
138+ rows = rows[-30:] # last 30 runs
139+
140+ # Choose numeric columns (skip date, run, sha)
141+ skip = {"date","run","sha"}
142+ cols = [h for h in header if h not in skip]
143+
144+ x = range(1, len(rows)+1)
145+ dates = [r["date"] for r in rows]
146+
110147 plt.figure()
111- for key, values in series.items():
112- plt.plot(x, values, label=key)
148+ for key in cols:
149+ try:
150+ ys = [int(r.get(key,0)) for r in rows]
151+ except Exception:
152+ continue
153+ plt.plot(x, ys, label=key)
113154
114155 plt.title("Complete Profile")
115- plt.xlabel("Run (old → new) ")
156+ plt.xlabel("Date ")
116157 plt.ylabel("Bytes")
158+ step = max(1, len(dates)//8)
159+ shown = list(range(0, len(dates), step))
160+ plt.xticks([i+1 for i in shown], [dates[i] for i in shown], rotation=45, ha="right")
161+
117162 plt.legend()
118163 plt.tight_layout()
119164 plt.savefig(out_png)
0 commit comments