diff --git a/.changeset/weak-drinks-report.md b/.changeset/weak-drinks-report.md new file mode 100644 index 0000000000..1f8ee512ba --- /dev/null +++ b/.changeset/weak-drinks-report.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-climate': patch +--- + +Send Authorization headers in fetch requests using FetchApi in Code Climate plugin to fix unauthorized requests to Backstage backends with authentication enabled. diff --git a/plugins/code-climate/api-report.md b/plugins/code-climate/api-report.md index b0cc3e1450..5ef53cf543 100644 --- a/plugins/code-climate/api-report.md +++ b/plugins/code-climate/api-report.md @@ -8,6 +8,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { FetchApi } from '@backstage/core-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; // Warning: (ae-missing-release-tag) "CodeClimateApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -74,7 +75,8 @@ export const mockData: CodeClimateData; // // @public (undocumented) export class ProductionCodeClimateApi implements CodeClimateApi { - constructor(discoveryApi: DiscoveryApi); + // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts + constructor(options: Options); // (undocumented) fetchAllData(options: { apiUrl: string; diff --git a/plugins/code-climate/src/api/production-api.ts b/plugins/code-climate/src/api/production-api.ts index 665d7e9f63..81ba6b9ad6 100644 --- a/plugins/code-climate/src/api/production-api.ts +++ b/plugins/code-climate/src/api/production-api.ts @@ -22,7 +22,7 @@ import { CodeClimateIssuesData, } from './code-climate-data'; import { CodeClimateApi } from './code-climate-api'; -import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; import { Duration } from 'luxon'; import humanizeDuration from 'humanize-duration'; @@ -34,8 +34,19 @@ const codeSmellsQuery = `${basicIssuesOptions}&${categoriesFilter}=Complexity`; const duplicationQuery = `${basicIssuesOptions}&${categoriesFilter}=Duplication`; const otherIssuesQuery = `${basicIssuesOptions}&${categoriesFilter}=Bug%20Risk`; +type Options = { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; +}; + export class ProductionCodeClimateApi implements CodeClimateApi { - constructor(private readonly discoveryApi: DiscoveryApi) {} + private readonly discoveryApi: DiscoveryApi; + private readonly fetchApi: FetchApi; + + constructor(options: Options) { + this.discoveryApi = options.discoveryApi; + this.fetchApi = options.fetchApi; + } async fetchAllData(options: { apiUrl: string; @@ -44,7 +55,6 @@ export class ProductionCodeClimateApi implements CodeClimateApi { testReportID: string; }): Promise { const { apiUrl, repoID, snapshotID, testReportID } = options; - const [ maintainabilityResponse, testCoverageResponse, @@ -52,15 +62,19 @@ export class ProductionCodeClimateApi implements CodeClimateApi { duplicationResponse, otherIssuesResponse, ] = await Promise.all([ - await fetch(`${apiUrl}/repos/${repoID}/snapshots/${snapshotID}`), - await fetch(`${apiUrl}/repos/${repoID}/test_reports/${testReportID}`), - await fetch( + await this.fetchApi.fetch( + `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}`, + ), + await this.fetchApi.fetch( + `${apiUrl}/repos/${repoID}/test_reports/${testReportID}`, + ), + await this.fetchApi.fetch( `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${codeSmellsQuery}`, ), - await fetch( + await this.fetchApi.fetch( `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${duplicationQuery}`, ), - await fetch( + await this.fetchApi.fetch( `${apiUrl}/repos/${repoID}/snapshots/${snapshotID}/issues?${otherIssuesQuery}`, ), ]); @@ -109,7 +123,7 @@ export class ProductionCodeClimateApi implements CodeClimateApi { 'proxy', )}/codeclimate/api`; - const repoResponse = await fetch(`${apiUrl}/repos/${repoID}`); + const repoResponse = await this.fetchApi.fetch(`${apiUrl}/repos/${repoID}`); if (!repoResponse.ok) { throw new Error('Failed fetching Code Climate info'); diff --git a/plugins/code-climate/src/plugin.ts b/plugins/code-climate/src/plugin.ts index dcf86f1e19..54502b6355 100644 --- a/plugins/code-climate/src/plugin.ts +++ b/plugins/code-climate/src/plugin.ts @@ -20,7 +20,7 @@ import { createPlugin, createRouteRef, discoveryApiRef, - identityApiRef, + fetchApiRef, createComponentExtension, } from '@backstage/core-plugin-api'; @@ -37,9 +37,10 @@ export const codeClimatePlugin = createPlugin({ api: codeClimateApiRef, deps: { discoveryApi: discoveryApiRef, - identityApi: identityApiRef, + fetchApi: fetchApiRef, }, - factory: ({ discoveryApi }) => new ProductionCodeClimateApi(discoveryApi), + factory: ({ discoveryApi, fetchApi }) => + new ProductionCodeClimateApi({ discoveryApi, fetchApi }), }), ], routes: {