mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 16:03:17 +00:00
Add pending host setup action in project settings
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -504,6 +504,8 @@ Already partially landed:
|
||||
runtime RPC, and CLI for independent setup/provisioning metadata
|
||||
- renderer-store lifecycle actions for project-host setup create, update, and
|
||||
delete, routed by setup-owning host
|
||||
- project settings action for creating pending setup/provisioning metadata on a
|
||||
known host before a checkout path exists
|
||||
|
||||
Not complete yet:
|
||||
|
||||
|
||||
@@ -508,6 +508,8 @@ Already partially landed:
|
||||
runtime RPC, and CLI for independent setup/provisioning metadata
|
||||
- renderer-store lifecycle actions for project-host setup create, update, and
|
||||
delete, routed by setup-owning host
|
||||
- project settings action for creating pending setup/provisioning metadata on a
|
||||
known host before a checkout path exists
|
||||
|
||||
Not complete yet:
|
||||
|
||||
|
||||
@@ -426,6 +426,8 @@ Already partially landed:
|
||||
runtime RPC, and CLI for independent setup/provisioning metadata
|
||||
- renderer-store lifecycle actions for project-host setup create, update, and
|
||||
delete, routed by setup-owning host
|
||||
- project settings action for creating pending setup/provisioning metadata on a
|
||||
known host before a checkout path exists
|
||||
|
||||
Still needed:
|
||||
|
||||
|
||||
@@ -785,6 +785,9 @@ Landed so far:
|
||||
- Added renderer-store lifecycle actions for first-class setup create, update,
|
||||
and delete. Runtime-owned setups route through their owning runtime instead
|
||||
of whichever host is currently focused.
|
||||
- Added a project settings action to create pending project-host setup metadata
|
||||
for a known host without requiring an existing checkout path. This lets the UI
|
||||
represent setup/provisioning intent before import/clone/provisioning finishes.
|
||||
- Added tests for local repos, SSH repos, same-provider multi-host grouping,
|
||||
no-identity same-name non-grouping, selector cache behavior, persistence
|
||||
backfill, repo mutation synchronization, renderer hydration, runtime RPC
|
||||
@@ -815,8 +818,8 @@ Important limitation:
|
||||
across load and repo mutations, but the UI/API still mostly creates setups
|
||||
through repo-backed import/clone paths. First-class setup update now exists,
|
||||
first-class setup create/update/delete now exist for independent metadata and
|
||||
are exposed through the renderer store, but actual provisioning execution and
|
||||
full UI flows are still future work.
|
||||
are exposed through the renderer store/settings, but actual provisioning
|
||||
execution and full UI flows are still future work.
|
||||
|
||||
Remaining end-to-end work:
|
||||
|
||||
@@ -824,7 +827,7 @@ Remaining end-to-end work:
|
||||
- finish SSH clone streamed-progress parity, provisioning, and bulk setup-on-host
|
||||
flows
|
||||
- add actual provisioning execution APIs instead of only recording independent
|
||||
setup/provisioning metadata
|
||||
setup/provisioning metadata and intent
|
||||
- split settings into explicit client, host, project, and project-host setup
|
||||
scopes
|
||||
- validate the default project-first sidebar view in Electron and continue
|
||||
|
||||
@@ -266,4 +266,58 @@ describe('RepositoryHostSetupsSection', () => {
|
||||
expect(openSettingsPage).toHaveBeenCalledTimes(1)
|
||||
expect(openSettingsTarget).toHaveBeenCalledWith({ pane: 'repo', repoId: 'remote-repo' })
|
||||
})
|
||||
|
||||
it('creates pending setup metadata for a known host without requiring a path', async () => {
|
||||
const createProjectHostSetup = vi.fn().mockResolvedValue({
|
||||
project: makeProject({ id: 'github:stablyai/orca' }),
|
||||
setup: makeSetup({
|
||||
id: 'gpu-setup',
|
||||
projectId: 'github:stablyai/orca',
|
||||
repoId: '',
|
||||
hostId: 'runtime:gpu',
|
||||
path: '',
|
||||
setupState: 'not-set-up',
|
||||
setupMethod: 'provisioned'
|
||||
})
|
||||
})
|
||||
const localRepo = makeRepo({
|
||||
id: 'local-repo',
|
||||
displayName: 'Orca',
|
||||
path: '/Users/alice/orca'
|
||||
})
|
||||
useAppStore.setState({
|
||||
repos: [localRepo],
|
||||
projects: [makeProject({ id: 'github:stablyai/orca' })],
|
||||
projectHostSetups: [
|
||||
makeSetup({
|
||||
id: 'local-repo',
|
||||
projectId: 'github:stablyai/orca',
|
||||
repoId: 'local-repo',
|
||||
hostId: 'local',
|
||||
path: '/Users/alice/orca'
|
||||
})
|
||||
],
|
||||
settings: { activeRuntimeEnvironmentId: 'gpu' } as never,
|
||||
createProjectHostSetup
|
||||
})
|
||||
|
||||
renderSection(localRepo)
|
||||
|
||||
const trackButton = Array.from(container.querySelectorAll('button')).find(
|
||||
(button) => button.textContent === 'Track setup'
|
||||
)
|
||||
expect(trackButton).toBeTruthy()
|
||||
|
||||
await act(async () => {
|
||||
trackButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
})
|
||||
|
||||
expect(createProjectHostSetup).toHaveBeenCalledWith({
|
||||
projectId: 'github:stablyai/orca',
|
||||
hostId: 'runtime:gpu',
|
||||
displayName: 'Orca',
|
||||
setupState: 'not-set-up',
|
||||
setupMethod: 'provisioned'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -98,6 +98,7 @@ export function RepositoryHostSetupsSection({
|
||||
const openSettingsPage = useAppStore((state) => state.openSettingsPage)
|
||||
const openSettingsTarget = useAppStore((state) => state.openSettingsTarget)
|
||||
const setupProjectExistingFolder = useAppStore((state) => state.setupProjectExistingFolder)
|
||||
const createProjectHostSetup = useAppStore((state) => state.createProjectHostSetup)
|
||||
const deleteProjectHostSetup = useAppStore((state) => state.deleteProjectHostSetup)
|
||||
const sshTargetLabels = useAppStore((state) => state.sshTargetLabels)
|
||||
const activeRuntimeEnvironmentId = useAppStore(
|
||||
@@ -123,6 +124,7 @@ export function RepositoryHostSetupsSection({
|
||||
const [setupPath, setSetupPath] = useState('')
|
||||
const [setupKind, setSetupKind] = useState<'git' | 'folder'>('git')
|
||||
const [isSettingUp, setIsSettingUp] = useState(false)
|
||||
const [isCreatingPendingSetup, setIsCreatingPendingSetup] = useState(false)
|
||||
const [deletingSetupId, setDeletingSetupId] = useState<string | null>(null)
|
||||
const setupTargetHostId = selectedSetupHostId ?? setupHostOptions[0]?.id ?? null
|
||||
|
||||
@@ -309,6 +311,39 @@ export function RepositoryHostSetupsSection({
|
||||
? translate('auto.components.settings.RepositoryPane.settingUpHost', 'Importing...')
|
||||
: translate('auto.components.settings.RepositoryPane.setupHost', 'Import')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={!setupTargetHostId || isCreatingPendingSetup}
|
||||
onClick={async () => {
|
||||
if (!setupTargetHostId || !selectedProjectHostSetup) {
|
||||
return
|
||||
}
|
||||
setIsCreatingPendingSetup(true)
|
||||
const result = await createProjectHostSetup({
|
||||
projectId: selectedProjectHostSetup.projectId,
|
||||
hostId: setupTargetHostId,
|
||||
displayName: repo.displayName,
|
||||
setupState: 'not-set-up',
|
||||
setupMethod: 'provisioned'
|
||||
})
|
||||
setIsCreatingPendingSetup(false)
|
||||
if (result) {
|
||||
setSelectedSetupHostId(null)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isCreatingPendingSetup
|
||||
? translate(
|
||||
'auto.components.settings.RepositoryPane.creatingPendingSetup',
|
||||
'Creating...'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.settings.RepositoryPane.createPendingSetup',
|
||||
'Track setup'
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -5065,6 +5065,8 @@
|
||||
"setupKindFolder": "Folder",
|
||||
"settingUpHost": "Importing...",
|
||||
"setupHost": "Import",
|
||||
"creatingPendingSetup": "Creating...",
|
||||
"createPendingSetup": "Track setup",
|
||||
"499a437335": "Identity"
|
||||
},
|
||||
"RepositorySourceControlAiActionRows": {
|
||||
|
||||
@@ -5045,6 +5045,8 @@
|
||||
"setupKindFolder": "フォルダー",
|
||||
"settingUpHost": "インポート中...",
|
||||
"setupHost": "インポート",
|
||||
"creatingPendingSetup": "作成中...",
|
||||
"createPendingSetup": "セットアップを追跡",
|
||||
"499a437335": "身元"
|
||||
},
|
||||
"RepositorySourceControlAiActionRows": {
|
||||
|
||||
@@ -5045,6 +5045,8 @@
|
||||
"setupKindFolder": "폴더",
|
||||
"settingUpHost": "가져오는 중...",
|
||||
"setupHost": "가져오기",
|
||||
"creatingPendingSetup": "생성 중...",
|
||||
"createPendingSetup": "설정 추적",
|
||||
"499a437335": "신원"
|
||||
},
|
||||
"RepositorySourceControlAiActionRows": {
|
||||
|
||||
@@ -5045,6 +5045,8 @@
|
||||
"setupKindFolder": "文件夹",
|
||||
"settingUpHost": "正在导入...",
|
||||
"setupHost": "导入",
|
||||
"creatingPendingSetup": "正在创建...",
|
||||
"createPendingSetup": "跟踪设置",
|
||||
"499a437335": "身份"
|
||||
},
|
||||
"RepositorySourceControlAiActionRows": {
|
||||
|
||||
Reference in New Issue
Block a user