Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh

Commit

An open pull request's page no longer asks repos whether it is behind a second time, and anyone's ready pull request says it is ready to merge. Signed in, flagon-io/g1t #41 took 5 to 10 seconds and once failed: get_pull worked out whether it is behind (stored with its mergeability for its head, as merge_choices does), then the merge gate asked repos `behind` again on every view, a walk of the git store that took up to 5 s (Workers Logs: /rpc/behind 4.9 s, 649 ms CPU). The gate now takes what the page already worked out (merge_gate_seen), as does the lifecycle's own gate; merging and the queue still ask repos as they did. And the lifecycle was worked out only for pull requests g1t's agent made (managed = 1), which since g1t stopped running agents of its own is none, so a person's pull request that met everything its branch asks for (#41: CI passed, no approvals required) said nothing about being ready. Every open pull request now gets one; only one g1t manages merges by itself (auto_merge is gated on managed), and anyone else's draft still gets none, so its page does not keep refreshing. Lists keep showing a lifecycle only for managed pull requests, since nothing yet refreshes a stored one for the rest. Checked: cargo test -p g1t-work (189 passing).

G1t-Session:
ses_01m4y12gdde2r9q832m7xk87kd
syntaqxcommitted Parent8e30fb4Browse files
3 files+35−140/3 viewed
+1−1
16311631 self.settings_on(&repo, &pull),
16321632 async {
16331633 if pull.status.is_active() {
1634− self.merge_gate(&repo, &pull, viewer.as_ref(), false, true).await.map(Some)
1634+ self.merge_gate_seen(&repo, &pull, viewer.as_ref(), behind).await.map(Some)
16351635 } else {
16361636 Ok(None)
16371637 }
+17−9
11 //! Where a pull request stands, and merging it on the repository's say.
22 //!
3−//! A pull request g1t's agent once made (`made_by_g1t`, `managed = 1`)
4−//! still shows where it stands: its checks, the approvals the branch
5−//! wants, the merge queue, and whether a person has to step in. Where the
6−//! repository's settings say ready pull requests land by themselves
7−//! (`auto_merge`), such a pull request is merged here once everything its
8−//! branch's rules ask for is met, attributed to `g1t` (`POLICY_ACTOR_ID`).
3+//! Every open pull request shows where it stands: its checks, the
4+//! approvals the branch wants, the merge queue, whether a person has to
5+//! step in, and when it is ready for whoever merges it. Only one g1t's
6+//! agent once made (`made_by_g1t`, `managed = 1`) is merged here by
7+//! itself, where the repository's settings say ready pull requests land
8+//! by themselves (`auto_merge`), once everything its branch's rules ask
9+//! for is met, attributed to `g1t` (`POLICY_ACTOR_ID`). Anyone else's
10+//! waits for a person to merge it.
911 //!
1012 //! A merge asked for while a pull request is behind is recorded here
1113 //! (`request_landing`). Once the push that brings it up to date arrives
369371 .await?
370372 }
371373 };
372− let Some(progress) = progress.filter(|progress| progress.managed != 0) else {
374+ let Some(progress) = progress else {
373375 return Ok(None);
374376 };
377+ // g1t merges by itself only what it is seeing through. Anyone
378+ // else's draft is theirs to finish, with nothing to say yet.
379+ let managed = progress.managed != 0;
380+ if !managed && pull.status == PullStatus::Draft {
381+ return Ok(None);
382+ }
375383 let now = rfc3339(now_ms());
376384 let working_on = progress
377385 .working_until
385393 // merges by itself: what people must still do, and whether an
386394 // agent's change may land here unattended.
387395 let gate = match self.repo_for(pull).await? {
388− Some(repo) => Some(self.merge_gate(&repo, pull, Some(&User::system(&repo.namespace)), false, true).await?),
396+ Some(repo) => Some(self.merge_gate_seen(&repo, pull, Some(&User::system(&repo.namespace)), behind).await?),
389397 None => None,
390398 };
391399 let rules_allow_auto_merge = gate
399407 revisions: progress.revisions,
400408 behind,
401409 conflicting: self.conflicting_files(pull).await?.is_some(),
402− auto_merge: settings.auto_merge && rules_allow_auto_merge,
410+ auto_merge: managed && settings.auto_merge && rules_allow_auto_merge,
403411 require_up_to_date: settings.require_up_to_date,
404412 approvals_missing: gate.as_ref().and_then(|gate| gate.people_gap()),
405413 person_request: self.person_request(pull, progress.revised_at.as_deref()).await?,
+17−4
791791 ignore_checks: bool,
792792 honor_bypass: bool,
793793 ) -> Result<Gate> {
794− self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, None).await
794+ self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, None, None).await
795795 }
796796
797+ /// `merge_gate` with whether it is behind already worked out (from
798+ /// what was stored with its mergeability, or asked once for this
799+ /// request), so that showing a pull request does not ask repos again.
800+ pub(crate) async fn merge_gate_seen(&self, repo: &Repo, pull: &Pull, actor: Option<&User>, behind: bool) -> Result<Gate> {
801+ self.merge_gate_at(repo, pull, actor, false, true, None, None, Some(behind)).await
802+ }
803+
797804 /// `merge_gate` for a merge by `method`: rules that allow only some
798805 /// methods, and linear history, judge it too. Without a method they do
799806 /// not, as for showing what a pull request still needs.
806813 honor_bypass: bool,
807814 method: MergeMethod,
808815 ) -> Result<Gate> {
809− self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, Some(method)).await
816+ self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, Some(method), None).await
810817 }
811818
812819 /// Re-evaluate current reviews and rules against the exact combined state.
828835 ) -> Result<Gate> {
829836 // The tested state was built by the entry's method (queue.rs), which
830837 // the rules judge as they are now.
831− let gate = self.merge_gate_at(repo, pull, Some(actor), false, true, Some((commit, statuses)), Some(method)).await?;
838+ let gate = self.merge_gate_at(repo, pull, Some(actor), false, true, Some((commit, statuses)), Some(method), None).await?;
832839 Ok(if landing_honors_bypass(actor, bypass_rules) { gate } else { gate.without_bypass() })
833840 }
834841
842+ #[allow(clippy::too_many_arguments)]
835843 async fn merge_gate_at(
836844 &self,
837845 repo: &Repo,
841849 honor_bypass: bool,
842850 tested: Option<(&str, Vec<g1t_contracts::work::CommitStatus>)>,
843851 method: Option<MergeMethod>,
852+ known_behind: Option<bool>,
844853 ) -> Result<Gate> {
845854 let tested_commit = tested.as_ref().map(|(commit, _)| *commit);
846855 let tested_statuses = tested.as_ref().map(|(_, statuses)| statuses.clone());
880889 async {
881890 // The repository service verifies ancestry and CAS for the
882891 // combined commit; the original PR may legitimately be behind.
883− if tested_commit.is_some() { Ok(false) } else { self.is_behind(pull).await }
892+ match (tested_commit, known_behind) {
893+ (Some(_), _) => Ok(false),
894+ (None, Some(behind)) => Ok(behind),
895+ (None, None) => self.is_behind(pull).await,
896+ }
884897 },
885898 async {
886899 if needs_owners { self.code_owners_gap(&owners_settings, pull).await } else { Ok(None) }

Comments

Sign in to comment.