Merge pull request #23062 from backstage/rugvip/pr/55498e
jenkins-backend: migrated to use auth services
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-jenkins-backend': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Both `createRouter` and `DefaultJenkinsInfoProvider.fromConfig` now require the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support new auth services.
|
||||
|
||||
The `JenkinsInfoProvider` interface has been updated to receive `credentials` of the type `BackstageCredentials` rather than a token.
|
||||
@@ -32,6 +32,8 @@ export default async function createPlugin(
|
||||
jenkinsInfoProvider: DefaultJenkinsInfoProvider.fromConfig({
|
||||
catalog,
|
||||
config: env.config,
|
||||
discovery: env.discovery,
|
||||
}),
|
||||
discovery: env.discovery,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,11 +3,15 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { AuthService } from '@backstage/backend-plugin-api';
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { BackstageCredentials } from '@backstage/backend-plugin-api';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DiscoveryService } from '@backstage/backend-plugin-api';
|
||||
import express from 'express';
|
||||
import { HttpAuthService } from '@backstage/backend-plugin-api';
|
||||
import { Logger } from 'winston';
|
||||
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
@@ -21,12 +25,14 @@ export class DefaultJenkinsInfoProvider implements JenkinsInfoProvider {
|
||||
static fromConfig(options: {
|
||||
config: Config;
|
||||
catalog: CatalogApi;
|
||||
discovery: DiscoveryService;
|
||||
auth?: AuthService;
|
||||
}): DefaultJenkinsInfoProvider;
|
||||
// (undocumented)
|
||||
getInstance(opt: {
|
||||
entityRef: CompoundEntityRef;
|
||||
jobFullName?: string;
|
||||
backstageToken?: string;
|
||||
credentials?: BackstageCredentials;
|
||||
}): Promise<JenkinsInfo>;
|
||||
// (undocumented)
|
||||
static readonly NEW_JENKINS_ANNOTATION = 'jenkins.io/job-full-name';
|
||||
@@ -61,7 +67,7 @@ export interface JenkinsInfoProvider {
|
||||
getInstance(options: {
|
||||
entityRef: CompoundEntityRef;
|
||||
jobFullName?: string;
|
||||
backstageToken?: string;
|
||||
credentials?: BackstageCredentials;
|
||||
}): Promise<JenkinsInfo>;
|
||||
}
|
||||
|
||||
@@ -86,6 +92,12 @@ export default jenkinsPlugin;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface RouterOptions {
|
||||
// (undocumented)
|
||||
auth?: AuthService;
|
||||
// (undocumented)
|
||||
discovery: DiscoveryService;
|
||||
// (undocumented)
|
||||
httpAuth?: HttpAuthService;
|
||||
// (undocumented)
|
||||
jenkinsInfoProvider: JenkinsInfoProvider;
|
||||
// (undocumented)
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@types/jenkins": "^1.0.0",
|
||||
"@types/supertest": "^2.0.8"
|
||||
|
||||
@@ -38,12 +38,24 @@ export const jenkinsPlugin = createBackendPlugin({
|
||||
httpRouter: coreServices.httpRouter,
|
||||
config: coreServices.rootConfig,
|
||||
catalogClient: catalogServiceRef,
|
||||
discovery: coreServices.discovery,
|
||||
auth: coreServices.auth,
|
||||
},
|
||||
async init({ logger, permissions, httpRouter, config, catalogClient }) {
|
||||
async init({
|
||||
logger,
|
||||
permissions,
|
||||
httpRouter,
|
||||
config,
|
||||
catalogClient,
|
||||
discovery,
|
||||
auth,
|
||||
}) {
|
||||
const winstonLogger = loggerToWinstonLogger(logger);
|
||||
const jenkinsInfoProvider = DefaultJenkinsInfoProvider.fromConfig({
|
||||
auth,
|
||||
config,
|
||||
catalog: catalogClient,
|
||||
discovery,
|
||||
});
|
||||
httpRouter.use(
|
||||
await createRouter({
|
||||
@@ -56,6 +68,8 @@ export const jenkinsPlugin = createBackendPlugin({
|
||||
* Info provider to be able to get all necessary information for the APIs
|
||||
*/
|
||||
jenkinsInfoProvider,
|
||||
discovery,
|
||||
auth,
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
import { getRootLogger } from '@backstage/backend-common';
|
||||
import yn from 'yn';
|
||||
import { startStandaloneServer } from './service/standaloneServer';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
|
||||
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
|
||||
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
|
||||
const logger = getRootLogger();
|
||||
const config = new ConfigReader({});
|
||||
|
||||
startStandaloneServer({ port, enableCors, logger }).catch(err => {
|
||||
startStandaloneServer({ config, port, enableCors, logger }).catch(err => {
|
||||
logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -20,6 +20,7 @@ import { JenkinsInfo } from './jenkinsInfoProvider';
|
||||
import { JenkinsBuild, JenkinsProject } from '../types';
|
||||
import { AuthorizeResult } from '@backstage/plugin-permission-common';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import { mockServices } from '@backstage/backend-test-utils';
|
||||
|
||||
jest.mock('jenkins');
|
||||
jest.mock('node-fetch');
|
||||
@@ -716,6 +717,8 @@ describe('JenkinsApi', () => {
|
||||
);
|
||||
});
|
||||
describe('rebuildProject', () => {
|
||||
const auth = mockServices.auth();
|
||||
|
||||
it('successfully rebuilds', async () => {
|
||||
mockFetch.mockResolvedValueOnce({ status: 200 } as Response);
|
||||
const status = await jenkinsApi.rebuildProject(
|
||||
@@ -723,6 +726,7 @@ describe('JenkinsApi', () => {
|
||||
jobFullName,
|
||||
buildNumber,
|
||||
resourceRef,
|
||||
{ credentials: await auth.getOwnServiceCredentials() },
|
||||
);
|
||||
expect(status).toEqual(200);
|
||||
});
|
||||
@@ -733,6 +737,7 @@ describe('JenkinsApi', () => {
|
||||
jobFullName,
|
||||
buildNumber,
|
||||
resourceRef,
|
||||
{ credentials: await auth.getOwnServiceCredentials() },
|
||||
);
|
||||
expect(status).toEqual(401);
|
||||
});
|
||||
@@ -750,6 +755,7 @@ describe('JenkinsApi', () => {
|
||||
jobFullName,
|
||||
buildNumber,
|
||||
resourceRef,
|
||||
{ credentials: await auth.getOwnServiceCredentials() },
|
||||
);
|
||||
expect(status).toEqual(401);
|
||||
});
|
||||
|
||||
@@ -23,12 +23,13 @@ import type {
|
||||
JenkinsProject,
|
||||
ScmDetails,
|
||||
} from '../types';
|
||||
import {
|
||||
AuthorizeResult,
|
||||
PermissionEvaluator,
|
||||
} from '@backstage/plugin-permission-common';
|
||||
import { AuthorizeResult } from '@backstage/plugin-permission-common';
|
||||
import { jenkinsExecutePermission } from '@backstage/plugin-jenkins-common';
|
||||
import fetch, { HeaderInit } from 'node-fetch';
|
||||
import {
|
||||
BackstageCredentials,
|
||||
PermissionsService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export class JenkinsApiImpl {
|
||||
private static readonly lastBuildTreeSpec = `lastBuild[
|
||||
@@ -75,7 +76,7 @@ export class JenkinsApiImpl {
|
||||
inQueue,
|
||||
builds[*]`;
|
||||
|
||||
constructor(private readonly permissionApi?: PermissionEvaluator) {}
|
||||
constructor(private readonly permissionApi?: PermissionsService) {}
|
||||
|
||||
/**
|
||||
* Get a list of projects for the given JenkinsInfo.
|
||||
@@ -160,12 +161,12 @@ export class JenkinsApiImpl {
|
||||
jobFullName: string,
|
||||
buildNumber: number,
|
||||
resourceRef: string,
|
||||
options?: { token?: string },
|
||||
options: { credentials: BackstageCredentials },
|
||||
): Promise<number> {
|
||||
if (this.permissionApi) {
|
||||
const response = await this.permissionApi.authorize(
|
||||
[{ permission: jenkinsExecutePermission, resourceRef }],
|
||||
{ token: options?.token },
|
||||
{ credentials: options.credentials },
|
||||
);
|
||||
// permission api returns always at least one item, we need to check only one result since we do not expect any additional results
|
||||
const { result } = response[0];
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
JenkinsConfig,
|
||||
JenkinsInfo,
|
||||
} from './jenkinsInfoProvider';
|
||||
import { mockServices } from '@backstage/backend-test-utils';
|
||||
|
||||
describe('JenkinsConfig', () => {
|
||||
it('Reads simple config and annotation', async () => {
|
||||
@@ -184,6 +185,8 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
return DefaultJenkinsInfoProvider.fromConfig({
|
||||
config,
|
||||
catalog: mockCatalog,
|
||||
discovery: mockServices.discovery(),
|
||||
auth: mockServices.auth(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -191,9 +194,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
const provider = configureProvider({ jenkins: {} }, undefined);
|
||||
await expect(provider.getInstance({ entityRef })).rejects.toThrow();
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
it('Reads simple config and annotation', async () => {
|
||||
@@ -218,9 +222,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toStrictEqual({
|
||||
baseUrl: 'https://jenkins.example.com',
|
||||
crumbIssuer: undefined,
|
||||
@@ -257,9 +262,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toMatchObject({
|
||||
baseUrl: 'https://jenkins.example.com',
|
||||
jobFullName: 'teamA/artistLookup-build',
|
||||
@@ -296,9 +302,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toMatchObject({
|
||||
baseUrl: 'https://jenkins.example.com',
|
||||
jobFullName: 'teamA/artistLookup-build',
|
||||
@@ -335,9 +342,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toMatchObject({
|
||||
baseUrl: 'https://jenkins-other.example.com',
|
||||
jobFullName: 'teamA/artistLookup-build',
|
||||
@@ -363,9 +371,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toMatchObject({
|
||||
baseUrl: 'https://jenkins.example.com',
|
||||
jobFullName: 'teamA/artistLookup-build',
|
||||
@@ -391,9 +400,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toMatchObject({
|
||||
baseUrl: 'https://jenkins.example.com',
|
||||
jobFullName: 'teamA/artistLookup-build',
|
||||
@@ -424,9 +434,10 @@ describe('DefaultJenkinsInfoProvider', () => {
|
||||
);
|
||||
const info: JenkinsInfo = await provider.getInstance({ entityRef });
|
||||
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(entityRef, {
|
||||
backstageToken: undefined,
|
||||
});
|
||||
expect(mockCatalog.getEntityByRef).toHaveBeenCalledWith(
|
||||
entityRef,
|
||||
undefined,
|
||||
);
|
||||
expect(info).toMatchObject({
|
||||
baseUrl: 'https://jenkins-other.example.com',
|
||||
jobFullName: 'teamA/artistLookup-build',
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createLegacyAuthAdapters } from '@backstage/backend-common';
|
||||
import {
|
||||
AuthService,
|
||||
BackstageCredentials,
|
||||
DiscoveryService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import {
|
||||
Entity,
|
||||
@@ -34,7 +40,7 @@ export interface JenkinsInfoProvider {
|
||||
*/
|
||||
jobFullName?: string;
|
||||
|
||||
backstageToken?: string;
|
||||
credentials?: BackstageCredentials;
|
||||
}): Promise<JenkinsInfo>;
|
||||
}
|
||||
|
||||
@@ -183,27 +189,37 @@ export class DefaultJenkinsInfoProvider implements JenkinsInfoProvider {
|
||||
private constructor(
|
||||
private readonly config: JenkinsConfig,
|
||||
private readonly catalog: CatalogApi,
|
||||
private readonly auth: AuthService,
|
||||
) {}
|
||||
|
||||
static fromConfig(options: {
|
||||
config: Config;
|
||||
catalog: CatalogApi;
|
||||
discovery: DiscoveryService;
|
||||
auth?: AuthService;
|
||||
}): DefaultJenkinsInfoProvider {
|
||||
const { auth } = createLegacyAuthAdapters(options);
|
||||
return new DefaultJenkinsInfoProvider(
|
||||
JenkinsConfig.fromConfig(options.config),
|
||||
options.catalog,
|
||||
auth,
|
||||
);
|
||||
}
|
||||
|
||||
async getInstance(opt: {
|
||||
entityRef: CompoundEntityRef;
|
||||
jobFullName?: string;
|
||||
backstageToken?: string;
|
||||
credentials?: BackstageCredentials;
|
||||
}): Promise<JenkinsInfo> {
|
||||
// load entity
|
||||
const entity = await this.catalog.getEntityByRef(opt.entityRef, {
|
||||
token: opt.backstageToken,
|
||||
});
|
||||
const entity = await this.catalog.getEntityByRef(
|
||||
opt.entityRef,
|
||||
opt.credentials &&
|
||||
(await this.auth.getPluginRequestToken({
|
||||
onBehalfOf: opt.credentials,
|
||||
targetPluginId: 'catalog',
|
||||
})),
|
||||
);
|
||||
if (!entity) {
|
||||
throw new Error(
|
||||
`Couldn't find entity with name: ${stringifyEntityRef(opt.entityRef)}`,
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { errorHandler } from '@backstage/backend-common';
|
||||
import {
|
||||
createLegacyAuthAdapters,
|
||||
errorHandler,
|
||||
} from '@backstage/backend-common';
|
||||
import express from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import { Logger } from 'winston';
|
||||
@@ -25,17 +28,24 @@ import {
|
||||
PermissionEvaluator,
|
||||
toPermissionEvaluator,
|
||||
} from '@backstage/plugin-permission-common';
|
||||
import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';
|
||||
import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { stringifyError } from '@backstage/errors';
|
||||
import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';
|
||||
import { jenkinsPermissions } from '@backstage/plugin-jenkins-common';
|
||||
import {
|
||||
AuthService,
|
||||
DiscoveryService,
|
||||
HttpAuthService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @public */
|
||||
export interface RouterOptions {
|
||||
logger: Logger;
|
||||
jenkinsInfoProvider: JenkinsInfoProvider;
|
||||
permissions?: PermissionEvaluator | PermissionAuthorizer;
|
||||
discovery: DiscoveryService;
|
||||
auth?: AuthService;
|
||||
httpAuth?: HttpAuthService;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
@@ -56,6 +66,8 @@ export async function createRouter(
|
||||
: undefined;
|
||||
}
|
||||
|
||||
const { httpAuth } = createLegacyAuthAdapters(options);
|
||||
|
||||
const jenkinsApi = new JenkinsApiImpl(permissionEvaluator);
|
||||
|
||||
const router = Router();
|
||||
@@ -70,9 +82,6 @@ export async function createRouter(
|
||||
'/v1/entity/:namespace/:kind/:name/projects',
|
||||
async (request, response) => {
|
||||
const { namespace, kind, name } = request.params;
|
||||
const token = getBearerTokenFromAuthorizationHeader(
|
||||
request.header('authorization'),
|
||||
);
|
||||
const branch = request.query.branch;
|
||||
let branches: string[] | undefined;
|
||||
|
||||
@@ -96,7 +105,7 @@ export async function createRouter(
|
||||
namespace,
|
||||
name,
|
||||
},
|
||||
backstageToken: token,
|
||||
credentials: await httpAuth.credentials(request),
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -123,9 +132,6 @@ export async function createRouter(
|
||||
router.get(
|
||||
'/v1/entity/:namespace/:kind/:name/job/:jobFullName/:buildNumber',
|
||||
async (request, response) => {
|
||||
const token = getBearerTokenFromAuthorizationHeader(
|
||||
request.header('authorization'),
|
||||
);
|
||||
const { namespace, kind, name, jobFullName, buildNumber } =
|
||||
request.params;
|
||||
|
||||
@@ -136,7 +142,7 @@ export async function createRouter(
|
||||
name,
|
||||
},
|
||||
jobFullName,
|
||||
backstageToken: token,
|
||||
credentials: await httpAuth.credentials(request),
|
||||
});
|
||||
|
||||
const build = await jenkinsApi.getBuild(
|
||||
@@ -154,9 +160,6 @@ export async function createRouter(
|
||||
router.get(
|
||||
'/v1/entity/:namespace/:kind/:name/job/:jobFullName',
|
||||
async (request, response) => {
|
||||
const token = getBearerTokenFromAuthorizationHeader(
|
||||
request.header('authorization'),
|
||||
);
|
||||
const { namespace, kind, name, jobFullName } = request.params;
|
||||
|
||||
const jenkinsInfo = await jenkinsInfoProvider.getInstance({
|
||||
@@ -166,7 +169,7 @@ export async function createRouter(
|
||||
name,
|
||||
},
|
||||
jobFullName,
|
||||
backstageToken: token,
|
||||
credentials: await httpAuth.credentials(request),
|
||||
});
|
||||
|
||||
const build = await jenkinsApi.getJobBuilds(jenkinsInfo, jobFullName);
|
||||
@@ -182,9 +185,6 @@ export async function createRouter(
|
||||
async (request, response) => {
|
||||
const { namespace, kind, name, jobFullName, buildNumber } =
|
||||
request.params;
|
||||
const token = getBearerTokenFromAuthorizationHeader(
|
||||
request.header('authorization'),
|
||||
);
|
||||
const jenkinsInfo = await jenkinsInfoProvider.getInstance({
|
||||
entityRef: {
|
||||
kind,
|
||||
@@ -192,7 +192,7 @@ export async function createRouter(
|
||||
name,
|
||||
},
|
||||
jobFullName,
|
||||
backstageToken: token,
|
||||
credentials: await httpAuth.credentials(request),
|
||||
});
|
||||
|
||||
const resourceRef = stringifyEntityRef({ kind, namespace, name });
|
||||
@@ -202,7 +202,7 @@ export async function createRouter(
|
||||
parseInt(buildNumber, 10),
|
||||
resourceRef,
|
||||
{
|
||||
token,
|
||||
credentials: await httpAuth.credentials(request),
|
||||
},
|
||||
);
|
||||
response.json({}).status(status);
|
||||
|
||||
@@ -14,17 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createServiceBuilder } from '@backstage/backend-common';
|
||||
import { HostDiscovery, createServiceBuilder } from '@backstage/backend-common';
|
||||
import { Server } from 'http';
|
||||
import { Logger } from 'winston';
|
||||
import { createRouter } from './router';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { JenkinsInfo } from './jenkinsInfoProvider';
|
||||
import { Config } from '@backstage/config';
|
||||
|
||||
export interface ServerOptions {
|
||||
port: number;
|
||||
enableCors: boolean;
|
||||
logger: Logger;
|
||||
config: Config;
|
||||
}
|
||||
|
||||
export async function startStandaloneServer(
|
||||
@@ -41,6 +43,7 @@ export async function startStandaloneServer(
|
||||
return { baseUrl: 'https://example.com/', jobFullName: 'build-foo' };
|
||||
},
|
||||
},
|
||||
discovery: HostDiscovery.fromConfig(options.config),
|
||||
});
|
||||
|
||||
let service = createServiceBuilder(module)
|
||||
|
||||
@@ -7054,6 +7054,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@backstage/backend-common": "workspace:^"
|
||||
"@backstage/backend-plugin-api": "workspace:^"
|
||||
"@backstage/backend-test-utils": "workspace:^"
|
||||
"@backstage/catalog-client": "workspace:^"
|
||||
"@backstage/catalog-model": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
|
||||
Reference in New Issue
Block a user