Merge pull request #3764 from backstage/orkohunter/techdocs-backend-refactor-factory-methods

This commit is contained in:
Himanshu Mishra
2020-12-21 19:10:38 +01:00
committed by GitHub
9 changed files with 158 additions and 75 deletions
+40
View File
@@ -0,0 +1,40 @@
---
'@backstage/create-app': patch
'@backstage/techdocs-common': minor
'@backstage/plugin-techdocs-backend': minor
---
techdocs-backend: Simplified file, removing individual preparers and generators.
techdocs-backend: UrlReader is now available to use in preparers.
In your Backstage app, `packages/backend/plugins/techdocs.ts` file has now been simplified,
to remove registering individual preparers and generators.
Please update the file when upgrading the version of `@backstage/plugin-techdocs-backend` package.
```typescript
const preparers = await Preparers.fromConfig(config, {
logger,
reader,
});
const generators = await Generators.fromConfig(config, {
logger,
});
const publisher = await Publisher.fromConfig(config, {
logger,
discovery,
});
```
You should be able to remove unnecessary imports, and just do
```typescript
import {
createRouter,
Preparers,
Generators,
Publisher,
} from '@backstage/plugin-techdocs-backend';
```
+13 -22
View File
@@ -72,12 +72,8 @@ add the following
```typescript
import {
createRouter,
DirectoryPreparer,
Preparers,
Generators,
TechdocsGenerator,
CommonGitPreparer,
UrlPreparer,
Publisher,
} from '@backstage/plugin-techdocs-backend';
import { PluginEnvironment } from '../types';
@@ -90,30 +86,25 @@ export default async function createPlugin({
reader,
}: PluginEnvironment) {
// Preparers are responsible for fetching source files for documentation.
const preparers = new Preparers();
const directoryPreparer = new DirectoryPreparer(logger);
preparers.register('dir', directoryPreparer);
const commonGitPreparer = new CommonGitPreparer(logger);
preparers.register('github', commonGitPreparer);
preparers.register('gitlab', commonGitPreparer);
preparers.register('azure/api', commonGitPreparer);
const urlPreparer = new UrlPreparer(reader, logger);
preparers.register('url', urlPreparer);
const preparers = await Preparers.fromConfig(config, {
logger,
reader,
});
// Generators are used for generating documentation sites.
const generators = new Generators();
const techdocsGenerator = new TechdocsGenerator(logger, config);
generators.register('techdocs', techdocsGenerator);
const generators = await Generators.fromConfig(config, {
logger,
});
// Publishers are used for
// Publisher is used for
// 1. Publishing generated files to storage
// 2. Fetching files from storage and passing them to TechDocs frontend.
const publisher = Publisher.fromConfig(config, logger, discovery);
const publisher = await Publisher.fromConfig(config, {
logger,
discovery,
});
// Docker client used by the generators.
// Docker client (conditionally) used by the generators, based on techdocs.generators config.
const dockerClient = new Docker();
return await createRouter({
+13 -22
View File
@@ -15,12 +15,8 @@
*/
import {
createRouter,
DirectoryPreparer,
Preparers,
Generators,
TechdocsGenerator,
CommonGitPreparer,
UrlPreparer,
Publisher,
} from '@backstage/plugin-techdocs-backend';
import { PluginEnvironment } from '../types';
@@ -33,30 +29,25 @@ export default async function createPlugin({
reader,
}: PluginEnvironment) {
// Preparers are responsible for fetching source files for documentation.
const preparers = new Preparers();
const directoryPreparer = new DirectoryPreparer(logger);
preparers.register('dir', directoryPreparer);
const commonGitPreparer = new CommonGitPreparer(logger);
preparers.register('github', commonGitPreparer);
preparers.register('gitlab', commonGitPreparer);
preparers.register('azure/api', commonGitPreparer);
const urlPreparer = new UrlPreparer(reader, logger);
preparers.register('url', urlPreparer);
const preparers = await Preparers.fromConfig(config, {
logger,
reader,
});
// Generators are used for generating documentation sites.
const generators = new Generators();
const techdocsGenerator = new TechdocsGenerator(logger, config);
generators.register('techdocs', techdocsGenerator);
const generators = await Generators.fromConfig(config, {
logger,
});
// Publishers are used for
// Publisher is used for
// 1. Publishing generated files to storage
// 2. Fetching files from storage and passing them to TechDocs frontend.
const publisher = Publisher.fromConfig(config, logger, discovery);
const publisher = await Publisher.fromConfig(config, {
logger,
discovery,
});
// Docker client used by the generators.
// Docker client (conditionally) used by the generators, based on techdocs.generators config.
const dockerClient = new Docker();
return await createRouter({
@@ -1,10 +1,7 @@
import {
createRouter,
DirectoryPreparer,
Preparers,
Generators,
TechdocsGenerator,
CommonGitPreparer,
Publisher,
} from '@backstage/plugin-techdocs-backend';
import { PluginEnvironment } from '../types';
@@ -14,22 +11,28 @@ export default async function createPlugin({
logger,
config,
discovery,
reader,
}: PluginEnvironment) {
const generators = new Generators();
const techdocsGenerator = new TechdocsGenerator(logger, config);
// Preparers are responsible for fetching source files for documentation.
const preparers = await Preparers.fromConfig(config, {
logger,
reader,
});
generators.register('techdocs', techdocsGenerator);
// Generators are used for generating documentation sites.
const generators = await Generators.fromConfig(config, {
logger,
});
const preparers = new Preparers();
const directoryPreparer = new DirectoryPreparer(logger);
const commonGitPreparer = new CommonGitPreparer(logger);
preparers.register('dir', directoryPreparer);
preparers.register('github', commonGitPreparer);
preparers.register('gitlab', commonGitPreparer);
const publisher = Publisher.fromConfig(config, logger, discovery);
// Publisher is used for
// 1. Publishing generated files to storage
// 2. Fetching files from storage and passing them to TechDocs frontend.
const publisher = await Publisher.fromConfig(config, {
logger,
discovery,
});
// Docker client (conditionally) used by the generators, based on techdocs.generators config.
const dockerClient = new Docker();
return await createRouter({
@@ -14,18 +14,32 @@
* limitations under the License.
*/
import { Logger } from 'winston';
import { Entity } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { TechdocsGenerator } from '.';
import {
GeneratorBase,
SupportedGeneratorKey,
GeneratorBuilder,
} from './types';
import { Entity } from '@backstage/catalog-model';
import { getGeneratorKey } from './helpers';
export class Generators implements GeneratorBuilder {
private generatorMap = new Map<SupportedGeneratorKey, GeneratorBase>();
static async fromConfig(
config: Config,
{ logger }: { logger: Logger },
): Promise<GeneratorBuilder> {
const generators = new Generators();
const techdocsGenerator = new TechdocsGenerator(logger, config);
generators.register('techdocs', techdocsGenerator);
return generators;
}
register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase) {
this.generatorMap.set(generatorKey, generator);
}
@@ -13,14 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { PreparerBase, RemoteProtocol, PreparerBuilder } from './types';
import { Logger } from 'winston';
import { UrlReader } from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { DirectoryPreparer, CommonGitPreparer, UrlPreparer } from '.';
import { PreparerBase, RemoteProtocol, PreparerBuilder } from './types';
import { parseReferenceAnnotation } from '../../helpers';
type factoryOptions = {
logger: Logger;
reader: UrlReader;
};
export class Preparers implements PreparerBuilder {
private preparerMap = new Map<RemoteProtocol, PreparerBase>();
static async fromConfig(
// @ts-ignore
// Config not used now, but will be used in urlPreparer when it starts using
// @backstage/integration to get the tokens for providers.
config: Config,
{ logger, reader }: factoryOptions,
): Promise<PreparerBuilder> {
const preparers = new Preparers();
const directoryPreparer = new DirectoryPreparer(logger);
preparers.register('dir', directoryPreparer);
const commonGitPreparer = new CommonGitPreparer(logger);
preparers.register('github', commonGitPreparer);
preparers.register('gitlab', commonGitPreparer);
preparers.register('azure/api', commonGitPreparer);
const urlPreparer = new UrlPreparer(reader, logger);
preparers.register('url', urlPreparer);
return preparers;
}
register(protocol: RemoteProtocol, preparer: PreparerBase) {
this.preparerMap.set(protocol, preparer);
}
@@ -23,24 +23,27 @@ import { LocalPublish } from './local';
import { GoogleGCSPublish } from './googleStorage';
const logger = getVoidLogger();
const testDiscovery: jest.Mocked<PluginEndpointDiscovery> = {
const discovery: jest.Mocked<PluginEndpointDiscovery> = {
getBaseUrl: jest.fn().mockResolvedValueOnce('http://localhost:7000'),
getExternalBaseUrl: jest.fn(),
};
describe('Publisher', () => {
it('should create local publisher by default', () => {
it('should create local publisher by default', async () => {
const mockConfig = new ConfigReader({
techdocs: {
requestUrl: 'http://localhost:7000',
},
});
const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery);
const publisher = await Publisher.fromConfig(mockConfig, {
logger,
discovery,
});
expect(publisher).toBeInstanceOf(LocalPublish);
});
it('should create local publisher from config', () => {
it('should create local publisher from config', async () => {
const mockConfig = new ConfigReader({
techdocs: {
requestUrl: 'http://localhost:7000',
@@ -50,11 +53,14 @@ describe('Publisher', () => {
},
});
const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery);
const publisher = await Publisher.fromConfig(mockConfig, {
logger,
discovery,
});
expect(publisher).toBeInstanceOf(LocalPublish);
});
it('should create google gcs publisher from config', () => {
it('should create google gcs publisher from config', async () => {
const mockConfig = new ConfigReader({
techdocs: {
requestUrl: 'http://localhost:7000',
@@ -69,7 +75,10 @@ describe('Publisher', () => {
},
});
const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery);
const publisher = await Publisher.fromConfig(mockConfig, {
logger,
discovery,
});
expect(publisher).toBeInstanceOf(GoogleGCSPublish);
});
});
@@ -21,16 +21,20 @@ import { PublisherType, PublisherBase } from './types';
import { LocalPublish } from './local';
import { GoogleGCSPublish } from './googleStorage';
type factoryOptions = {
logger: Logger;
discovery: PluginEndpointDiscovery;
};
/**
* Factory class to create a TechDocs publisher based on defined publisher type in app config.
* Uses `techdocs.publisher.type`.
*/
export class Publisher {
static fromConfig(
static async fromConfig(
config: Config,
logger: Logger,
discovery: PluginEndpointDiscovery,
): PublisherBase {
{ logger, discovery }: factoryOptions,
): Promise<PublisherBase> {
const publisherType = (config.getOptionalString(
'techdocs.publisher.type',
) ?? 'local') as PublisherType;
@@ -59,7 +59,7 @@ export async function startStandaloneServer(
const techdocsGenerator = new TechdocsGenerator(logger, config);
generators.register('techdocs', techdocsGenerator);
const publisher = Publisher.fromConfig(config, logger, discovery);
const publisher = await Publisher.fromConfig(config, { logger, discovery });
const dockerClient = new Docker();