feat: allow repositories with nested namespace
Signed-off-by: Antonio Musolino <antoniomusolino007@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': minor
|
||||
---
|
||||
|
||||
added the possibility to handle raw Gitlab URLs with nested namespaces
|
||||
@@ -34,6 +34,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^1.0.1-next.0",
|
||||
"@backstage/errors": "^1.0.0",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"git-url-parse": "^11.6.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
|
||||
@@ -87,6 +87,26 @@ describe('gitlab core', () => {
|
||||
url: 'https://gitlab.example.com/a/b/blob/master/c.yaml',
|
||||
result: 'https://gitlab.example.com/a/b/raw/master/c.yaml',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url: 'https://gitlab.example.com/a/b/repo/blob/master/c.yaml',
|
||||
result: 'https://gitlab.example.com/a/b/repo/raw/master/c.yaml',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url: 'https://gitlab.example.com/a/blob/blob/master/c.yaml',
|
||||
result: 'https://gitlab.example.com/a/blob/raw/master/c.yaml',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url: 'https://gitlab.example.com/a/b/blob/blob/c.yaml',
|
||||
result: 'https://gitlab.example.com/a/b/raw/blob/c.yaml',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url: 'https://gitlab.example.com/a//blob/blob/c.yaml',
|
||||
result: 'https://gitlab.example.com/a/blob/raw/c.yaml',
|
||||
},
|
||||
])('should handle happy path %#', async ({ config, url, result }) => {
|
||||
await expect(getGitLabFileFetchUrl(url, config)).resolves.toBe(result);
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
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
|
||||
@@ -66,31 +67,34 @@ export function getGitLabRequestOptions(config: GitLabIntegrationConfig): {
|
||||
}
|
||||
|
||||
// Converts
|
||||
// from: https://gitlab.example.com/a/b/blob/master/c.yaml
|
||||
// to: https://gitlab.example.com/a/b/raw/master/c.yaml
|
||||
// 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 [empty, userOrOrg, repoName, blobKeyword, ...restOfPath] =
|
||||
url.pathname.split('/');
|
||||
const splitPath = url.pathname.split('/').filter(Boolean);
|
||||
|
||||
if (
|
||||
empty !== '' ||
|
||||
userOrOrg === '' ||
|
||||
repoName === '' ||
|
||||
blobKeyword !== 'blob' ||
|
||||
!restOfPath.join('/').match(/\.(yaml|yml)$/)
|
||||
) {
|
||||
throw new Error('Wrong GitLab URL');
|
||||
// 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 = [empty, userOrOrg, repoName, 'raw', ...restOfPath].join('/');
|
||||
url.pathname = [...repoPath, 'raw', ...restOfPath].join('/');
|
||||
|
||||
return url;
|
||||
} catch (e) {
|
||||
throw new Error(`Incorrect url: ${target}, ${e}`);
|
||||
throw new InputError(`Incorrect url: ${target}, ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user