Merge pull request #4353 from backstage/freben/resolve-url

integration: add the resolveUrl method
This commit is contained in:
Fredrik Adelöw
2021-02-03 21:22:37 +01:00
committed by GitHub
12 changed files with 222 additions and 15 deletions
+1
View File
@@ -34,6 +34,7 @@
"@backstage/backend-common": "^0.5.1",
"@backstage/catalog-model": "^0.7.0",
"@backstage/config": "^0.1.2",
"@backstage/integration": "^0.3.1",
"@octokit/graphql": "^4.5.8",
"@types/express": "^4.17.6",
"@types/ldapjs": "^1.0.9",
@@ -15,30 +15,73 @@
*/
import { LocationSpec } from '@backstage/catalog-model';
import { toAbsoluteUrl } from './LocationEntityProcessor';
import { ConfigReader } from '@backstage/config';
import {
ScmIntegrations,
ScmIntegrationRegistry,
} from '@backstage/integration';
import path from 'path';
import { toAbsoluteUrl } from './LocationEntityProcessor';
describe('LocationEntityProcessor', () => {
describe('toAbsoluteUrl', () => {
it('handles files', () => {
const integrations = ({} as unknown) as ScmIntegrationRegistry;
const base: LocationSpec = {
type: 'file',
target: `some${path.sep}path${path.sep}catalog-info.yaml`,
};
expect(toAbsoluteUrl(base, `.${path.sep}c`)).toBe(
expect(toAbsoluteUrl(integrations, base, `.${path.sep}c`)).toBe(
`some${path.sep}path${path.sep}c`,
);
expect(toAbsoluteUrl(base, `${path.sep}c`)).toBe(`${path.sep}c`);
expect(toAbsoluteUrl(integrations, base, `${path.sep}c`)).toBe(
`${path.sep}c`,
);
});
it('handles urls', () => {
const integrations = ScmIntegrations.fromConfig(new ConfigReader({}));
const base: LocationSpec = {
type: 'url',
target: 'http://a.com/b/catalog-info.yaml',
};
expect(toAbsoluteUrl(base, './c/d')).toBe('http://a.com/b/c/d');
expect(toAbsoluteUrl(base, 'c/d')).toBe('http://a.com/b/c/d');
expect(toAbsoluteUrl(base, 'http://b.com/z')).toBe('http://b.com/z');
jest.spyOn(integrations, 'resolveUrl');
expect(toAbsoluteUrl(integrations, base, './c/d')).toBe(
'http://a.com/b/c/d',
);
expect(toAbsoluteUrl(integrations, base, 'c/d')).toBe(
'http://a.com/b/c/d',
);
expect(toAbsoluteUrl(integrations, base, 'http://b.com/z')).toBe(
'http://b.com/z',
);
expect(integrations.resolveUrl).toBeCalledTimes(3);
});
it('handles azure urls specifically', () => {
const integrations = ScmIntegrations.fromConfig(
new ConfigReader({
integrations: {
azure: [{ host: 'dev.azure.com' }],
},
}),
);
expect(
toAbsoluteUrl(
integrations,
{
type: 'url',
target:
'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
},
'./a.yaml',
),
).toBe(
'https://dev.azure.com/organization/project/_git/repository?path=%2Fa.yaml',
);
});
});
});
@@ -15,11 +15,16 @@
*/
import { Entity, LocationEntity, LocationSpec } from '@backstage/catalog-model';
import { ScmIntegrationRegistry } from '@backstage/integration';
import path from 'path';
import * as result from './results';
import { CatalogProcessor, CatalogProcessorEmit } from './types';
import path from 'path';
export function toAbsoluteUrl(base: LocationSpec, target: string): string {
export function toAbsoluteUrl(
integrations: ScmIntegrationRegistry,
base: LocationSpec,
target: string,
): string {
try {
if (base.type === 'file') {
if (target.startsWith('.')) {
@@ -27,13 +32,19 @@ export function toAbsoluteUrl(base: LocationSpec, target: string): string {
}
return target;
}
return new URL(target, base.target).toString();
return integrations.resolveUrl({ url: target, base: base.target });
} catch (e) {
return target;
}
}
export class LocationRefProcessor implements CatalogProcessor {
type Options = {
integrations: ScmIntegrationRegistry;
};
export class LocationEntityProcessor implements CatalogProcessor {
constructor(private readonly options: Options) {}
async postProcessEntity(
entity: Entity,
location: LocationSpec,
@@ -47,7 +58,7 @@ export class LocationRefProcessor implements CatalogProcessor {
emit(
result.inputError(
location,
`LocationRefProcessor cannot handle ${type} type location with target ${location.target} that ends with a path separator`,
`LocationEntityProcessor cannot handle ${type} type location with target ${location.target} that ends with a path separator`,
),
);
}
@@ -61,7 +72,11 @@ export class LocationRefProcessor implements CatalogProcessor {
}
for (const maybeRelativeTarget of targets) {
const target = toAbsoluteUrl(location, maybeRelativeTarget);
const target = toAbsoluteUrl(
this.options.integrations,
location,
maybeRelativeTarget,
);
emit(result.location({ type, target }, false));
}
}
@@ -23,7 +23,7 @@ export { CodeOwnersProcessor } from './CodeOwnersProcessor';
export { FileReaderProcessor } from './FileReaderProcessor';
export { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor';
export { LdapOrgReaderProcessor } from './LdapOrgReaderProcessor';
export { LocationRefProcessor } from './LocationEntityProcessor';
export { LocationEntityProcessor } from './LocationEntityProcessor';
export { MicrosoftGraphOrgReaderProcessor } from './MicrosoftGraphOrgReaderProcessor';
export { PlaceholderProcessor } from './PlaceholderProcessor';
export type { PlaceholderResolver } from './PlaceholderProcessor';
@@ -26,6 +26,7 @@ import {
Validators,
} from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import lodash from 'lodash';
import { Logger } from 'winston';
import {
@@ -46,8 +47,8 @@ import {
HigherOrderOperation,
HigherOrderOperations,
LdapOrgReaderProcessor,
LocationEntityProcessor,
LocationReaders,
LocationRefProcessor,
MicrosoftGraphOrgReaderProcessor,
PlaceholderProcessor,
PlaceholderResolver,
@@ -280,6 +281,7 @@ export class CatalogBuilder {
private buildProcessors(): CatalogProcessor[] {
const { config, logger, reader } = this.env;
const integrations = ScmIntegrations.fromConfig(config);
this.checkDeprecatedReaderProcessors();
@@ -306,7 +308,7 @@ export class CatalogBuilder {
MicrosoftGraphOrgReaderProcessor.fromConfig(config, { logger }),
new UrlReaderProcessor({ reader, logger }),
new CodeOwnersProcessor({ reader, logger }),
new LocationRefProcessor(),
new LocationEntityProcessor({ integrations }),
new AnnotateLocationEntityProcessor(),
);
}