steps/ per ladder step: gate rule 4, writer, backfill (8); R-653, R-656; decoy suite reads live pins (R-663)
gates / gates (push) Successful in 2s
gates / gates (push) Successful in 2s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""steps_backfill.py — ONE-OFF (2026-09-24, `09` §6.4 part 5): write `steps/<step_key(to)>.yml` for every
|
||||
ladder entry that is not the newest, from git history.
|
||||
|
||||
WHICH COMMIT, and why not "the commit of the step": the definition a box must pin for a step is the one
|
||||
the catalog SERVED while that step was the head — the NEWEST commit whose compose images equal the
|
||||
step's `to`, i.e. the step's images WITH every fix that flowed after they moved. The commit that MOVED
|
||||
the image can be the broken one: romm's 15f9ebf (5.0.0 -> 5.3.0, 512M, four workers) OOM-looped on
|
||||
demo-hp; the working definition is the same images under f4eb94f's template (768M, two workers).
|
||||
|
||||
Prints one line per step: app, entry, step key, the commit it came from. Never overwrites a step file.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import ladder # noqa: E402
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
def git(*a):
|
||||
return subprocess.run(["git", "-C", ROOT] + list(a), capture_output=True, text=True, check=True).stdout
|
||||
|
||||
|
||||
def main():
|
||||
wrote = 0
|
||||
for app in sorted(os.listdir(os.path.join(ROOT, "templates"))):
|
||||
d = os.path.join(ROOT, "templates", app)
|
||||
fy = os.path.join(d, ".felhom.yml")
|
||||
if not os.path.isfile(fy):
|
||||
continue
|
||||
entries, _, errs = ladder.parse(open(fy, encoding="utf-8").read())
|
||||
if errs or len(entries) < 2:
|
||||
continue
|
||||
rel = "templates/%s/docker-compose.yml" % app
|
||||
commits = git("log", "--format=%H", "--", rel).split() # newest first
|
||||
for i, e in enumerate(entries[:-1]):
|
||||
dst = os.path.join(d, ladder.step_file(e["to"]))
|
||||
if os.path.exists(dst):
|
||||
print("SKIP %-10s entry %d: %s exists" % (app, i + 1, ladder.step_file(e["to"])))
|
||||
continue
|
||||
found = None
|
||||
for c in commits:
|
||||
body = git("show", "%s:%s" % (c, rel))
|
||||
if ladder.images_in(body) == e["to"]:
|
||||
found = (c, body)
|
||||
break # newest first: the last definition served for this step
|
||||
if not found:
|
||||
print("MISS %-10s entry %d: no commit's compose names %s" % (app, i + 1, e["to"]))
|
||||
continue
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
open(dst, "w", encoding="utf-8").write(found[1])
|
||||
print("WROTE %-10s entry %d/%d -> %s from %s (%s)" % (app, i + 1, len(entries), ladder.step_file(e["to"]),
|
||||
found[0][:12], git("log", "-1", "--format=%s", found[0]).strip()[:70]))
|
||||
wrote += 1
|
||||
print("steps_backfill: %d step definition(s) written" % wrote)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user