generated from coulomb/repo-seed
feat(CUST-WP-0014): repo sync automation & Gitea inventory
- Migration e2f3a4b5c6d7: add last_state_synced_at to managed_repos
- consistency_check.py: PATCH last_state_synced_at after fix run;
fix ~ treated as non-empty state_hub_task_id (C-03 vs C-11);
fix _inject_task_id_into_block skipping injection when field exists
with null value
- install_hooks.sh: idempotent post-commit hook installer for all
registered repos (make install-hooks REPO= / install-hooks-all)
- gitea_inventory.py: compare coulomb Gitea org against state-hub
registered repos — registered / unregistered / hub-only sections
- infra/README.md: document systemd user timer + crontab fallback
- systemd user timer: custodian-sync.{service,timer} runs
fix-consistency-all every 15 min (enabled)
- dashboard/src/repo-sync.md: Repo Sync Health page — sync age table,
unregistered Gitea repos, hub-only repos
- api/routers/repos.py: GET /repos/{slug}/dispatch endpoint returning
active goal, pending tasks per workstream, human interventions
- mcp_server/server.py: get_repo_dispatch() MCP tool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -191,9 +191,18 @@ def _inject_task_id_into_block(
|
||||
task_meta = _parse_yaml_block(block_content.strip())
|
||||
if str(task_meta.get("id", "")) != match_id:
|
||||
return m.group(0)
|
||||
if field_name in task_meta:
|
||||
existing_val = task_meta.get(field_name)
|
||||
if existing_val is not None and str(existing_val).strip() not in ("", "~", "null", "None", "none"):
|
||||
return m.group(0)
|
||||
new_content = block_content.rstrip() + f"\n{field_name}: \"{field_value}\""
|
||||
# Replace existing null/~ line if present, otherwise append
|
||||
new_content = re.sub(
|
||||
rf"^{re.escape(field_name)}:.*$",
|
||||
f'{field_name}: "{field_value}"',
|
||||
block_content,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
if new_content == block_content:
|
||||
new_content = block_content.rstrip() + f"\n{field_name}: \"{field_value}\""
|
||||
return f"```task\n{new_content}\n```"
|
||||
|
||||
new_text = _TASK_BLOCK_RE.sub(_replace, text)
|
||||
@@ -461,7 +470,10 @@ def check_repo(api_base: str, repo_slug: str) -> ConsistencyReport:
|
||||
if task.get("_parse_error"):
|
||||
continue
|
||||
t_id = str(task.get("id", "")).strip()
|
||||
t_sh_id = str(task.get("state_hub_task_id", "")).strip().strip('"')
|
||||
_raw_sh = task.get("state_hub_task_id")
|
||||
t_sh_id = "" if _raw_sh is None else str(_raw_sh).strip().strip('"')
|
||||
if t_sh_id in ("~", "null", "None", "none"):
|
||||
t_sh_id = ""
|
||||
t_status = str(task.get("status", "")).strip()
|
||||
|
||||
if t_sh_id:
|
||||
@@ -724,6 +736,12 @@ def fix_repo(api_base: str, repo_slug: str) -> ConsistencyReport:
|
||||
except Exception as e:
|
||||
report.fixes_applied.append(f"{issue.check_id} ERROR: {e}")
|
||||
|
||||
# Record that a sync run happened for this repo
|
||||
from datetime import timezone as _tz
|
||||
import datetime as _dt
|
||||
now_iso = _dt.datetime.now(_tz.utc).isoformat()
|
||||
_api_patch(api_base, f"/repos/{repo_slug}/", {"last_state_synced_at": now_iso})
|
||||
|
||||
return report
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user