Files
orca/src/shared/code-host-failure-copy.ts
T
OrcaWinandOrcaWin 3b9c1d356d fix(i18n): code GitHub/GitLab operation failures for the renderer (#35689)
* fix(i18n): code GitHub/GitLab operation failures for the renderer

* fix(i18n): show coded failures in comment composers; exhaustive classification switches

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 22:18:41 -07:00

107 lines
5.1 KiB
TypeScript

import type { ClassifiedError } from './classified-error'
// One English table for GitHub/GitLab operation failures: main builds the wire `error`, the renderer translates by code.
export const CODE_HOST_FAILURE_COPY = {
titleRequired: 'Title is required',
networkError: 'Network error — check your connection.',
invalidUpdate: 'Invalid update — {{detail}}',
invalidRequest: 'Invalid request — {{detail}}',
issueNotFound: 'Issue not found — it may have been deleted.',
issueUpdateFailed: 'Failed to update issue: {{detail}}',
'github.repoUnresolved': 'Could not resolve GitHub owner/repo for this repository',
'github.unexpectedResponse': 'Unexpected response from GitHub',
'github.pullRequestIdUnresolved': 'Could not resolve GitHub pull request ID',
'github.reviewerRequired': 'Enter at least one reviewer',
'github.stackAutoMergeUnsupported':
'GitHub does not support auto-merge for stacked pull requests.',
'github.autoMergeAlreadyMergeable':
'This pull request can already be merged. Use Merge instead of auto-merge.',
'github.noFailedChecks': 'No failed GitHub Actions checks to rerun.',
'github.noRerunnableChecks': 'No rerunnable checks found.',
'github.stackMergeInvalidResponse': 'GitHub returned an invalid stack merge response.',
'github.stackMergePending': 'GitHub is still merging this stack. Refresh to check its status.',
'github.rateLimited': 'GitHub rate limit hit. Try again in a few minutes.',
'github.issuePermissionDenied':
"You don't have permission to edit this issue. Check your GitHub token scopes.",
'github.issuesDisabled': 'Issues are disabled on this repository.',
'github.pullRequestPermissionDenied':
"You don't have permission to edit this pull request. Check your GitHub token scopes.",
'github.pullRequestNotFound': 'Pull request not found — it may have been deleted.',
'github.pullRequestUpdateFailed': 'Failed to update pull request: {{detail}}',
'github.autoMergeEnableFailed': 'Failed to enable auto-merge for pull request: {{detail}}',
'github.autoMergeDisableFailed': 'Failed to disable auto-merge for pull request: {{detail}}',
'github.mergeQueueAddFailed': 'Failed to add pull request to the merge queue: {{detail}}',
'github.rerunPermissionDenied':
"You don't have permission to rerun checks on this repository. Check your GitHub token scopes.",
'github.rerunTargetNotFound':
'GitHub resource to rerun was not found — it may have expired or been deleted.',
'github.rerunRejected': 'Could not rerun checks — {{detail}}',
'github.rerunFailed': 'Failed to rerun checks: {{detail}}',
'gitlab.projectUnresolved': 'Could not resolve GitLab project for this repository',
'gitlab.unexpectedResponse': 'Unexpected response from GitLab',
'gitlab.commentBodyRequired': 'Comment body is required',
'gitlab.discussionIdRequired': 'Discussion id is required',
'gitlab.readyTitleConflict': 'Cannot update the title while marking a merge request ready',
'gitlab.mergeRequestTitleUnreadable': 'Could not read the current merge request title',
'gitlab.rateLimited': 'GitLab rate limit hit. Try again in a few minutes.',
'gitlab.issuePermissionDenied':
"You don't have permission to edit this issue. Check your GitLab token scopes.",
'gitlab.jobLogPermissionDenied':
"You don't have permission to read this job's log. Check your GitLab token scopes.",
'gitlab.jobProjectNotFound': "Could not find this job's GitLab project.",
'gitlab.jobLogFailed': 'Failed to load the job log: {{detail}}'
} as const
export type CodeHostFailureCode = keyof typeof CODE_HOST_FAILURE_COPY
/** Wire shape: `error` stays English for older clients; `errorDetail` is verbatim gh/glab text. */
export type CodeHostFailure = {
ok: false
error: string
errorCode?: string
errorDetail?: string
}
export function codeHostFailureText(code: CodeHostFailureCode, detail?: string): string {
return CODE_HOST_FAILURE_COPY[code].replace('{{detail}}', () => detail ?? '')
}
export function codeHostFailure(code: CodeHostFailureCode, detail?: string): CodeHostFailure {
return {
ok: false,
error: codeHostFailureText(code, detail),
errorCode: code,
...(detail !== undefined ? { errorDetail: detail } : {})
}
}
export function classifiedCodeHostError(
type: ClassifiedError['type'],
code: CodeHostFailureCode,
detail?: string
): ClassifiedError {
return {
type,
message: codeHostFailureText(code, detail),
code,
...(detail !== undefined ? { detail } : {})
}
}
/** Carries a classified gh/glab failure onto an `{ ok: false }` result. */
export function classifiedFailure(classified: ClassifiedError): CodeHostFailure {
return {
ok: false,
error: classified.message,
...(classified.code !== undefined ? { errorCode: classified.code } : {}),
...(classified.detail !== undefined ? { errorDetail: classified.detail } : {})
}
}
/** A single failure keeps its code; several are joined in English only. */
export function combinedClassifiedFailure(errors: readonly ClassifiedError[]): CodeHostFailure {
return errors.length === 1
? classifiedFailure(errors[0])
: { ok: false, error: errors.map((e) => e.message).join('; ') }
}