An expanded card now marks a draft ready for review and merges a change request that the host would merge now: - The forge seam gains provider actions `markReady` and `merge`, which return a typed `ForgeActionFailure`; the registry polls a watched change request at once after either settles. Snapshots carry `mergeReady` and the `mergeMethods` the repository allows, the user's usual one first. - GitHub marks ready with `gh pr ready` and merges through the REST merge endpoint with the head SHA the card showed, so new commits refuse the merge; it never enables auto-merge, joins a merge queue, or deletes the head branch. - The panel Remote acts only on visible bindings of the Session, and the card offers 标记为可评审 for drafts and a 合并 menu with the allowed methods and a confirmation, reporting each outcome in a toast. - The forge panel e2e replaces the worktree branch before the ARIA capture normalizes durations, so a random suffix no longer breaks it.
75 lines
2.8 KiB
TypeScript
75 lines
2.8 KiB
TypeScript
import type { ChangeRequestRef, ForgeRepository } from '@deepseek-ai/dsh-experimental-forge'
|
|
|
|
/** Repository on github.com used across the provider tests. */
|
|
export const demo: ForgeRepository = { forge: 'github', host: 'github.com', owner: 'octo', name: 'demo' }
|
|
|
|
/** Build a pull request reference in `demo` or another repository. */
|
|
export function pull(number: number, repository: ForgeRepository = demo): ChangeRequestRef {
|
|
return { repository, number }
|
|
}
|
|
|
|
/** One CheckRun context node as GitHub returns it. */
|
|
export function checkRun(name: string, status: string, conclusion: string | null, workflow: string | null = 'ci'): Record<string, unknown> {
|
|
return {
|
|
__typename: 'CheckRun',
|
|
name,
|
|
status,
|
|
conclusion,
|
|
detailsUrl: `https://github.com/octo/demo/actions/runs/1/job/${name}`,
|
|
startedAt: status === 'QUEUED' ? null : '2026-10-09T01:00:00Z',
|
|
completedAt: status === 'COMPLETED' ? '2026-10-09T01:02:07Z' : null,
|
|
checkSuite: workflow === null ? { workflowRun: null } : { workflowRun: { workflow: { name: workflow } } },
|
|
}
|
|
}
|
|
|
|
/** One StatusContext node as GitHub returns it. */
|
|
export function statusContext(context: string, state: string): Record<string, unknown> {
|
|
return { __typename: 'StatusContext', context, state, targetUrl: null }
|
|
}
|
|
|
|
/** Merge settings of a repository that allows squash and merge commits and whose viewer may merge, usually with a merge commit. */
|
|
export function repositorySettings(overrides: Record<string, unknown> = {}): Record<string, unknown> {
|
|
return {
|
|
squashMergeAllowed: true,
|
|
mergeCommitAllowed: true,
|
|
rebaseMergeAllowed: false,
|
|
viewerPermission: 'WRITE',
|
|
viewerDefaultMergeMethod: 'MERGE',
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
/** A pull request node with the fields the snapshot query selects. */
|
|
export function pullRequestNode(number: number, overrides: Record<string, unknown> = {}, contexts: unknown[] = [], rollupState: string | null = 'SUCCESS'): Record<string, unknown> {
|
|
return {
|
|
number,
|
|
url: `https://github.com/octo/demo/pull/${number}`,
|
|
title: `Change ${number}`,
|
|
state: 'OPEN',
|
|
isDraft: false,
|
|
updatedAt: '2026-10-09T01:02:03Z',
|
|
closedAt: null,
|
|
author: { login: 'octo' },
|
|
headRefName: `topic-${number}`,
|
|
headRefOid: 'f'.repeat(40),
|
|
baseRefName: 'master',
|
|
additions: 128,
|
|
deletions: 14,
|
|
mergeable: 'MERGEABLE',
|
|
mergeStateStatus: 'CLEAN',
|
|
reviewDecision: null,
|
|
reviewThreads: { nodes: [{ isResolved: true }, { isResolved: false }, { isResolved: false }] },
|
|
commits: {
|
|
nodes: [{
|
|
commit: {
|
|
statusCheckRollup: rollupState === null ? null : {
|
|
state: rollupState,
|
|
contexts: { pageInfo: { hasNextPage: false }, nodes: contexts },
|
|
},
|
|
},
|
|
}],
|
|
},
|
|
...overrides,
|
|
}
|
|
}
|