ci: onboard windy-connect + windy-search to private-repo CI
Some checks failed
check / gate (push) Has been cancelled

windy-connect promoted from pull mirror to writable (release.yml, which
publishes to PyPI on tag push, disabled — the sync pushes tags).
windy-search was already writable; its scheduled drift-check is disabled
because it now runs as cron on Kit 0. Both added to BRIDGE_REPOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-23 02:44:19 -04:00
parent dcf9286f16
commit e4a15869c0
3 changed files with 48 additions and 23 deletions

View File

@@ -14,7 +14,9 @@ from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
_spec = importlib.util.spec_from_file_location("pr_status_bridge", ROOT / "scripts" / "pr_status_bridge.py")
_spec = importlib.util.spec_from_file_location(
"pr_status_bridge", ROOT / "scripts" / "pr_status_bridge.py"
)
bridge = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(bridge)
@@ -22,7 +24,14 @@ SHA = "a" * 40
def _run(i, wf, job, status, sha=SHA, n=1):
return {"id": i, "workflow_id": wf, "name": job, "status": status, "head_sha": sha, "run_number": n}
return {
"id": i,
"workflow_id": wf,
"name": job,
"status": status,
"head_sha": sha,
"run_number": n,
}
class Fake:
@@ -34,7 +43,7 @@ class Fake:
def gitea(self, method, path, body=None):
if "/actions/tasks" in path:
page = int(path.rsplit("page=", 1)[1])
return 200, {"workflow_runs": self.runs[(page - 1) * 50: page * 50]}
return 200, {"workflow_runs": self.runs[(page - 1) * 50 : page * 50]}
if method == "GET" and path.endswith("/pulls?state=open&limit=50"):
return 200, self.wg_prs
if method == "POST" and path.endswith("/pulls"):
@@ -63,6 +72,7 @@ def fake(monkeypatch):
monkeypatch.setattr(bridge, "gitea", f.gitea)
monkeypatch.setattr(bridge, "github", f.github)
return f
return make
@@ -74,8 +84,10 @@ def test_posts_latest_verdict_per_job(fake):
def test_unchanged_state_is_not_reposted(fake):
f = fake(runs=[_run(1, "ci.yml", "test", "success")],
statuses=[{"context": "windy-git/ci/test", "state": "success"}])
f = fake(
runs=[_run(1, "ci.yml", "test", "success")],
statuses=[{"context": "windy-git/ci/test", "state": "success"}],
)
bridge.post_statuses("r", SHA)
assert f.posted == []
@@ -100,9 +112,13 @@ def test_runs_past_the_first_page_are_seen(fake):
def _gh_pr(n, repo="sneakyfree/r"):
return {"number": n, "title": "t", "html_url": "u",
"head": {"ref": f"b{n}", "sha": SHA, "repo": {"full_name": repo} if repo else None},
"base": {"ref": "main"}}
return {
"number": n,
"title": "t",
"html_url": "u",
"head": {"ref": f"b{n}", "sha": SHA, "repo": {"full_name": repo} if repo else None},
"base": {"ref": "main"},
}
def test_fork_prs_are_never_mirrored(fake, monkeypatch):

View File

@@ -43,7 +43,8 @@ WG_OWNER = os.environ.get("WINDYGIT_OWNER", "windyadmin")
# Private repos only. Public repos run real GitHub Actions on veron1's GitHub
# runner; bridging those too would put two competing verdicts on every commit.
REPOS = os.environ.get(
"BRIDGE_REPOS", "windy-chat windy-mail windy-calendar Windy-Clone WindyCloud"
"BRIDGE_REPOS",
"windy-chat windy-mail windy-calendar Windy-Clone WindyCloud windy-search windy-connect",
).split()
# Gitea run status -> GitHub status state. `skipped` is deliberately absent: a
@@ -108,13 +109,17 @@ def sync_prs(repo: str) -> list[str]:
heads.append(pr["head"]["sha"])
if tag in ours:
continue
st, _ = gitea("POST", f"/repos/{WG_OWNER}/{repo}/pulls", {
"head": pr["head"]["ref"],
"base": pr["base"]["ref"],
"title": f"{tag} {pr['title']}"[:250],
"body": f"Mirror of {pr['html_url']} so CI runs here. Do not merge in Windy Git — "
"GitHub is the source of truth; merge there.",
})
st, _ = gitea(
"POST",
f"/repos/{WG_OWNER}/{repo}/pulls",
{
"head": pr["head"]["ref"],
"base": pr["base"]["ref"],
"title": f"{tag} {pr['title']}"[:250],
"body": f"Mirror of {pr['html_url']} so CI runs here. Do not merge in Windy Git — "
"GitHub is the source of truth; merge there.",
},
)
print(f" {repo}: opened mirror PR for GH#{pr['number']} -> {st}")
for tag, p in ours.items():
@@ -154,12 +159,16 @@ def post_statuses(repo: str, sha: str) -> None:
state = STATE.get(r["status"])
if state is None or current.get(ctx) == state:
continue
st, _ = github("POST", f"/repos/{GH_OWNER}/{repo}/statuses/{sha}", {
"state": state,
"context": ctx,
"description": f"Windy Git CI on Veron 1: {r['status']}"[:140],
"target_url": f"{PUBLIC}/{WG_OWNER}/{repo}/actions/runs/{r['run_number']}",
})
st, _ = github(
"POST",
f"/repos/{GH_OWNER}/{repo}/statuses/{sha}",
{
"state": state,
"context": ctx,
"description": f"Windy Git CI on Veron 1: {r['status']}"[:140],
"target_url": f"{PUBLIC}/{WG_OWNER}/{repo}/actions/runs/{r['run_number']}",
},
)
print(f" {repo}@{sha[:7]} {ctx} = {state} -> {st}")

View File

@@ -38,7 +38,7 @@ FAILED=0
# Repos Windy Git tracks FROM GitHub. Remove a repo from this list at the moment
# it flips to Windy-Git-first, or the sync will fight its authors and win.
REPOS="${SYNC_REPOS:-windy-calendar windy-search windy-registry Windy-Clone WindyCloud windy-cloud-sites windy-mind eternitas windy-agent windy-git windy-chat windy-mail}"
REPOS="${SYNC_REPOS:-windy-calendar windy-search windy-registry Windy-Clone WindyCloud windy-cloud-sites windy-mind eternitas windy-agent windy-git windy-chat windy-mail windy-connect}"
mkdir -p "$WORK"
log() { printf '[sync %s] %s\n' "$(date -u +%H:%M:%SZ)" "$*"; }