mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 00:03:20 +00:00
Defect 1: the typed GitLab MR search query was dropped before reaching the API. Thread query?: string end-to-end through the renderer effect, the source-lookup, the preload/RPC args, and the desktop IPC handlers (which previously passed a hardcoded undefined), and honor it on both the glab REST path (&search=) and the cwd-inferred 'glab mr list' fallback. Defect 2: when MR base resolution failed the renderer silently returned, leaving baseBranch undefined so the worktree was created off the repo default branch (origin/master) with no feedback. Surface the failure via toast and clear stale base state, mirroring the GitHub PR path. Also make resolveManagedMrBase resilient to an optional compare-base (target branch) fetch failure: degrade gracefully by dropping compareBaseRef instead of aborting, so a merged MR with a deleted target ref still resolves to its valid source-branch base. Fixes #6263 Co-authored-by: Orca <help@stably.ai>
62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
import type { MRListState } from '../../shared/types'
|
|
|
|
export type GitLabIssueListState = 'opened' | 'closed' | 'all'
|
|
|
|
export function normalizeGitLabPositiveInteger(
|
|
value: unknown,
|
|
fallback: number,
|
|
max: number
|
|
): number {
|
|
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
return fallback
|
|
}
|
|
return Math.min(Math.max(1, Math.trunc(value)), max)
|
|
}
|
|
|
|
export function normalizeGitLabMRListState(value: unknown): MRListState {
|
|
return value === 'merged' || value === 'closed' || value === 'all' ? value : 'opened'
|
|
}
|
|
|
|
export function normalizeGitLabIssueListState(value: unknown): GitLabIssueListState {
|
|
return value === 'closed' || value === 'all' ? value : 'opened'
|
|
}
|
|
|
|
// Why: cap the free-text MR search at the same byte budget the renderer
|
|
// enforces (SMART_WORKSPACE_SOURCE_QUERY_MAX_BYTES) so the RPC/SSH path —
|
|
// which can be driven by callers other than the desktop input — can't push
|
|
// an unbounded string into the glab `&search=` query.
|
|
const GITLAB_SEARCH_QUERY_MAX_BYTES = 2048
|
|
|
|
export function normalizeGitLabSearchQuery(value: unknown): string | undefined {
|
|
if (typeof value !== 'string') {
|
|
return undefined
|
|
}
|
|
const trimmed = value.trim()
|
|
if (!trimmed) {
|
|
return undefined
|
|
}
|
|
return Buffer.byteLength(trimmed, 'utf8') > GITLAB_SEARCH_QUERY_MAX_BYTES ? undefined : trimmed
|
|
}
|
|
|
|
export function normalizeGitLabIssueAssignee(value: unknown): '@me' | undefined {
|
|
// Why: the renderer only exposes "Assigned to me"; accepting arbitrary
|
|
// values would turn preload/RPC boundaries into a generic glab flag surface.
|
|
return value === '@me' ? '@me' : undefined
|
|
}
|
|
|
|
export function normalizeGitLabIssueListArgs(args: {
|
|
state?: unknown
|
|
assignee?: unknown
|
|
limit?: unknown
|
|
}): {
|
|
state: GitLabIssueListState
|
|
assignee: '@me' | undefined
|
|
limit: number
|
|
} {
|
|
return {
|
|
state: normalizeGitLabIssueListState(args.state),
|
|
assignee: normalizeGitLabIssueAssignee(args.assignee),
|
|
limit: normalizeGitLabPositiveInteger(args.limit, 20, 100)
|
|
}
|
|
}
|