fix: skip the deploy PR when the git sync push committed nothing (#11076)

Claude-Session: https://claude.ai/code/session_01WVDyzszjbvSssMN6HpnZZw

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-09-10 22:45:34 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent d87f089288
commit 8ecbd339ee
2 changed files with 64 additions and 1 deletions
+1 -1
View File
@@ -183,7 +183,7 @@ pub enum ObjectType {
DatatableMigration,
}
pub const LATEST_GIT_SYNC_SCRIPT_PATH: &str = "hub/28949/sync-script-to-git-repo-windmill";
pub const LATEST_GIT_SYNC_SCRIPT_PATH: &str = "hub/28958/sync-script-to-git-repo-windmill";
/// Hub script that applies a repository's state back into a workspace
/// (the repo → Windmill / "pull" direction). Same script the UI runs from
+63
View File
@@ -771,6 +771,69 @@ class TestGitSync(GitSyncTestBase):
f"Expected folder-grouped branch name containing '{expected_folder_part}', got: {deploy_branch}",
)
def _new_sync_job_results(self, seen: set, path: str) -> list:
"""Results of the deploy callbacks not in `seen` that pushed `path`."""
results = []
for listed in self._client.get_completed_jobs(job_kinds="deploymentcallback"):
if listed["id"] in seen:
continue
job = self._client._client.get(
f"/api/w/{self._client._workspace}/jobs_u/get/{listed['id']}"
).json()
items = (job.get("args") or {}).get("items") or []
if any(item.get("path") == path for item in items):
results.append(job.get("result"))
return results
def test_promotion_push_reports_whether_it_pushed(self):
"""The push job's result says whether a commit was pushed, and the
PR-on-deploy hook relies on it: on `pushed: false` it skips, otherwise
it asks the host for a PR on the deploy branch, which for a push that
committed nothing was never created (GitHub: 422 "head invalid")."""
repo_name, _ = self._create_test_repo()
resource_path = self._setup_git_sync_resource(repo_name)
# Saving the config is itself a settings deploy, and it commits nothing:
# the repo has no wmill.yaml including settings, so none are pulled.
seen = {j["id"] for j in self._client.get_completed_jobs(job_kinds="deploymentcallback")}
self._configure_single_repo_sync(
resource_path,
include_type=["script", "settings"],
use_individual_branch=True,
group_by_folder=True,
)
self._wait_until(
lambda: self._new_sync_job_results(seen, "settings.yaml"),
timeout=90,
message="no push job for the settings deploy",
)
results = self._new_sync_job_results(seen, "settings.yaml")
self.assertEqual(
[(r or {}).get("pushed") for r in results],
[False],
f"a settings deploy that committed nothing must report pushed: false, got: {results}",
)
folder_name = unique_name("pushed")
self._create_folder(folder_name)
seen = {j["id"] for j in self._client.get_completed_jobs(job_kinds="deploymentcallback")}
script_path = f"f/{folder_name}/{unique_name('script')}"
self._client.create_script(
path=script_path,
content=ts_script("return 'pushed'"),
language="bun",
)
self._wait_until(
lambda: self._new_sync_job_results(seen, script_path),
timeout=90,
message=f"no push job for {script_path}",
)
results = self._new_sync_job_results(seen, script_path)
self.assertTrue(
all((r or {}).get("pushed") is True for r in results),
f"a deploy that committed must report pushed: true, got: {results}",
)
# ──────────────────────────────────────────────────
# Exclude path filtering
# ──────────────────────────────────────────────────