Skip to content

Commit

Runner: checkout finds a run's commit after its branch moved on

A run checks out its own commit. When a newer push lands before the run starts, the depth-1 fetch of the branch brings only the new tip, and the fallback, a plain fetch, never reaches past a shallow boundary: checkout failed with "reference is not a tree" (deploy run #63, and the preview failure seen earlier). Now it asks for the commit itself, and failing that fetches with --unshallow.

syntaqxcommitted Parent3b9e617Browse files
1 file+19−40/1 viewed
+19−4
114114 return (false, BTreeMap::new());
115115 }
116116 let target = sha.clone().unwrap_or_else(|| "FETCH_HEAD".into());
117− // The commit may be further back than a shallow fetch reaches.
118− let present = Command::new("git").current_dir(&path).args(["cat-file", "-e", &format!("{target}^{{commit}}")]).status().is_ok_and(|s| s.success());
119− if !present && !self.fetch_retrying(&path, &["fetch", "--no-tags", "--quiet", "origin"], auth.as_deref()) {
120− return (false, BTreeMap::new());
117+ // The commit may be further back than a shallow fetch reaches: the
118+ // branch moved on after the run began, say. Ask for the commit
119+ // itself, and failing that the whole history; a plain fetch never
120+ // reaches past a shallow boundary.
121+ let has = |target: &str| Command::new("git").current_dir(&path).args(["cat-file", "-e", &format!("{target}^{{commit}}")]).status().is_ok_and(|s| s.success());
122+ if !has(&target) {
123+ let by_sha = sha.as_deref().is_some_and(|sha| {
124+ let mut args = vec!["fetch", "--no-tags", "--quiet"];
125+ if depth > 0 {
126+ args.push(&depth_arg);
127+ }
128+ args.extend(["origin", sha]);
129+ self.git(&path, &args, auth.as_deref()) && has(sha)
130+ });
131+ let shallow = path.join(".git").join("shallow").exists();
132+ let deepen: &[&str] = if shallow { &["fetch", "--no-tags", "--quiet", "--unshallow", "origin"] } else { &["fetch", "--no-tags", "--quiet", "origin"] };
133+ if !by_sha && !self.fetch_retrying(&path, deepen, auth.as_deref()) {
134+ return (false, BTreeMap::new());
135+ }
121136 }
122137 let checked_out = match &branch {
123138 Some(branch) => self.git(&path, &["checkout", "--quiet", "--force", "-B", branch, &target], None),