diff --git a/.changeset/twenty-kiwis-punch.md b/.changeset/twenty-kiwis-punch.md new file mode 100644 index 0000000000..51cc5d46c0 --- /dev/null +++ b/.changeset/twenty-kiwis-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Bugfix: Pass user provided token through to gitlab url resolvers diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts index 4be6e65b96..3e5497a307 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts @@ -32,18 +32,18 @@ import { NotModifiedError, } from '@backstage/errors'; import { - GitLabIntegration, - ScmIntegrations, getGitLabFileFetchUrl, getGitLabIntegrationRelativePath, getGitLabRequestOptions, + GitLabIntegration, + ScmIntegrations, } from '@backstage/integration'; import parseGitUrl from 'git-url-parse'; import { trimEnd, trimStart } from 'lodash'; import { Minimatch } from 'minimatch'; import { Readable } from 'stream'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; -import { ReadTreeResponseFactory, ReaderFactory } from './types'; +import { ReaderFactory, ReadTreeResponseFactory } from './types'; import { parseLastModified } from './util'; /** @@ -79,7 +79,7 @@ export class GitlabUrlReader implements UrlReaderService { ): Promise { const { etag, lastModifiedAfter, signal, token } = options ?? {}; const isArtifact = url.includes('/-/jobs/artifacts/'); - const builtUrl = await this.getGitlabFetchUrl(url); + const builtUrl = await this.getGitlabFetchUrl(url, token); let response: Response; try { @@ -328,23 +328,32 @@ export class GitlabUrlReader implements UrlReaderService { return `gitlab{host=${host},authed=${Boolean(token)}}`; } - private async getGitlabFetchUrl(target: string): Promise { + private async getGitlabFetchUrl( + target: string, + token?: string, + ): Promise { // If the target is for a job artifact then go down that path const targetUrl = new URL(target); if (targetUrl.pathname.includes('/-/jobs/artifacts/')) { - return this.getGitlabArtifactFetchUrl(targetUrl).then(value => + return this.getGitlabArtifactFetchUrl(targetUrl, token).then(value => value.toString(), ); } // Default to the old behavior of assuming the url is for a file - return getGitLabFileFetchUrl(target, this.integration.config); + return getGitLabFileFetchUrl(target, { + ...this.integration.config, + ...(token && { token }), + }); } // convert urls of the form: // https://example.com///-/jobs/artifacts//raw/?job= // to urls of the form: // https://example.com/api/v4/projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job= - private async getGitlabArtifactFetchUrl(target: URL): Promise { + private async getGitlabArtifactFetchUrl( + target: URL, + token?: string, + ): Promise { if (!target.pathname.includes('/-/jobs/artifacts/')) { throw new Error('Unable to process url as an GitLab artifact'); } @@ -353,7 +362,7 @@ export class GitlabUrlReader implements UrlReaderService { target.pathname.split('/-/jobs/artifacts/'); const projectPath = new URL(target); projectPath.pathname = namespaceAndProject; - const projectId = await this.resolveProjectToId(projectPath); + const projectId = await this.resolveProjectToId(projectPath, token); const relativePath = getGitLabIntegrationRelativePath( this.integration.config, ); @@ -367,7 +376,10 @@ export class GitlabUrlReader implements UrlReaderService { } } - private async resolveProjectToId(pathToProject: URL): Promise { + private async resolveProjectToId( + pathToProject: URL, + token?: string, + ): Promise { let project = pathToProject.pathname; // Check relative path exist and remove it if so const relativePath = getGitLabIntegrationRelativePath( @@ -382,7 +394,7 @@ export class GitlabUrlReader implements UrlReaderService { `${ pathToProject.origin }${relativePath}/api/v4/projects/${encodeURIComponent(project)}`, - getGitLabRequestOptions(this.integration.config), + getGitLabRequestOptions(this.integration.config, token), ); const data = await result.json(); if (!result.ok) { diff --git a/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts b/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts index 9b327cfbf0..f6e861e6ff 100644 --- a/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts +++ b/packages/backend-plugin-api/src/services/definitions/UrlReaderService.ts @@ -209,7 +209,7 @@ export type UrlReaderServiceReadTreeOptions = { * @remarks * * By default all URL Readers will use the integrations config which is supplied - * when creating the Readers. Sometimes it might be desireable to use the already + * when creating the Readers. Sometimes it might be desirable to use the already * created URLReaders but with a different token, maybe that's supplied by the user * at runtime. */ diff --git a/packages/integration/src/gitlab/core.ts b/packages/integration/src/gitlab/core.ts index c7f8dd036f..4a17b2a15e 100644 --- a/packages/integration/src/gitlab/core.ts +++ b/packages/integration/src/gitlab/core.ts @@ -49,6 +49,7 @@ export async function getGitLabFileFetchUrl( * Gets the request options necessary to make requests to a given provider. * * @param config - The relevant provider config + * @param token - An optional auth token to use for communicating with GitLab. By default uses the integration token * @public */ export function getGitLabRequestOptions(