fix(tasks): hide repos without remote identity (#9898)

This commit is contained in:
余辉 2026-07-24 14:46:01 +08:00 committed by GitHub
parent 108a2ad41b
commit fa09d6fd8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 3 deletions

View File

@ -179,7 +179,6 @@ import {
readLinearBoardIssueDragData,
writeLinearBoardIssueDragData
} from '@/lib/linear-board-drag-payload'
import { isGitRepoKind } from '../../../shared/repo-kind'
import { getRepoExecutionHostId } from '../../../shared/execution-host'
import { projectHostSetupProjectionFromRepos } from '../../../shared/project-host-setup-projection'
import { TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY } from '../../../shared/protocol-version'
@ -238,6 +237,7 @@ import { findTaskPageJiraIssue } from '@/components/task-page-jira-cache-selecto
import { getRepoBackedTaskEmptyState } from '@/components/task-page-empty-state'
import {
getDefaultTaskRepoSelection,
getTaskEligibleRepos,
getTaskProjectPickerGroups,
normalizeTaskRepoSelection
} from '@/components/task-page-default-repo-selection'
@ -3141,7 +3141,7 @@ export default function TaskPage(): React.JSX.Element {
const linearConnected = linearStatusCurrent && linearStatus.connected
const jiraConnected = jiraStatusCurrent && jiraStatus.connected
const submitShortcutLabel = getScreenSubmitShortcutLabel()
const eligibleRepos = useMemo(() => repos.filter((repo) => isGitRepoKind(repo)), [repos])
const eligibleRepos = useMemo(() => getTaskEligibleRepos(repos), [repos])
// Why: initial selection precedence — explicit preselection > persisted defaultRepoSelection > all eligible; preselection wins so "open tasks for this repo" lands single-repo.
const resolvedInitialSelection = useMemo<ReadonlySet<string>>(() => {

View File

@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
import type { Repo } from '../../../shared/types'
import {
getDefaultTaskRepoSelection,
getTaskEligibleRepos,
getTaskProjectPickerGroups,
getTaskProjectPickerRepos,
normalizeTaskRepoSelection
@ -18,6 +19,51 @@ function repo(overrides: Partial<Repo> & Pick<Repo, 'id'>): Repo {
}
}
describe('getTaskEligibleRepos', () => {
it('keeps only Git repos with a resolvable remote identity', () => {
const eligible = getTaskEligibleRepos([
repo({ id: 'github-upstream', upstream: { owner: 'stablyai', repo: 'orca' } }),
repo({
id: 'github-icon',
repoIcon: {
type: 'image',
src: 'https://github.com/stablyai.png?size=64',
source: 'github',
label: 'stablyai/orca'
}
}),
repo({
id: 'gitlab-remote',
gitRemoteIdentity: {
canonicalKey: 'gitlab.example.com/team/orca',
remoteName: 'origin',
remoteUrl: 'git@gitlab.example.com:team/orca.git'
}
}),
repo({ id: 'local-only' }),
repo({
id: 'incomplete-remote',
gitRemoteIdentity: {
canonicalKey: 'gitlab.example.com/team/incomplete',
remoteName: '',
remoteUrl: 'git@gitlab.example.com:team/incomplete.git'
}
}),
repo({
id: 'folder-with-remote',
kind: 'folder',
upstream: { owner: 'stablyai', repo: 'docs' }
})
])
expect(eligible.map((candidate) => candidate.id)).toEqual([
'github-upstream',
'github-icon',
'gitlab-remote'
])
})
})
describe('getDefaultTaskRepoSelection', () => {
it('selects one source per logical GitHub project', () => {
const selection = getDefaultTaskRepoSelection([

View File

@ -1,5 +1,9 @@
import { getRepoExecutionHostId, LOCAL_EXECUTION_HOST_ID } from '../../../shared/execution-host'
import { getProjectIdentityKey } from '../../../shared/project-host-setup-projection'
import {
getProjectIdentityKey,
hasProjectRemoteIdentity
} from '../../../shared/project-host-setup-projection'
import { isGitRepoKind } from '../../../shared/repo-kind'
import type { Repo } from '../../../shared/types'
export type TaskProjectPickerGroup = {
@ -8,6 +12,10 @@ export type TaskProjectPickerGroup = {
sources: Repo[]
}
export function getTaskEligibleRepos(repos: readonly Repo[]): Repo[] {
return repos.filter((repo) => isGitRepoKind(repo) && hasProjectRemoteIdentity(repo))
}
export function getDefaultTaskRepoSelection(repos: readonly Repo[]): Set<string> {
const selectedByProject = new Map<string, Repo>()
for (const repo of repos) {

View File

@ -80,6 +80,12 @@ export function isGitHubBackedRepo(
return getProjectProviderIdentity(repo) !== null
}
export function hasProjectRemoteIdentity(
repo: Pick<Repo, 'upstream' | 'repoIcon' | 'gitRemoteIdentity'>
): boolean {
return getProjectProviderIdentity(repo) !== null || getProjectGitRemoteIdentity(repo) !== null
}
export function getProjectIdentityKey(
repo: Pick<Repo, 'id' | 'upstream' | 'repoIcon' | 'gitRemoteIdentity'>
): string {