From 1e97419d305418c224b916c8a9d8c1cd00d9b9cc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Oct 2020 15:50:49 +0200 Subject: [PATCH] backend-common: merge GitlabReaderProcessor functionality into GitlabUrlReader --- .../src/reading/GitlabReaderProcessor.ts | 89 ------------------- .../src/reading/GitlabUrlReader.test.ts | 30 ++++++- .../src/reading/GitlabUrlReader.ts | 46 +++++++++- 3 files changed, 71 insertions(+), 94 deletions(-) delete mode 100644 packages/backend-common/src/reading/GitlabReaderProcessor.ts diff --git a/packages/backend-common/src/reading/GitlabReaderProcessor.ts b/packages/backend-common/src/reading/GitlabReaderProcessor.ts deleted file mode 100644 index c33b388e1a..0000000000 --- a/packages/backend-common/src/reading/GitlabReaderProcessor.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { LocationSpec } from '@backstage/catalog-model'; -import fetch from 'node-fetch'; -import * as result from './results'; -import { LocationProcessor, LocationProcessorEmit } from './types'; - -export class GitlabReaderProcessor implements LocationProcessor { - async readLocation( - location: LocationSpec, - optional: boolean, - emit: LocationProcessorEmit, - ): Promise { - if (location.type !== 'gitlab') { - return false; - } - - try { - const url = this.buildRawUrl(location.target); - - const response = await fetch(url.toString()); - - if (response.ok) { - const data = await response.buffer(); - emit(result.data(location, data)); - } else { - const message = `${location.target} could not be read as ${url}, ${response.status} ${response.statusText}`; - if (response.status === 404) { - if (!optional) { - throw result.notFoundError(location, message); - } - } else { - throw result.generalError(location, message); - } - } - } catch (e) { - const message = `Unable to read ${location.type} ${location.target}, ${e}`; - emit(result.generalError(location, message)); - } - - return true; - } - - // Converts - // from: https://gitlab.example.com/a/b/blob/master/c.yaml - // to: https://gitlab.example.com/a/b/raw/master/c.yaml - private buildRawUrl(target: string): URL { - try { - const url = new URL(target); - - const [empty, userOrOrg, repoName, , ...restOfPath] = url.pathname - .split('/') - // for the common case https://gitlab.example.com/a/b/-/blob/master/c.yaml - .filter(path => path !== '-'); - - if ( - empty !== '' || - userOrOrg === '' || - repoName === '' || - !restOfPath.join('/').match(/\.yaml$/) - ) { - throw new Error('Wrong GitLab URL'); - } - - // Replace 'blob' with 'raw' - url.pathname = [empty, userOrOrg, repoName, 'raw', ...restOfPath].join( - '/', - ); - - return url; - } catch (e) { - throw new Error(`Incorrect url: ${target}, ${e}`); - } - } -} diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-common/src/reading/GitlabUrlReader.test.ts index 17023d9120..60a8d19db3 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.test.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.test.ts @@ -35,7 +35,7 @@ describe('GitlabUrlReader', () => { }, ]); - it('should build raw api', () => { + it('should build project urls', () => { const processor = new GitlabUrlReader( readConfig(createConfig(undefined))[0], ); @@ -69,7 +69,33 @@ describe('GitlabUrlReader', () => { for (const test of tests) { if (test.url) { - expect(processor.buildRawUrl(test.target, 12345).toString()).toEqual( + expect( + processor.buildProjectUrl(test.target, 12345).toString(), + ).toEqual(test.url.toString()); + } else { + throw new Error( + 'This should not have happened. Either err or url should have matched.', + ); + } + } + }); + + it('should build raw urls', () => { + const processor = new GitlabUrlReader( + readConfig(createConfig(undefined))[0], + ); + + const tests = [ + { + target: 'https://gitlab.example.com/a/b/blob/master/c.yaml', + url: new URL('https://gitlab.example.com/a/b/raw/master/c.yaml'), + err: undefined, + }, + ]; + + for (const test of tests) { + if (test.url) { + expect(processor.buildRawUrl(test.target).toString()).toEqual( test.url.toString(), ); } else { diff --git a/packages/backend-common/src/reading/GitlabUrlReader.ts b/packages/backend-common/src/reading/GitlabUrlReader.ts index 56ae91bb4b..9931b6d9d5 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.ts @@ -68,8 +68,16 @@ export class GitlabUrlReader implements UrlReader { } async read(url: string): Promise { - const projectID = await this.getProjectID(url); - const builtUrl = this.buildRawUrl(url, projectID); + // TODO(Rugvip): merged the old GitlabReaderProcessor in here and used + // the existence of /~/blob/ to switch the logic. Don't know if this + // makes sense and it might require some more work. + let builtUrl: URL; + if (url.includes('/-/blob/')) { + const projectID = await this.getProjectID(url); + builtUrl = this.buildProjectUrl(url, projectID); + } else { + builtUrl = this.buildRawUrl(url); + } let response: Response; try { @@ -89,9 +97,41 @@ export class GitlabUrlReader implements UrlReader { throw new Error(message); } + // Converts + // from: https://gitlab.example.com/a/b/blob/master/c.yaml + // to: https://gitlab.example.com/a/b/raw/master/c.yaml + buildRawUrl(target: string): URL { + try { + const url = new URL(target); + + const [empty, userOrOrg, repoName, ...restOfPath] = url.pathname + .split('/') + // for the common case https://gitlab.example.com/a/b/-/blob/master/c.yaml + .filter(path => path !== '-'); + + if ( + empty !== '' || + userOrOrg === '' || + repoName === '' || + !restOfPath.join('/').match(/\.yaml$/) + ) { + throw new Error('Wrong GitLab URL'); + } + + // Replace 'blob' with 'raw' + url.pathname = [empty, userOrOrg, repoName, 'raw', ...restOfPath].join( + '/', + ); + + return url; + } catch (e) { + throw new Error(`Incorrect url: ${target}, ${e}`); + } + } + // convert https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath // to https://gitlab.com/api/v4/projects//repository/files/filepath?ref=branch - buildRawUrl(target: string, projectID: Number): URL { + buildProjectUrl(target: string, projectID: Number): URL { try { const url = new URL(target);