pass user provided token through to gitlab url resolvers

Signed-off-by: Cptn Fizzbin <code@cptnfizzbin.ca>
This commit is contained in:
Cptn Fizzbin
2025-04-23 10:03:01 -04:00
parent 424f3bc20b
commit 36f77e935c
4 changed files with 30 additions and 12 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': patch
---
Bugfix: Pass user provided token through to gitlab url resolvers
@@ -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<UrlReaderServiceReadUrlResponse> {
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<string> {
private async getGitlabFetchUrl(
target: string,
token?: string,
): Promise<string> {
// 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/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_file>?job=<job_name>
// to urls of the form:
// https://example.com/api/v4/projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=<job_name>
private async getGitlabArtifactFetchUrl(target: URL): Promise<URL> {
private async getGitlabArtifactFetchUrl(
target: URL,
token?: string,
): Promise<URL> {
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<number> {
private async resolveProjectToId(
pathToProject: URL,
token?: string,
): Promise<number> {
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) {
@@ -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.
*/
+1
View File
@@ -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(