diff options
| author | godosa <godosa@godosa.eu> | 2026-10-07 09:31:12 +0200 |
|---|---|---|
| committer | godosa <godosa@godosa.eu> | 2026-10-07 09:31:12 +0200 |
| commit | 4743282cde2cd3d6ec767e93564b2121c6d643e4 (patch) | |
| tree | dc7d8af1a52c75e47dc5ea4c6808607c336a5110 /wf.py | |
| parent | ecf39ec27307f36d9458a22a332c8848bffe79a5 (diff) | |
| download | workflow-4743282cde2cd3d6ec767e93564b2121c6d643e4.tar.gz workflow-4743282cde2cd3d6ec767e93564b2121c6d643e4.zip | |
split projects 4/6: workflow.toml push, wf push, .wf/push-failed marker
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEAjUkQRrCYX5MZhWxdtj2
Diffstat (limited to 'wf.py')
| -rwxr-xr-x | wf.py | 52 |
1 files changed, 47 insertions, 5 deletions
@@ -7,6 +7,7 @@ Change: add "Title. Goal." -p N -e EFFORT · done ID… -m "entry" · prio ID N move ID SECTION | --before/--after ID · status ID progress NOTE|blocked A-ID|clear set ID --title/--effort/--after/--ref/--model/--sessions/--cloud · note ID "line" body ID <stdin (Model:/Sessions:/After:/Ref: kept) · tick ID N|TEXT · setup · merge (in a lane worktree) + push (rerun a merge's push: workflow.toml push, else push home) Orch: orch pick LANE [--id ID] [--recovery WHY] · orch post ID LANE [--result LINE] [--agent A] [--duration S] [--no-next] Other: report "what happened" · init · migrate [--write] · res … (shared memory/CPU ledger; wf res -h) batch N [--lanes L,…] [--prep] | --status (unattended batch orchestrator; wf batch -h) @@ -432,6 +433,8 @@ def cmd_next(args) -> int: item, skipped = lanes.pick(p.doc, p.archived, p.cfg.lanes, p.cfg.slice_above, lane, model, claims, other_live(p.cfg), args.owner) multi = multi_lines(p, args, lane or "all", 1 if warning else 0) + if (marker := p.cfg.root / ".wf" / "push-failed").is_file(): + out += [f"push failed: {marker.read_text().splitlines()[0]} → wf push (in {p.cfg.root})"] if not args.brief: awaiting = p.doc.section("awaiting").items if awaiting: @@ -1268,13 +1271,44 @@ def cmd_merge(args) -> int: git_run(top, "switch", "-q", "--detach", master) if branch: git_run(top, "branch", "-q", "-d", branch) - if not args.no_push and any([_push_home(main), bmain != main and _push_home(bmain)]): - out.append("pushed home") + args.push_rc = 0 + if not args.no_push: + args.push_rc, lines = run_push(cfg, [bmain, main]) + out += lines out.append(f"merged {branch or 'detached HEAD'} into {master}") print("\n".join(out)) return 0 +def run_push(cfg: config.Config, repos: list[Path]) -> tuple[int, list[str]]: + """Push after a merge: workflow.toml push lines (cwd = root, env WF_MAIN; first nonzero stops and writes + .wf/push-failed), else _push_home on each repo. (exit code, lines to print).""" + marker = cfg.root / ".wf" / "push-failed" + if not cfg.push: + pushed = [r for r in dict.fromkeys(repos) if _push_home(r)] + return 0, ["pushed home"] if pushed else [] + env = {**os.environ, "WF_MAIN": str(cfg.root)} + for line in cfg.push: + r = subprocess.run(line, shell=True, cwd=cfg.root, env=env, capture_output=True, text=True) + if r.returncode: + tail = (r.stdout + r.stderr).strip().splitlines()[-5:] + wf_folder(cfg, "orch") # creates .wf with its .gitignore + marker.write_text(f"{line}\nexit {r.returncode}\n" + "\n".join(tail) + "\n") + return r.returncode, [f"not pushed (exit {r.returncode}): {line}", *(f" {t}" for t in tail), + "rerun: wf push"] + marker.unlink(missing_ok=True) + return 0, [f"pushed ({len(cfg.push)} push command{'s' * (len(cfg.push) != 1)})"] + + +def cmd_push(args) -> int: + """Run the push of a merge again (workflow.toml push, else push home), from the project or a code worktree.""" + cfg = config.load_at(Path(args.project or Path.cwd()).resolve()) + repos = [r for r in (config.git_top(cfg.root), config.code_main(cfg)) if r] + rc, lines = run_push(cfg, repos) + print("\n".join(lines) or "nothing to push (no push key, no remote home)") + return rc + + def _push_home(main: Path) -> bool: """git push home --all/--tags when remote home exists; True if pushed.""" if "home" not in git_run(main, "remote").stdout.split(): @@ -1371,8 +1405,11 @@ def cmd_finish(args) -> int: sha = git_run(top, "rev-parse", "--short", "HEAD").stdout.strip() tool = getattr(args, "tool_commit", None) print(f"report: commit {sha}" + (f" tool {tool}" if tool else ""), flush=True) - if not wt and not args.no_push and _push_home(top): - print("pushed home", flush=True) + push_rc = 0 + if not wt and not args.no_push: + push_rc, lines = run_push(cfg, [top]) + if lines: + print("\n".join(lines), flush=True) if wt: ns = argparse.Namespace(project=args.project, m=None, no_push=args.no_push, private=priv, private_msg=args.commit) @@ -1380,7 +1417,9 @@ def cmd_finish(args) -> int: if not rc and getattr(ns, "merged_sha", ""): tool = getattr(args, "tool_commit", None) books_sha = f" books {ns.books_sha}" if split else "" - print(f"report: commit {ns.merged_sha}{books_sha}" + (f" tool {tool}" if tool else ""), flush=True) + failed = f" push-failed {ns.push_rc}" if getattr(ns, "push_rc", 0) else "" + print(f"report: commit {ns.merged_sha}{books_sha}" + (f" tool {tool}" if tool else "") + failed, + flush=True) return rc return 0 @@ -2178,6 +2217,9 @@ def parser() -> argparse.ArgumentParser: sp.add_argument("-m", help="bookkeeping commit message (default '<id> done', id from the branch)") sp.add_argument("--no-push", action="store_true", help="skip git push home") + sp = cmd("push", cmd_push, "rerun a merge's push: workflow.toml push lines, else git push home") + sp.set_defaults(locks=True) + sp = cmd("finish", cmd_finish, "worker's last step in one call: quick_gate → done → commit PATHS (explicit) → " "wf merge (lane worktree; main tree: TASKS/archive go into the commit). Run verify first. " "Refuses before done if the gate is red, files outside PATHS are uncommitted, or a PATH is outside " |
