mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
* fix(ssh): let fork-PR worktrees add their contributor remote via the relay Creating a workspace from a fork PR on an SSH host failed with "Destructive git remote operations are not allowed via exec". The relay's git.exec allowlist blocked every `remote` write subcommand, but SSH fork-PR creation has to run `git remote add <fork> <url>` on the host before it can fetch and track the contributor's branch, so the whole create aborted. Allow exactly the two shapes that flow needs -- `remote add <name> <url>` and `remote remove <name>` -- validated with the same remote-name and URL rules the relay already applies to every pushTarget-carrying RPC. Everything else (set-url, rename, prune, extra operands, flags before the action) stays blocked, and the URL must be a github.com clone/ssh URL, so no new reach is granted beyond what push/fetch already accept. `remote remove` was blocked too, which silently leaked fork remotes on SSH hosts: worktree removal swallows the cleanup error. It works again now. A host still running an older relay gets an actionable "reconnect to deploy the latest relay" message instead of the raw policy error. * test(git-exec): pin remote read/write mutation classification Misclassifying `git remote` / `remote get-url` as mutating would flush the relay and SSH provider git read caches on every remote probe, so pin both directions.
65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
/**
|
|
* The relay's git.exec must carry the fork-PR remote setup that SSH worktree
|
|
* creation performs: adding the contributor's fork as a remote, and dropping it
|
|
* again when the last worktree using it is removed.
|
|
*/
|
|
import { describe, expect, it, beforeEach, afterEach } from 'vitest'
|
|
import { execFileSync } from 'node:child_process'
|
|
import { gitInit, type MockDispatcher } from './git-handler-test-setup'
|
|
import {
|
|
createGitHandlerRelay,
|
|
createGitTempDir,
|
|
removeGitTempDir
|
|
} from './git-handler-test-harness'
|
|
|
|
const FORK_REMOTE = 'pr-contributor-orca'
|
|
const FORK_URL = 'https://github.com/contributor/orca.git'
|
|
|
|
describe('GitHandler git.exec fork remote', () => {
|
|
let dispatcher: MockDispatcher
|
|
let tmpDir: string
|
|
|
|
beforeEach(() => {
|
|
tmpDir = createGitTempDir()
|
|
;({ dispatcher } = createGitHandlerRelay())
|
|
gitInit(tmpDir)
|
|
})
|
|
|
|
afterEach(async () => {
|
|
await removeGitTempDir(tmpDir)
|
|
})
|
|
|
|
function configuredRemotes(): string {
|
|
return execFileSync('git', ['remote'], { cwd: tmpDir, encoding: 'utf-8' }).trim()
|
|
}
|
|
|
|
it('adds and removes the fork remote', async () => {
|
|
await dispatcher.callRequest('git.exec', {
|
|
args: ['remote', 'add', FORK_REMOTE, FORK_URL],
|
|
cwd: tmpDir
|
|
})
|
|
expect(configuredRemotes()).toBe(FORK_REMOTE)
|
|
|
|
const url = (await dispatcher.callRequest('git.exec', {
|
|
args: ['remote', 'get-url', FORK_REMOTE],
|
|
cwd: tmpDir
|
|
})) as { stdout: string }
|
|
expect(url.stdout.trim()).toBe(FORK_URL)
|
|
|
|
await dispatcher.callRequest('git.exec', {
|
|
args: ['remote', 'remove', FORK_REMOTE],
|
|
cwd: tmpDir
|
|
})
|
|
expect(configuredRemotes()).toBe('')
|
|
})
|
|
|
|
it('still refuses to repoint an existing remote', async () => {
|
|
await expect(
|
|
dispatcher.callRequest('git.exec', {
|
|
args: ['remote', 'set-url', 'origin', FORK_URL],
|
|
cwd: tmpDir
|
|
})
|
|
).rejects.toThrow('Destructive git remote operations are not allowed via exec')
|
|
})
|
|
})
|