fix: refuse to finish a check whose repository has been repointed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75
This commit is contained in:
hugocasa
2026-09-03 13:35:20 +02:00
co-authored by Claude Opus 5
parent ed3cb9acb5
commit 5eecf0e8b1
3 changed files with 21 additions and 3 deletions
+1 -1
View File
@@ -1 +1 @@
39791c7861bb00c21045536df5c173856313dad5
889d277d59d818b9ebe0a936888f84cb112e7245
+5 -2
View File
@@ -4683,8 +4683,11 @@ async fn maintain_git_credentials_inner(db: &Pool<Postgres>) -> error::Result<()
// settings row survives, and rotating a token for one would be pure damage.
// Least-recently-checked first, so a pass that runs out of budget resumes
// where it stopped instead of re-checking the same head of the list forever.
// A repository with no recorded credential sorts first and costs only a
// database round trip: it has no token to introspect.
// A repository with no recorded credential sorts first and stays there,
// which is deliberate: it has no token to introspect, so it costs a few
// database queries and nothing else. Tens of thousands of them would have to
// exist in one instance before they consumed the pass budget ahead of a
// repository that does have a token.
let rows = sqlx::query!(
r#"SELECT ws.workspace_id, ws.git_sync
FROM workspace_settings ws
@@ -824,6 +824,11 @@ struct GitSyncCheck {
/// carry one; the resource path on the job is what is used now.
#[serde(default)]
repo_url: Option<String>,
/// Host and path of the repository the check was created on, with no
/// credential in it. The resource path is mutable, so this is what proves
/// the resource still points where the check lives.
#[serde(default)]
repo: Option<String>,
#[serde(default)]
pr_number: Option<i64>,
#[serde(default)]
@@ -1406,6 +1411,16 @@ async fn maybe_post_git_sync_check(
return;
}
};
// A resource repointed while the diff was running would otherwise close a
// check, or post a preview, on a repository that has nothing to do with it.
if check.repo.is_some()
&& windmill_common::git_sync_ee::repo_identity(&repo_url) != check.repo
{
tracing::warn!(
"git sync-check: the repository moved since the check was created; leaving it alone"
);
return;
}
// "In sync" on a PR that visibly changes files reads as a bug when those
// files are outside the repo's sync filters — say what the scope is.
let scope_note = if !is_deploy && success {