feat: 展示 Gitea webhook relay 诊断

- types/api: 接入后端 webhook 诊断响应并安全降级
- store: 将 webhook 状态并入项目 Gitea 集成状态
- ProjectsView: 展示 relay 目标、hook 数量和匹配明细
This commit is contained in:
湛兮
2026-06-12 04:57:15 +08:00
parent cb8519d3f9
commit 0302660351
4 changed files with 191 additions and 1 deletions
+51
View File
@@ -50,6 +50,9 @@ type BackendRunStatus = 'pending' | 'queued' | 'running' | 'success' | 'failed'
type DashboardOptions = {
includeAdminConfig?: boolean
}
type ProjectGiteaWebhookStatus = NonNullable<
ProjectGiteaRepositoryDiagnostic['webhook']
>['status']
type BackendVariableHelpValue =
| string
| {
@@ -798,6 +801,9 @@ function toProjectConfigs(backendProjects: BackendProject[]): ProjectConfig[] {
tagPolicy: tagPolicyLabel(project.environments),
giteaStatus: 'warning',
giteaMessage: '尚未执行 Gitea 诊断',
giteaWebhookStatus: 'warning',
giteaWebhookMessage: '尚未执行 Webhook 诊断',
giteaWebhookHooks: [],
environments: project.environments.map((environment) => {
return {
name: environment.name,
@@ -861,10 +867,55 @@ function sanitizeProjectGiteaRepositoryDiagnostic(
authoredAt: optionalSafeText(value.latestCommit.authoredAt),
}
: undefined,
webhook: value.webhook
? {
status: toProjectGiteaWebhookDiagnosticStatus(value.webhook.status),
message: optionalSafeText(value.webhook.message),
hookCount: Number.isFinite(value.webhook.hookCount) ? value.webhook.hookCount : 0,
activePushHookCount: Number.isFinite(value.webhook.activePushHookCount)
? value.webhook.activePushHookCount
: 0,
expectedRelayConfigured: value.webhook.expectedRelayConfigured === true,
expectedRelayTarget: optionalSafeText(value.webhook.expectedRelayTarget),
matchedHookId: Number.isFinite(value.webhook.matchedHookId)
? value.webhook.matchedHookId
: undefined,
hooks: Array.isArray(value.webhook.hooks)
? value.webhook.hooks.map((hook) => ({
id: Number.isFinite(hook.id) ? hook.id : 0,
type: safeText(hook.type, 'unknown'),
active: hook.active === true,
events: Array.isArray(hook.events)
? hook.events.filter((event): event is string => typeof event === 'string')
: [],
branchFilter: optionalSafeText(hook.branchFilter),
target: optionalSafeText(hook.target),
matchesExpectedRelay: hook.matchesExpectedRelay === true,
createdAt: optionalSafeText(hook.createdAt),
updatedAt: optionalSafeText(hook.updatedAt),
}))
: [],
}
: undefined,
updatedAt: optionalSafeText(value.updatedAt),
}
}
function toProjectGiteaWebhookDiagnosticStatus(
value: ProjectGiteaWebhookStatus,
): ProjectGiteaWebhookStatus {
if (
value === 'ok' ||
value === 'missing' ||
value === 'not_configured' ||
value === 'unavailable'
) {
return value
}
return 'unavailable'
}
function toProjectGiteaDiagnosticStatus(
value: ProjectGiteaRepositoryDiagnostic['status'],
): ProjectGiteaRepositoryDiagnostic['status'] {