diff --git a/.changeset/neat-hats-breathe.md b/.changeset/neat-hats-breathe.md new file mode 100644 index 00000000..96eb23b2 --- /dev/null +++ b/.changeset/neat-hats-breathe.md @@ -0,0 +1,5 @@ +--- +"changesets-gitlab": minor +--- + +feat: try `allDiffs` api first and fallback to `showChanges` when unavailable diff --git a/src/comment.ts b/src/comment.ts index 2be8fb49..06ebce40 100644 --- a/src/comment.ts +++ b/src/comment.ts @@ -4,13 +4,14 @@ import type { ReleasePlan, VersionType, } from '@changesets/types' -import type { Gitlab } from '@gitbeaker/core' -import type { - DiscussionNoteSchema, - DiscussionSchema, - MergeRequestChangesSchema, - MergeRequestNoteSchema, - NoteSchema, +import type { CommitDiffSchema, Gitlab } from '@gitbeaker/core' +import { + GitbeakerRequestError, + type DiscussionNoteSchema, + type DiscussionSchema, + type MergeRequestDiffSchema, + type MergeRequestNoteSchema, + type NoteSchema, } from '@gitbeaker/rest' import { humanId } from 'human-id' import { markdownTable } from 'markdown-table' @@ -20,7 +21,7 @@ import * as context from './context.js' import { env } from './env.js' import { getChangedPackages } from './get-changed-packages.js' import type { LooseString } from './types.js' -import { getUsername, TRUTHY_VALUES } from './utils.js' +import { getUsername, HTTP_STATUS_NOT_FOUND, TRUTHY_VALUES } from './utils.js' const generatedByBotNote = 'Generated By Changesets GitLab Bot' @@ -207,10 +208,10 @@ async function getNoteInfo( } const hasChangesetBeenAdded = async ( - changedFilesPromise: Promise, + changedFilesPromise: Promise, ) => { const changedFiles = await changedFilesPromise - return changedFiles.changes.some(file => { + return changedFiles.some(file => { return ( file.new_file && /^\.changeset\/.+\.md$/.test(file.new_path) && @@ -219,35 +220,6 @@ const hasChangesetBeenAdded = async ( }) } -/** - * @see https://github.com/jdalrymple/gitbeaker/blob/52ef0e622de304d98afb811f4937560edefd8889/packages/rest/src/Requester.ts#L79-L86 - */ -export interface GitLabAPIError extends Error { - cause: { - description: string - request: Request - response: Response - } -} - -const GITLAB_API_ERROR_CAUSE_KEYS = new Set([ - 'description', - 'request', - 'response', -]) - -// type-coverage:ignore-next-line -- https://github.com/plantain-00/type-coverage/issues/133 -const { toString } = Object.prototype // eslint-disable-line @typescript-eslint/unbound-method - -const isError = (value: unknown): value is Error => - toString.call(value) === '[object Error]' - -const isGitLabAPIError = (error: unknown): error is GitLabAPIError => - isError(error) && - !!error.cause && - typeof error.cause === 'object' && - Object.keys(error.cause).every(key => GITLAB_API_ERROR_CAUSE_KEYS.has(key)) - // eslint-disable-next-line sonarjs/cognitive-complexity export const comment = async () => { const mrBranch = env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME @@ -271,18 +243,32 @@ export const comment = async () => { let errFromFetchingChangedFiles = '' try { const latestCommitSha = env.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA - const changedFilesPromise = api.MergeRequests.showChanges( + + const changedFilesPromise = api.MergeRequests.allDiffs( context.projectId, mrIid, - ) + ).catch(async (err: unknown) => { + if ( + !(err instanceof GitbeakerRequestError) || + err.cause?.response.status !== HTTP_STATUS_NOT_FOUND + ) { + throw err + } + + const { changes } = await api.MergeRequests.showChanges( + context.projectId, + mrIid, + ) + return changes + }) const [noteInfo, hasChangeset, { changedPackages, releasePlan }] = await Promise.all([ getNoteInfo(api, mrIid, commentType), hasChangesetBeenAdded(changedFilesPromise), getChangedPackages({ - changedFiles: changedFilesPromise.then(x => - x.changes.map(x => x.new_path), + changedFiles: changedFilesPromise.then(changedFiles => + changedFiles.map(({ new_path }) => new_path), ), api, }).catch((err: unknown) => { @@ -368,11 +354,9 @@ export const comment = async () => { ) } } - } catch (err: unknown) { - if (isGitLabAPIError(err)) { - const { - cause: { description, request, response }, - } = err + } catch (err) { + if (err instanceof GitbeakerRequestError && err.cause) { + const { description, request, response } = err.cause console.error(description) try { console.error('request:', await request.text()) diff --git a/src/utils.ts b/src/utils.ts index 083930dc..cabea43b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -177,3 +177,5 @@ export const FALSY_VALUES = new Set(['false', '0']) export const TRUTHY_VALUES = new Set(['true', '1']) export const GITLAB_MAX_TAGS = 4 + +export const HTTP_STATUS_NOT_FOUND = 404