Address review action stabilization feedback

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
brennanb2025
2026-06-26 13:50:14 -07:00
co-authored by Orca
parent cf7cde8865
commit c4816cfef6
10 changed files with 95 additions and 4 deletions
@@ -245,6 +245,23 @@ describe('mobile source-control primary action decision parity', () => {
inFlightRemoteOpKind: 'pull',
upstreamStatus: { hasUpstream: true, ahead: 2, behind: 0 }
})
},
{
name: 'in-flight force push mirrors force push',
input: decisionInputs({
isRemoteOperationActive: true,
inFlightRemoteOpKind: 'force_push',
upstreamStatus: { hasUpstream: true, ahead: 2, behind: 0 }
})
},
{
name: 'in-flight push blocks committable candidate',
input: decisionInputs({
isRemoteOperationActive: true,
inFlightRemoteOpKind: 'push',
stagedCount: 1,
hasMessage: true
})
}
])('matches the shared commit-area decision for $name', ({ input }) => {
expect(resolveMobileSourceControlCommitAreaPrimaryActionDecision(input)).toEqual(
@@ -5,6 +5,8 @@ import {
type CreateReviewIntentKind
} from '../../../../shared/source-control-create-review-intent'
// Why: renderer APIs keep PR terminology for compatibility, while shared logic
// uses provider-neutral review terminology for PR/MR hosts.
export type CreatePrIntentKind = CreateReviewIntentKind
export type CreatePrIntentEligibility = CreateReviewIntentEligibility
@@ -152,9 +152,15 @@ function resolvePrimaryActionTitle(
{ value0: resolvePrimaryActionLabel(decision, inputs) }
)
case 'remote_operation_in_progress':
return 'Remote operation in progress…'
return translate(
'auto.components.right.sidebar.source.control.primary.action.6f7a8b9c0d',
'Remote operation in progress…'
)
case 'remote_operation_blocks_commit':
return 'Remote operation in progress — try again once it finishes'
return translate(
'auto.components.right.sidebar.source.control.primary.action.7f8a9b0c1d',
'Remote operation in progress — try again once it finishes'
)
case 'resolve_conflicts_before_commit':
return translate(
'auto.components.right.sidebar.source.control.primary.action.a6457b46a7',
@@ -237,7 +243,10 @@ function resolvePrimaryActionTitle(
{ value0: copy.reviewLabel }
)
case 'nothing_to_commit_up_to_date':
return 'Nothing to commit. Branch is up to date.'
return translate(
'auto.components.right.sidebar.source.control.primary.action.8f9a0b1c2d',
'Nothing to commit. Branch is up to date.'
)
case 'checking_review_creation':
return translate(
'auto.components.right.sidebar.source.control.primary.action.h3i4j5k607',
+3
View File
@@ -9061,6 +9061,8 @@
"2d8f185fbc": "Stage all changes before committing partially staged files",
"a6457b46a7": "Resolve conflicts before committing",
"484f45c439": "{{value0}} in progress…",
"6f7a8b9c0d": "Remote operation in progress…",
"7f8a9b0c1d": "Remote operation in progress — try again once it finishes",
"74fc171e99": "Force Push in progress…",
"16aee3a5c1": "Commit in progress…",
"e61b0d7a3c": "Check out a branch before publishing commits.",
@@ -9080,6 +9082,7 @@
"d8a4c0e369": "Authenticate before creating a {{value0}}.",
"e9b5d1f470": "Check out a branch before creating a {{value0}}.",
"f0c6e2a581": "This branch is not ready for a {{value0}} yet.",
"8f9a0b1c2d": "Nothing to commit. Branch is up to date.",
"h3i4j5k607": "Checking whether this branch can create a {{value0}}…"
}
}
+3
View File
@@ -9061,6 +9061,8 @@
"2d8f185fbc": "Prepare todos los cambios antes de enviar archivos parcialmente preparados",
"a6457b46a7": "Resolver conflictos antes de comprometerse",
"484f45c439": "{{value0}} en progreso…",
"6f7a8b9c0d": "Remote operation in progress…",
"7f8a9b0c1d": "Remote operation in progress — try again once it finishes",
"74fc171e99": "Empuje forzado en progreso...",
"16aee3a5c1": "Compromiso en progreso...",
"e61b0d7a3c": "Cambia a una rama antes de publicar commits.",
@@ -9080,6 +9082,7 @@
"d8a4c0e369": "Authenticate before creating a {{value0}}.",
"e9b5d1f470": "Check out a branch before creating a {{value0}}.",
"f0c6e2a581": "This branch is not ready for a {{value0}} yet.",
"8f9a0b1c2d": "Nothing to commit. Branch is up to date.",
"h3i4j5k607": "Checking whether this branch can create a {{value0}}…"
}
}
+3
View File
@@ -9061,6 +9061,8 @@
"2d8f185fbc": "部分的にステージングされたファイルを commit する前に、すべての変更をステージングします。",
"a6457b46a7": "commit する前に競合を解決する",
"484f45c439": "{{value0}} が進行中です…",
"6f7a8b9c0d": "Remote operation in progress…",
"7f8a9b0c1d": "Remote operation in progress — try again once it finishes",
"74fc171e99": "強制プッシュ中です…",
"16aee3a5c1": "Commit 中です…",
"e61b0d7a3c": "commits を公開する前にブランチをチェックアウトしてください。",
@@ -9080,6 +9082,7 @@
"d8a4c0e369": "Authenticate before creating a {{value0}}.",
"e9b5d1f470": "Check out a branch before creating a {{value0}}.",
"f0c6e2a581": "This branch is not ready for a {{value0}} yet.",
"8f9a0b1c2d": "Nothing to commit. Branch is up to date.",
"h3i4j5k607": "Checking whether this branch can create a {{value0}}…"
}
}
+3
View File
@@ -9061,6 +9061,8 @@
"2d8f185fbc": "부분적으로 준비된 파일을 commit 하기 전에 모든 변경 사항을 준비합니다.",
"a6457b46a7": "commit 하기 전에 충돌을 해결하세요.",
"484f45c439": "{{value0}} 진행 중…",
"6f7a8b9c0d": "Remote operation in progress…",
"7f8a9b0c1d": "Remote operation in progress — try again once it finishes",
"74fc171e99": "강제 푸시 진행 중…",
"16aee3a5c1": "Commit 진행 중…",
"e61b0d7a3c": "commits을 게시하기 전에 브랜치를 체크아웃하세요.",
@@ -9080,6 +9082,7 @@
"d8a4c0e369": "{{value0}}을(를) 만들기 전에 인증하세요.",
"e9b5d1f470": "{{value0}}을(를) 만들기 전에 브랜치를 체크아웃하세요.",
"f0c6e2a581": "이 브랜치는 아직 {{value0}}을(를) 만들 준비가 되지 않았습니다.",
"8f9a0b1c2d": "Nothing to commit. Branch is up to date.",
"h3i4j5k607": "이 브랜치에서 {{value0}}을(를) 만들 수 있는지 확인 중…"
}
}
+3
View File
@@ -9061,6 +9061,8 @@
"2d8f185fbc": "在提交部分暂存的文件之前暂存所有更改",
"a6457b46a7": "提交前解决冲突",
"484f45c439": "{{value0}} 正在进行中...",
"6f7a8b9c0d": "Remote operation in progress…",
"7f8a9b0c1d": "Remote operation in progress — try again once it finishes",
"74fc171e99": "强制推送正在进行中...",
"16aee3a5c1": "正在进行中……",
"e61b0d7a3c": "请先检出分支再发布 commits。",
@@ -9080,6 +9082,7 @@
"d8a4c0e369": "Authenticate before creating a {{value0}}.",
"e9b5d1f470": "Check out a branch before creating a {{value0}}.",
"f0c6e2a581": "This branch is not ready for a {{value0}} yet.",
"8f9a0b1c2d": "Nothing to commit. Branch is up to date.",
"h3i4j5k607": "Checking whether this branch can create a {{value0}}…"
}
}
@@ -157,4 +157,25 @@ describe('source-control primary action decision', () => {
expect(resolveSourceControlPrimaryActionDecision(input).kind).toBe('create_pr')
expect(resolveSourceControlCommitAreaPrimaryActionDecision(input).kind).toBe('commit')
})
it('returns disabled create review while hosted-review creation eligibility is loading', () => {
const result = resolveSourceControlPrimaryActionDecision(
inputs({
upstreamStatus: { hasUpstream: true, ahead: 0, behind: 0 },
hostedReviewCreation: {
provider: 'gitlab',
review: null,
canCreate: false,
blockedReason: null,
nextAction: null
},
isHostedReviewCreationLoading: true
})
)
expect(result).toMatchObject({
kind: 'create_pr',
titleIntent: 'checking_review_creation',
disabled: true
})
})
})
@@ -1,4 +1,5 @@
import { shouldForcePushWithLeaseForUpstream } from './git-upstream-status'
import { supportsHostedReviewCreation } from './hosted-review-creation-providers'
import { resolveCreateReviewIntentEligibility } from './source-control-create-review-intent'
import { resolveSourceControlPrimaryActionDuringRemoteOp } from './source-control-primary-action-in-flight'
import type {
@@ -32,7 +33,8 @@ export function resolveSourceControlPrimaryActionDecision(
branchCommitsAhead,
hasCurrentBranch = true,
canPushLinkedReviewWithoutUpstream = false,
isPrIntentInFlight = false
isPrIntentInFlight = false,
isHostedReviewCreationLoading = false
} = inputs
if (isPrIntentInFlight) {
@@ -69,6 +71,19 @@ export function resolveSourceControlPrimaryActionDecision(
}
}
if (
isHostedReviewCreationLoading &&
hostedReviewCreation &&
shouldOfferCreateReviewLoadingAction(hostedReviewCreation)
) {
return {
kind: 'create_pr',
labelIntent: 'create_pr',
titleIntent: 'checking_review_creation',
disabled: true
}
}
const createPrIntent = resolveCreatePrIntentDecision(inputs)
if (createPrIntent) {
return createPrIntent
@@ -192,6 +207,18 @@ export function resolveSourceControlPrimaryActionDecision(
}
}
function shouldOfferCreateReviewLoadingAction(
hostedReviewCreation: SourceControlPrimaryActionDecisionInputs['hostedReviewCreation']
): boolean {
if (!supportsHostedReviewCreation(hostedReviewCreation?.provider)) {
return false
}
return (
hostedReviewCreation.blockedReason !== 'existing_review' &&
hostedReviewCreation.blockedReason !== 'unsupported_provider'
)
}
export function resolveSourceControlCommitAreaPrimaryActionDecision(
inputs: SourceControlPrimaryActionDecisionInputs
): SourceControlPrimaryActionDecision {