Look up project IDs for unscoped routes

Signed-off-by: Jamie Klassen <jklassen@vmware.com>
This commit is contained in:
Jamie Klassen
2022-07-21 11:55:27 -04:00
parent 3a2254185e
commit 1e1e436e86
3 changed files with 16 additions and 71 deletions
@@ -106,7 +106,7 @@ describe('GitlabUrlReader', () => {
);
it.each([
// Project URLs
// Scoped routes
{
url: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
config: createConfig(),
@@ -135,12 +135,12 @@ describe('GitlabUrlReader', () => {
}),
},
// Raw URLs
// Unscoped route
{
url: 'https://gitlab.example.com/a/b/blob/master/c.yaml',
config: createConfig(),
response: expect.objectContaining({
url: 'https://gitlab.example.com/a/b/raw/master/c.yaml',
url: 'https://gitlab.example.com/api/v4/projects/12345/repository/files/c.yaml/raw?ref=master',
}),
},
])('should handle happy path %#', async ({ url, config, response }) => {
+4 -22
View File
@@ -155,11 +155,11 @@ describe('gitlab core', () => {
});
describe('when target has an unscoped route', () => {
it('returns a raw URL', async () => {
it('returns projects API URL', async () => {
const target =
'https://gitlab.com/group/project/blob/branch/folder/file.yaml';
const fetchUrl =
'https://gitlab.com/group/project/raw/branch/folder/file.yaml';
'https://gitlab.com/api/v4/projects/12345/repository/files/folder%2Ffile.yaml/raw?ref=branch';
await expect(
getGitLabFileFetchUrl(target, configWithNoToken),
).resolves.toBe(fetchUrl);
@@ -169,17 +169,7 @@ describe('gitlab core', () => {
const target =
'https://gitlab.com/group/subgroup/project/blob/branch/folder/file.yaml';
const fetchUrl =
'https://gitlab.com/group/subgroup/project/raw/branch/folder/file.yaml';
await expect(
getGitLabFileFetchUrl(target, configWithNoToken),
).resolves.toBe(fetchUrl);
});
it('supports project named "blob"', async () => {
const target =
'https://gitlab.com/group/blob/blob/branch/folder/file.yaml';
const fetchUrl =
'https://gitlab.com/group/blob/raw/branch/folder/file.yaml';
'https://gitlab.com/api/v4/projects/12345/repository/files/folder%2Ffile.yaml/raw?ref=branch';
await expect(
getGitLabFileFetchUrl(target, configWithNoToken),
).resolves.toBe(fetchUrl);
@@ -189,15 +179,7 @@ describe('gitlab core', () => {
const target =
'https://gitlab.com/group/project/blob/blob/folder/file.yaml';
const fetchUrl =
'https://gitlab.com/group/project/raw/blob/folder/file.yaml';
await expect(
getGitLabFileFetchUrl(target, configWithNoToken),
).resolves.toBe(fetchUrl);
});
it('removes empty path segment', async () => {
const target = 'https://gitlab.example.com/group//blob/blob/file.yaml';
const fetchUrl = 'https://gitlab.example.com/group/blob/raw/file.yaml';
'https://gitlab.com/api/v4/projects/12345/repository/files/folder%2Ffile.yaml/raw?ref=blob';
await expect(
getGitLabFileFetchUrl(target, configWithNoToken),
).resolves.toBe(fetchUrl);
+9 -46
View File
@@ -19,7 +19,6 @@ import {
GitLabIntegrationConfig,
} from './config';
import fetch from 'cross-fetch';
import { InputError } from '@backstage/errors';
/**
* Given a URL pointing to a file on a provider, returns a URL that is suitable
@@ -29,7 +28,7 @@ import { InputError } from '@backstage/errors';
*
* Converts
* from: https://gitlab.example.com/a/b/blob/master/c.yaml
* to: https://gitlab.example.com/a/b/raw/master/c.yaml
* to: https://gitlab.com/api/v4/projects/projectId/repository/c.yaml?ref=master
* -or-
* from: https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath
* to: https://gitlab.com/api/v4/projects/projectId/repository/files/filepath?ref=branch
@@ -42,15 +41,8 @@ export async function getGitLabFileFetchUrl(
url: string,
config: GitLabIntegrationConfig,
): Promise<string> {
// TODO(Rugvip): From the old GitlabReaderProcessor; used
// the existence of /-/blob/ to switch the logic. Don't know if this
// makes sense and it might require some more work.
if (url.includes('/-/blob/')) {
const projectID = await getProjectId(url, config);
return buildProjectUrl(url, projectID, config).toString();
}
return buildRawUrl(url).toString();
const projectID = await getProjectId(url, config);
return buildProjectUrl(url, projectID, config).toString();
}
/**
@@ -70,38 +62,6 @@ export function getGitLabRequestOptions(config: GitLabIntegrationConfig): {
};
}
// Converts
// from: https://gitlab.example.com/groupA/teams/repoA/blob/master/c.yaml
// to: https://gitlab.example.com/groupA/teams/repoA/raw/master/c.yaml
export function buildRawUrl(target: string): URL {
try {
const url = new URL(target);
const splitPath = url.pathname.split('/').filter(Boolean);
// Check blob existence
const blobIndex = splitPath.indexOf('blob', 2);
if (blobIndex < 2 || blobIndex === splitPath.length - 1) {
throw new InputError('Wrong GitLab URL');
}
// Take repo path
const repoPath = splitPath.slice(0, blobIndex);
const restOfPath = splitPath.slice(blobIndex + 1);
if (!restOfPath.join('/').match(/\.(yaml|yml)$/)) {
throw new InputError('Wrong GitLab URL');
}
// Replace 'blob' with 'raw'
url.pathname = [...repoPath, 'raw', ...restOfPath].join('/');
return url;
} catch (e) {
throw new InputError(`Incorrect url: ${target}, ${e}`);
}
}
// Converts
// from: https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath
// to: https://gitlab.com/api/v4/projects/projectId/repository/files/filepath?ref=branch
@@ -113,7 +73,10 @@ export function buildProjectUrl(
try {
const url = new URL(target);
const branchAndFilePath = url.pathname.split('/-/blob/')[1];
const branchAndFilePath = url.pathname
.split('/blob/')
.slice(1)
.join('/blob/');
const [branch, ...filePath] = branchAndFilePath.split('/');
const relativePath = getGitLabIntegrationRelativePath(config);
@@ -143,12 +106,12 @@ export async function getProjectId(
): Promise<number> {
const url = new URL(target);
if (!url.pathname.includes('/-/blob/')) {
if (!url.pathname.includes('/blob/')) {
throw new Error('Please provide full path to yaml file from GitLab');
}
try {
let repo = url.pathname.split('/-/blob/')[0];
let repo = url.pathname.split('/-/blob/')[0].split('/blob/')[0];
// Get gitlab relative path
const relativePath = getGitLabIntegrationRelativePath(config);