feat(vscode): webhook 副作用按 assignee 门禁,适配多人协作

This commit is contained in:
2026-08-18 23:57:21 +08:00
parent c20bd86370
commit c370214d12
11 changed files with 450 additions and 22 deletions
+33 -8
View File
@@ -16,6 +16,7 @@ const PAGE_SIZE = 50
export interface GiteaUser {
login: string
id: number
email?: string
}
export interface GiteaIssue {
@@ -57,8 +58,8 @@ function baseUrl(host: string): string {
function authHeaders(token: string): Record<string, string> {
return {
'Authorization': `token ${token}`,
'Accept': 'application/json',
Authorization: `token ${token}`,
Accept: 'application/json',
}
}
@@ -92,7 +93,7 @@ export async function listIssuesByFilter(opts: {
const out: GiteaIssue[] = []
let page = 1
// Gitea returns a JSON array of issues; we accumulate until we see a short page.
// eslint-disable-next-line no-constant-condition
while (true) {
const url = new URL(`${baseUrl(opts.host)}/repos/${opts.owner}/${opts.repo}/issues`)
url.searchParams.set('type', 'issues')
@@ -127,7 +128,7 @@ export async function listAllRepoComments(opts: {
}): Promise<GiteaComment[]> {
const out: GiteaComment[] = []
let page = 1
// eslint-disable-next-line no-constant-condition
while (true) {
const url = new URL(`${baseUrl(opts.host)}/repos/${opts.owner}/${opts.repo}/issues/comments`)
url.searchParams.set('limit', String(PAGE_SIZE))
@@ -161,7 +162,7 @@ export async function listIssueComments(opts: {
}): Promise<GiteaComment[]> {
const out: GiteaComment[] = []
let page = 1
// eslint-disable-next-line no-constant-condition
while (true) {
const url = new URL(
`${baseUrl(opts.host)}/repos/${opts.owner}/${opts.repo}/issues/${opts.index}/comments`,
@@ -204,7 +205,6 @@ export async function postIssueComment(opts: {
await ensureOk(res)
}
export interface GiteaPullRequest {
number: number
merged: boolean
@@ -285,6 +285,32 @@ export async function getIssue(opts: {
return await res.json() as GiteaIssue
}
/**
* 覆盖式设置工单 assignee(实施即认领的多人协作语义:单一责任人,
* 重新实施会把责任转移给新实施者)。
*/
export async function updateIssueAssignees(opts: {
host: string
token: string
owner: string
repo: string
index: number
assignees: string[]
}): Promise<void> {
const res = await fetch(
`${baseUrl(opts.host)}/repos/${opts.owner}/${opts.repo}/issues/${opts.index}`,
{
method: 'PATCH',
headers: {
...authHeaders(opts.token),
'Content-Type': 'application/json',
},
body: JSON.stringify({ assignees: opts.assignees }),
},
)
await ensureOk(res)
}
export async function getDependencies(opts: {
host: string
token: string
@@ -430,7 +456,6 @@ export async function removeDependency(opts: {
await ensureOk(res)
}
// no longer auto-invoked by the implement flow; kept for future manual ops
export async function createWebhook(opts: {
host: string
@@ -550,7 +575,7 @@ export async function listPullRequestFiles(opts: {
}): Promise<PrFileDto[]> {
const out: PrFileDto[] = []
let page = 1
// eslint-disable-next-line no-constant-condition
while (true) {
const url = new URL(
`${baseUrl(opts.host)}/repos/${opts.owner}/${opts.repo}/pulls/${opts.index}/files`,