integration: add the basics of cross-integration concerns
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/integration': minor
|
||||
---
|
||||
|
||||
Add the basics of cross-integration concerns
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 { Config } from '@backstage/config';
|
||||
import { AzureIntegration } from './azure/AzureIntegration';
|
||||
import { BitbucketIntegration } from './bitbucket/BitbucketIntegration';
|
||||
import { GitHubIntegration } from './github/GitHubIntegration';
|
||||
import { GitLabIntegration } from './gitlab/GitLabIntegration';
|
||||
import {
|
||||
ScmIntegration,
|
||||
ScmIntegrationPredicateTuple,
|
||||
ScmIntegrations,
|
||||
} from './types';
|
||||
|
||||
export class ScmIntegrationsImpl implements ScmIntegrations {
|
||||
static fromConfig(config: Config): ScmIntegrationsImpl {
|
||||
return new ScmIntegrationsImpl([
|
||||
...AzureIntegration.factory({ config }),
|
||||
...BitbucketIntegration.factory({ config }),
|
||||
...GitHubIntegration.factory({ config }),
|
||||
...GitLabIntegration.factory({ config }),
|
||||
]);
|
||||
}
|
||||
|
||||
constructor(private readonly integrations: ScmIntegrationPredicateTuple[]) {}
|
||||
|
||||
list(): ScmIntegration[] {
|
||||
return this.integrations.map(i => i.integration);
|
||||
}
|
||||
|
||||
byName(name: string): ScmIntegration | undefined {
|
||||
return this.integrations.map(i => i.integration).find(i => i.name === name);
|
||||
}
|
||||
|
||||
byUrl(url: string): ScmIntegration | undefined {
|
||||
return this.integrations.find(i => i.predicate(new URL(url)))?.integration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 { ConfigReader } from '@backstage/config';
|
||||
import { AzureIntegration } from './AzureIntegration';
|
||||
|
||||
describe('AzureIntegration', () => {
|
||||
it('has a working factory', () => {
|
||||
const integrations = AzureIntegration.factory({
|
||||
config: ConfigReader.fromConfigs([
|
||||
{
|
||||
context: '',
|
||||
data: {
|
||||
integrations: {
|
||||
azure: [
|
||||
{
|
||||
host: 'h.com',
|
||||
token: 'token',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
});
|
||||
expect(integrations.length).toBe(2); // including default
|
||||
expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns the basics', () => {
|
||||
const integration = new AzureIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('azure');
|
||||
expect(integration.name).toBe('h.com');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 { ScmIntegration, ScmIntegrationFactory } from '../types';
|
||||
import { AzureIntegrationConfig, readAzureIntegrationConfigs } from './config';
|
||||
|
||||
export class AzureIntegration implements ScmIntegration {
|
||||
static factory: ScmIntegrationFactory = ({ config }) => {
|
||||
const configs = readAzureIntegrationConfigs(
|
||||
config.getOptionalConfigArray('integrations.azure') ?? [],
|
||||
);
|
||||
return configs.map(integration => ({
|
||||
predicate: (url: URL) => url.host === integration.host,
|
||||
integration: new AzureIntegration(integration),
|
||||
}));
|
||||
};
|
||||
|
||||
constructor(private readonly config: AzureIntegrationConfig) {}
|
||||
|
||||
get type(): string {
|
||||
return 'azure';
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this.config.host;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 { ConfigReader } from '@backstage/config';
|
||||
import { BitbucketIntegration } from './BitbucketIntegration';
|
||||
|
||||
describe('BitbucketIntegration', () => {
|
||||
it('has a working factory', () => {
|
||||
const integrations = BitbucketIntegration.factory({
|
||||
config: ConfigReader.fromConfigs([
|
||||
{
|
||||
context: '',
|
||||
data: {
|
||||
integrations: {
|
||||
bitbucket: [
|
||||
{
|
||||
host: 'h.com',
|
||||
apiBaseUrl: 'a',
|
||||
token: 't',
|
||||
username: 'u',
|
||||
appPassword: 'p',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
});
|
||||
expect(integrations.length).toBe(2); // including default
|
||||
expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns the basics', () => {
|
||||
const integration = new BitbucketIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('bitbucket');
|
||||
expect(integration.name).toBe('h.com');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 { ScmIntegration, ScmIntegrationFactory } from '../types';
|
||||
import {
|
||||
BitbucketIntegrationConfig,
|
||||
readBitbucketIntegrationConfigs,
|
||||
} from './config';
|
||||
|
||||
export class BitbucketIntegration implements ScmIntegration {
|
||||
static factory: ScmIntegrationFactory = ({ config }) => {
|
||||
const configs = readBitbucketIntegrationConfigs(
|
||||
config.getOptionalConfigArray('integrations.bitbucket') ?? [],
|
||||
);
|
||||
return configs.map(integration => ({
|
||||
predicate: (url: URL) => url.host === integration.host,
|
||||
integration: new BitbucketIntegration(integration),
|
||||
}));
|
||||
};
|
||||
|
||||
constructor(private readonly config: BitbucketIntegrationConfig) {}
|
||||
|
||||
get type(): string {
|
||||
return 'bitbucket';
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this.config.host;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 { ConfigReader } from '@backstage/config';
|
||||
import { GitHubIntegration } from './GitHubIntegration';
|
||||
|
||||
describe('GitHubIntegration', () => {
|
||||
it('has a working factory', () => {
|
||||
const integrations = GitHubIntegration.factory({
|
||||
config: ConfigReader.fromConfigs([
|
||||
{
|
||||
context: '',
|
||||
data: {
|
||||
integrations: {
|
||||
github: [
|
||||
{
|
||||
host: 'h.com',
|
||||
apiBaseUrl: 'a',
|
||||
rawBaseUrl: 'r',
|
||||
token: 't',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
});
|
||||
expect(integrations.length).toBe(2); // including default
|
||||
expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns the basics', () => {
|
||||
const integration = new GitHubIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('github');
|
||||
expect(integration.name).toBe('h.com');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 { ScmIntegration, ScmIntegrationFactory } from '../types';
|
||||
import {
|
||||
GitHubIntegrationConfig,
|
||||
readGitHubIntegrationConfigs,
|
||||
} from './config';
|
||||
|
||||
export class GitHubIntegration implements ScmIntegration {
|
||||
static factory: ScmIntegrationFactory = ({ config }) => {
|
||||
const configs = readGitHubIntegrationConfigs(
|
||||
config.getOptionalConfigArray('integrations.github') ?? [],
|
||||
);
|
||||
return configs.map(integration => ({
|
||||
predicate: (url: URL) => url.host === integration.host,
|
||||
integration: new GitHubIntegration(integration),
|
||||
}));
|
||||
};
|
||||
|
||||
constructor(private readonly config: GitHubIntegrationConfig) {}
|
||||
|
||||
get type(): string {
|
||||
return 'github';
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this.config.host;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 { ConfigReader } from '@backstage/config';
|
||||
import { GitLabIntegration } from './GitLabIntegration';
|
||||
|
||||
describe('GitLabIntegration', () => {
|
||||
it('has a working factory', () => {
|
||||
const integrations = GitLabIntegration.factory({
|
||||
config: ConfigReader.fromConfigs([
|
||||
{
|
||||
context: '',
|
||||
data: {
|
||||
integrations: {
|
||||
gitlab: [
|
||||
{
|
||||
host: 'h.com',
|
||||
token: 't',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
});
|
||||
expect(integrations.length).toBe(2); // including default
|
||||
expect(integrations[0].predicate(new URL('https://h.com/a'))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns the basics', () => {
|
||||
const integration = new GitLabIntegration({ host: 'h.com' } as any);
|
||||
expect(integration.type).toBe('gitlab');
|
||||
expect(integration.name).toBe('h.com');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 { ScmIntegration, ScmIntegrationFactory } from '../types';
|
||||
import {
|
||||
GitLabIntegrationConfig,
|
||||
readGitLabIntegrationConfigs,
|
||||
} from './config';
|
||||
|
||||
export class GitLabIntegration implements ScmIntegration {
|
||||
static factory: ScmIntegrationFactory = ({ config }) => {
|
||||
const configs = readGitLabIntegrationConfigs(
|
||||
config.getOptionalConfigArray('integrations.gitlab') ?? [],
|
||||
);
|
||||
return configs.map(integration => ({
|
||||
predicate: (url: URL) => url.host === integration.host,
|
||||
integration: new GitLabIntegration(integration),
|
||||
}));
|
||||
};
|
||||
|
||||
constructor(private readonly config: GitLabIntegrationConfig) {}
|
||||
|
||||
get type(): string {
|
||||
return 'gitlab';
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this.config.host;
|
||||
}
|
||||
}
|
||||
@@ -18,3 +18,4 @@ export * from './azure';
|
||||
export * from './bitbucket';
|
||||
export * from './github';
|
||||
export * from './gitlab';
|
||||
export type { ScmIntegration, ScmIntegrations } from './types';
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 { Config } from '@backstage/config';
|
||||
|
||||
/**
|
||||
* Encapsulates a single SCM integration.
|
||||
*/
|
||||
export type ScmIntegration = {
|
||||
type: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds all registered SCM integrations.
|
||||
*/
|
||||
export type ScmIntegrations = {
|
||||
/**
|
||||
* Lists all registered integrations.
|
||||
*/
|
||||
list(): ScmIntegration[];
|
||||
|
||||
/**
|
||||
* Fetches a named integration
|
||||
*
|
||||
* @param name The name of a registered integration
|
||||
*/
|
||||
byName(name: string): ScmIntegration | undefined;
|
||||
|
||||
/**
|
||||
* Fetches an integration by URL
|
||||
*
|
||||
* @param name A URL that matches a registered integration
|
||||
*/
|
||||
byUrl(url: string): ScmIntegration | undefined;
|
||||
};
|
||||
|
||||
export type ScmIntegrationPredicateTuple = {
|
||||
predicate: (url: URL) => boolean;
|
||||
integration: ScmIntegration;
|
||||
};
|
||||
|
||||
export type ScmIntegrationFactory = (options: {
|
||||
config: Config;
|
||||
}) => ScmIntegrationPredicateTuple[];
|
||||
Reference in New Issue
Block a user