diff --git a/lib/platform/gitea/__snapshots__/gitea-helper.spec.ts.snap b/lib/platform/gitea/__snapshots__/gitea-helper.spec.ts.snap index 9d40fd5b7d4d7d..500591aef74753 100644 --- a/lib/platform/gitea/__snapshots__/gitea-helper.spec.ts.snap +++ b/lib/platform/gitea/__snapshots__/gitea-helper.spec.ts.snap @@ -456,6 +456,21 @@ Array [ ] `; +exports[`platform/gitea/gitea-helper getIssue should call /api/v1/repos/[repo]/issues/[issue] endpoint 1`] = ` +Array [ + Object { + "headers": Object { + "accept": "application/json", + "accept-encoding": "gzip, deflate, br", + "host": "gitea.renovatebot.com", + "user-agent": "https://github.com/renovatebot/renovate", + }, + "method": "GET", + "url": "https://gitea.renovatebot.com/api/v1/repos/some/repo/issues/7", + }, +] +`; + exports[`platform/gitea/gitea-helper getOrgLabels should call /api/v1/orgs/[org]/labels endpoint 1`] = ` Array [ Object { diff --git a/lib/platform/gitea/gitea-helper.spec.ts b/lib/platform/gitea/gitea-helper.spec.ts index 225dcc3e5518ab..4095b539dc8004 100644 --- a/lib/platform/gitea/gitea-helper.spec.ts +++ b/lib/platform/gitea/gitea-helper.spec.ts @@ -508,6 +508,19 @@ describe(getName(), () => { }); }); + describe('getIssue', () => { + it('should call /api/v1/repos/[repo]/issues/[issue] endpoint', async () => { + httpMock + .scope(baseUrl) + .get(`/repos/${mockRepo.full_name}/issues/${mockIssue.number}`) + .reply(200, mockIssue); + + const res = await ght.getIssue(mockRepo.full_name, mockIssue.number); + expect(res).toEqual(mockIssue); + expect(httpMock.getTrace()).toMatchSnapshot(); + }); + }); + describe('getRepoLabels', () => { it('should call /api/v1/repos/[repo]/labels endpoint', async () => { httpMock diff --git a/lib/platform/gitea/gitea-helper.ts b/lib/platform/gitea/gitea-helper.ts index f0c9a0b36c1283..88e2bec4065463 100644 --- a/lib/platform/gitea/gitea-helper.ts +++ b/lib/platform/gitea/gitea-helper.ts @@ -400,6 +400,16 @@ export async function searchIssues( return res.body; } +export async function getIssue( + repoPath: string, + idx: number, + options?: GiteaHttpOptions +): Promise { + const url = `repos/${repoPath}/issues/${idx}`; + const res = await giteaHttp.getJson(url, options); + return res.body; +} + export async function getRepoLabels( repoPath: string, options?: GiteaHttpOptions diff --git a/lib/platform/gitea/index.spec.ts b/lib/platform/gitea/index.spec.ts index 8d42f712ec1ba8..d5ab8c01d8dcd1 100644 --- a/lib/platform/gitea/index.spec.ts +++ b/lib/platform/gitea/index.spec.ts @@ -905,10 +905,24 @@ describe(getName(), () => { }); }); + describe('getIssue', () => { + it('should return the issue', async () => { + const mockIssue = mockIssues.find((i) => i.number === 1); + helper.getIssue.mockResolvedValueOnce(mockIssue); + await initFakeRepo(); + + expect(await gitea.getIssue(mockIssue.number)).toHaveProperty( + 'number', + mockIssue.number + ); + }); + }); + describe('findIssue', () => { it('should return existing open issue', async () => { const mockIssue = mockIssues.find((i) => i.title === 'open-issue'); helper.searchIssues.mockResolvedValueOnce(mockIssues); + helper.getIssue.mockResolvedValueOnce(mockIssue); await initFakeRepo(); expect(await gitea.findIssue(mockIssue.title)).toHaveProperty( diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index a09a65b261d490..0458ff5758f7fe 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -587,16 +587,34 @@ const platform: Platform = { return config.issueList; }, + async getIssue(number: number, useCache = true): Promise { + try { + const body = ( + await helper.getIssue(config.repository, number, { + useCache, + }) + ).body; + return { + number, + body, + }; + } catch (err) /* istanbul ignore next */ { + logger.debug({ err, number }, 'Error getting issue'); + return null; + } + }, + async findIssue(title: string): Promise { const issueList = await platform.getIssueList(); const issue = issueList.find( (i) => i.state === 'open' && i.title === title ); - if (issue) { - logger.debug(`Found Issue #${issue.number}`); + if (!issue) { + return null; } - return issue ?? null; + logger.debug(`Found Issue #${issue.number}`); + return platform.getIssue(issue.number); }, async ensureIssue({ @@ -836,6 +854,7 @@ export const { getBranchPr, getBranchStatus, getBranchStatusCheck, + getIssue, getRawFile, getJsonFile, getIssueList, diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index ec07b151259977..0363732eee9cc6 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -1105,6 +1105,27 @@ export async function getIssueList(): Promise { return config.issueList; } +export async function getIssue( + number: number, + useCache = true +): Promise { + try { + const issueBody = ( + await githubApi.getJson<{ body: string }>( + `repos/${config.parentRepo || config.repository}/issues/${number}`, + { useCache } + ) + ).body.body; + return { + number, + body: issueBody, + }; + } catch (err) /* istanbul ignore next */ { + logger.debug({ err, number }, 'Error getting issue'); + return null; + } +} + export async function findIssue(title: string): Promise { logger.debug(`findIssue(${title})`); const [issue] = (await getIssueList()).filter( @@ -1114,15 +1135,7 @@ export async function findIssue(title: string): Promise { return null; } logger.debug(`Found issue ${issue.number}`); - const issueBody = ( - await githubApi.getJson<{ body: string }>( - `repos/${config.parentRepo || config.repository}/issues/${issue.number}` - ) - ).body.body; - return { - number: issue.number, - body: issueBody, - }; + return getIssue(issue.number); } async function closeIssue(issueNumber: number): Promise { diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 748b072c16b870..da190b10893409 100755 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -753,23 +753,36 @@ export async function getIssueList(): Promise { return config.issueList; } -export async function findIssue(title: string): Promise { - logger.debug(`findIssue(${title})`); +export async function getIssue( + number: number, + useCache = true +): Promise { try { - const issueList = await getIssueList(); - const issue = issueList.find((i) => i.title === title); - if (!issue) { - return null; - } const issueBody = ( await gitlabApi.getJson<{ description: string }>( - `projects/${config.repository}/issues/${issue.iid}` + `projects/${config.repository}/issues/${number}`, + { useCache } ) ).body.description; return { - number: issue.iid, + number, body: issueBody, }; + } catch (err) /* istanbul ignore next */ { + logger.debug({ err, number }, 'Error getting issue'); + return null; + } +} + +export async function findIssue(title: string): Promise { + logger.debug(`findIssue(${title})`); + try { + const issueList = await getIssueList(); + const issue = issueList.find((i) => i.title === title); + if (!issue) { + return null; + } + return getIssue(issue.iid); } catch (err) /* istanbul ignore next */ { logger.warn('Error finding issue'); return null; diff --git a/lib/platform/types.ts b/lib/platform/types.ts index 240425ace74b9f..dc73dda2298009 100644 --- a/lib/platform/types.ts +++ b/lib/platform/types.ts @@ -139,6 +139,7 @@ export type EnsureIssueResult = 'updated' | 'created'; export interface Platform { findIssue(title: string): Promise; getIssueList(): Promise; + getIssue?(number: number, useCache?: boolean): Promise; getVulnerabilityAlerts(): Promise; getRawFile(fileName: string, repo?: string): Promise; getJsonFile(fileName: string, repo?: string): Promise;