scaffolder: got rid of most backend-common usages

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2025-03-01 12:47:04 +01:00
parent 92de48f1ce
commit 09cf03890c
39 changed files with 414 additions and 110 deletions
+12
View File
@@ -0,0 +1,12 @@
---
'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
'@backstage/plugin-scaffolder-backend-module-github': patch
'@backstage/plugin-scaffolder-backend-module-rails': patch
'@backstage/plugin-scaffolder-node-test-utils': patch
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-scaffolder-common': patch
'@backstage/plugin-scaffolder-node': patch
---
Got rid of most `@backstage/backend-common` usages
@@ -45,7 +45,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createConfluenceToMarkdownAction } from './confluenceToMarkdown';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import {
createMockDirectory,
mockServices,
registerMswTestHooks,
} from '@backstage/backend-test-utils';
import { rest } from 'msw';
@@ -58,9 +57,6 @@ describe('confluence:transform:markdown examples', () => {
repoUrl: string;
}>;
const logger = loggerToWinstonLogger(mockServices.logger.mock());
jest.spyOn(logger, 'info');
const mockDir = createMockDirectory();
const workspacePath = mockDir.resolve('workspace');
@@ -75,8 +71,8 @@ describe('confluence:transform:markdown examples', () => {
mockContext = createMockActionContext({
input: yaml.parse(examples[0].example).steps[0].input,
workspacePath,
logger,
});
jest.spyOn(mockContext.logger, 'info');
mockDir.setContent({ 'workspace/mkdocs.yml': 'File contents' });
});
@@ -139,10 +135,10 @@ describe('confluence:transform:markdown examples', () => {
await action.handler(mockContext);
expect(logger.info).toHaveBeenCalledWith(
expect(mockContext.logger.info).toHaveBeenCalledWith(
`Fetching the mkdocs.yml catalog from https://github.com/organization-name/repo-name/blob/main/mkdocs.yml`,
);
expect(logger.info).toHaveBeenCalledTimes(5);
expect(mockContext.logger.info).toHaveBeenCalledTimes(5);
expect(mockDir.content({ path: 'workspace/docs' })).toEqual({
img: { 'testing.pdf': Buffer.from('hello') },
@@ -15,12 +15,10 @@
*/
import { createConfluenceToMarkdownAction } from './confluenceToMarkdown';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import {
createMockDirectory,
mockServices,
registerMswTestHooks,
} from '@backstage/backend-test-utils';
import type { ActionContext } from '@backstage/plugin-scaffolder-node';
@@ -57,9 +55,6 @@ describe('confluence:transform:markdown', () => {
repoUrl: string;
}>;
const logger = loggerToWinstonLogger(mockServices.logger.mock());
jest.spyOn(logger, 'info');
const mockDir = createMockDirectory();
const workspacePath = mockDir.resolve('workspace');
@@ -80,8 +75,8 @@ describe('confluence:transform:markdown', () => {
'https://notreal.github.com/space/backstage/blob/main/mkdocs.yml',
},
workspacePath,
logger,
});
jest.spyOn(mockContext.logger, 'info');
mockDir.setContent({ 'workspace/mkdocs.yml': 'File contents' });
});
@@ -144,10 +139,10 @@ describe('confluence:transform:markdown', () => {
await action.handler(mockContext);
expect(logger.info).toHaveBeenCalledWith(
expect(mockContext.logger.info).toHaveBeenCalledWith(
`Fetching the mkdocs.yml catalog from https://notreal.github.com/space/backstage/blob/main/mkdocs.yml`,
);
expect(logger.info).toHaveBeenCalledTimes(5);
expect(mockContext.logger.info).toHaveBeenCalledTimes(5);
expect(mockDir.content({ path: 'workspace/docs' })).toEqual({
img: { 'testing.pdf': Buffer.from('hello') },
@@ -193,10 +188,10 @@ describe('confluence:transform:markdown', () => {
await action.handler(mockContext);
expect(logger.info).toHaveBeenCalledWith(
expect(mockContext.logger.info).toHaveBeenCalledWith(
`Fetching the mkdocs.yml catalog from https://notreal.github.com/space/backstage/blob/main/mkdocs.yml`,
);
expect(logger.info).toHaveBeenCalledTimes(5);
expect(mockContext.logger.info).toHaveBeenCalledTimes(5);
expect(mockDir.content({ path: 'workspace/docs' })).toEqual({
'mkdocs.md': 'hello world',
@@ -43,7 +43,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/config": "workspace:^",
@@ -6,11 +6,37 @@
/// <reference types="node" />
import { BackendFeature } from '@backstage/backend-plugin-api';
import { ContainerRunner } from '@backstage/backend-common';
import { JsonObject } from '@backstage/types';
import { ScmIntegrations } from '@backstage/integration';
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { Writable } from 'stream';
// @public
export interface ContainerRunner {
runContainer(opts: {
imageName: string;
command?: string | string[];
args: string[];
logStream?: Writable;
mountDirs?: Record<string, string>;
workingDir?: string;
envVars?: Record<string, string>;
pullImage?: boolean;
defaultUser?: boolean;
pullOptions?: {
authconfig?: {
username?: string;
password?: string;
auth?: string;
email?: string;
serveraddress?: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
}): Promise<void>;
}
// @public
const cookiecutterModule: BackendFeature;
@@ -0,0 +1,50 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { Writable } from 'stream';
/**
* Handles the running of containers.
*
* @public
*/
export interface ContainerRunner {
/**
* Runs a container image to completion.
*/
runContainer(opts: {
imageName: string;
command?: string | string[];
args: string[];
logStream?: Writable;
mountDirs?: Record<string, string>;
workingDir?: string;
envVars?: Record<string, string>;
pullImage?: boolean;
defaultUser?: boolean;
pullOptions?: {
authconfig?: {
username?: string;
password?: string;
auth?: string;
email?: string;
serveraddress?: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
}): Promise<void>;
}
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { ContainerRunner } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { JsonObject } from '@backstage/types';
import { ScmIntegrations } from '@backstage/integration';
@@ -26,6 +25,7 @@ import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-
import { examples } from './cookiecutter.examples';
import yaml from 'yaml';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { ContainerRunner } from './ContainerRunner';
const executeShellCommand = jest.fn();
const commandExists = jest.fn();
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { ContainerRunner } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { JsonObject } from '@backstage/types';
import { ScmIntegrations } from '@backstage/integration';
@@ -25,6 +24,7 @@ import type { ActionContext } from '@backstage/plugin-scaffolder-node';
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
import { Writable } from 'stream';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { ContainerRunner } from './ContainerRunner';
const executeShellCommand = jest.fn();
const commandExists = jest.fn();
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { ContainerRunner } from '@backstage/backend-common';
import {
UrlReaderService,
resolveSafeChildPath,
@@ -32,6 +31,7 @@ import {
executeShellCommand,
} from '@backstage/plugin-scaffolder-node';
import { examples } from './cookiecutter.examples';
import { ContainerRunner } from './ContainerRunner';
export class CookiecutterRunner {
private readonly containerRunner?: ContainerRunner;
@@ -13,4 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { type ContainerRunner } from './ContainerRunner';
export { createFetchCookiecutterAction } from './cookiecutter';
@@ -42,7 +42,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/catalog-client": "workspace:^",
"@backstage/catalog-model": "workspace:^",
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { createRootLogger } from '@backstage/backend-common';
import { Config, ConfigReader } from '@backstage/config';
import {
GithubCredentialsProvider,
@@ -29,9 +28,6 @@ import { createPublishGithubPullRequestAction } from './githubPullRequest';
import { createMockDirectory } from '@backstage/backend-test-utils';
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
// Make sure root logger is initialized ahead of FS mock
createRootLogger();
type GithubPullRequestActionInput = ReturnType<
typeof createPublishGithubPullRequestAction
> extends TemplateAction<infer U>
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
jest.mock('@backstage/plugin-scaffolder-node', () => {
return {
...jest.requireActual('@backstage/plugin-scaffolder-node'),
@@ -40,28 +41,6 @@ import { createGithubRepoPushAction } from './githubRepoPush';
import { examples } from './githubRepoPush.examples';
import yaml from 'yaml';
const mockGit = {
init: jest.fn(),
add: jest.fn(),
checkout: jest.fn(),
commit: jest
.fn()
.mockResolvedValue('220f19cc36b551763d157f1b5e4a4b446165dbd6'),
fetch: jest.fn(),
addRemote: jest.fn(),
push: jest.fn(),
};
jest.mock('@backstage/backend-common', () => ({
loggerToWinstonLogger: jest.requireActual('@backstage/backend-common')
.loggerToWinstonLogger,
Git: {
fromAuth() {
return mockGit;
},
},
}));
jest.mock('./helpers', () => {
return {
...jest.requireActual('./helpers'),
@@ -14,28 +14,6 @@
* limitations under the License.
*/
const mockGit = {
init: jest.fn(),
add: jest.fn(),
checkout: jest.fn(),
commit: jest
.fn()
.mockResolvedValue('220f19cc36b551763d157f1b5e4a4b446165dbd6'),
fetch: jest.fn(),
addRemote: jest.fn(),
push: jest.fn(),
};
jest.mock('@backstage/backend-common', () => ({
loggerToWinstonLogger: jest.requireActual('@backstage/backend-common')
.loggerToWinstonLogger,
Git: {
fromAuth() {
return mockGit;
},
},
}));
jest.mock('./gitHelpers', () => {
return {
...jest.requireActual('./gitHelpers'),
@@ -43,7 +43,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
@@ -3,12 +3,40 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="node" />
import { BackendFeature } from '@backstage/backend-plugin-api';
import { ContainerRunner } from '@backstage/backend-common';
import { JsonObject } from '@backstage/types';
import { ScmIntegrations } from '@backstage/integration';
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { Writable } from 'stream';
// @public
export interface ContainerRunner {
runContainer(opts: {
imageName: string;
command?: string | string[];
args: string[];
logStream?: Writable;
mountDirs?: Record<string, string>;
workingDir?: string;
envVars?: Record<string, string>;
pullImage?: boolean;
defaultUser?: boolean;
pullOptions?: {
authconfig?: {
username?: string;
password?: string;
auth?: string;
email?: string;
serveraddress?: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
}): Promise<void>;
}
// @public
export function createFetchRailsAction(options: {
@@ -0,0 +1,50 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { Writable } from 'stream';
/**
* Handles the running of containers.
*
* @public
*/
export interface ContainerRunner {
/**
* Runs a container image to completion.
*/
runContainer(opts: {
imageName: string;
command?: string | string[];
args: string[];
logStream?: Writable;
mountDirs?: Record<string, string>;
workingDir?: string;
envVars?: Record<string, string>;
pullImage?: boolean;
defaultUser?: boolean;
pullOptions?: {
authconfig?: {
username?: string;
password?: string;
auth?: string;
email?: string;
serveraddress?: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
}): Promise<void>;
}
@@ -27,7 +27,6 @@ jest.mock('./railsNewRunner', () => {
};
});
import { ContainerRunner } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import { resolve as resolvePath } from 'path';
@@ -38,6 +37,7 @@ import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-
import { examples } from './index.examples';
import yaml from 'yaml';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { ContainerRunner } from './ContainerRunner';
describe('fetch:rails', () => {
const mockDir = createMockDirectory();
@@ -27,7 +27,6 @@ jest.mock('./railsNewRunner', () => {
};
});
import { ContainerRunner } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import { resolve as resolvePath } from 'path';
@@ -37,6 +36,7 @@ import { createMockDirectory } from '@backstage/backend-test-utils';
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
import { Writable } from 'stream';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { ContainerRunner } from './ContainerRunner';
describe('fetch:rails', () => {
const mockDir = createMockDirectory();
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { ContainerRunner } from '@backstage/backend-common';
import { JsonObject } from '@backstage/types';
import { InputError } from '@backstage/errors';
import { ScmIntegrations } from '@backstage/integration';
@@ -29,6 +28,9 @@ import { RailsNewRunner } from './railsNewRunner';
import { PassThrough } from 'stream';
import { examples } from './index.examples';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { ContainerRunner } from './ContainerRunner';
export { type ContainerRunner };
/**
* Creates the `fetch:rails` Scaffolder action.
@@ -27,11 +27,11 @@ jest.mock(
commandExists(...args),
);
import { ContainerRunner } from '@backstage/backend-common';
import path from 'path';
import { PassThrough } from 'stream';
import { RailsNewRunner } from './railsNewRunner';
import { createMockDirectory } from '@backstage/backend-test-utils';
import { ContainerRunner } from './ContainerRunner';
describe('Rails Templater', () => {
const containerRunner: jest.Mocked<ContainerRunner> = {
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { ContainerRunner } from '@backstage/backend-common';
import fs from 'fs-extra';
import path from 'path';
import { executeShellCommand } from '@backstage/plugin-scaffolder-node';
@@ -25,6 +24,7 @@ import {
} from './railsArgumentResolver';
import { JsonObject } from '@backstage/types';
import { Writable } from 'stream';
import { ContainerRunner } from './ContainerRunner';
export class RailsNewRunner {
private readonly containerRunner?: ContainerRunner;
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
coreServices,
createBackendPlugin,
@@ -52,6 +51,7 @@ import {
createWaitAction,
} from './scaffolder';
import { createRouter } from './service/router';
import { loggerToWinstonLogger } from './util/loggerToWinstonLogger';
/**
* Scaffolder plugin
@@ -38,8 +38,8 @@ import {
mockCredentials,
mockServices,
} from '@backstage/backend-test-utils';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import { LoggerService } from '@backstage/backend-plugin-api';
import { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';
describe('NunjucksWorkflowRunner', () => {
let logger: LoggerService;
@@ -38,7 +38,6 @@ import { TemplateActionRegistry } from '../actions';
import { generateExampleOutput, isTruthy } from './helper';
import { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import type {
AuditorService,
PermissionsService,
@@ -60,6 +59,7 @@ import { createDefaultFilters } from '../../lib/templating/filters';
import { scaffolderActionRules } from '../../service/rules';
import { createCounterMetric, createHistogramMetric } from '../../util/metrics';
import { BackstageLoggerTransport, WinstonLogger } from './logger';
import { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';
type NunjucksWorkflowRunnerOptions = {
workingDirectory: string;
@@ -14,10 +14,7 @@
* limitations under the License.
*/
import {
DatabaseManager,
loggerToWinstonLogger,
} from '@backstage/backend-common';
import { DatabaseManager } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
import {
@@ -27,6 +24,7 @@ import {
import { DatabaseTaskStore } from './DatabaseTaskStore';
import { StorageTaskBroker, TaskManager } from './StorageTaskBroker';
import { mockServices } from '@backstage/backend-test-utils';
import { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';
async function createStore(): Promise<DatabaseTaskStore> {
const manager = DatabaseManager.fromConfig(
@@ -15,10 +15,7 @@
*/
import os from 'os';
import {
DatabaseManager,
loggerToWinstonLogger,
} from '@backstage/backend-common';
import { DatabaseManager } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { DatabaseTaskStore } from './DatabaseTaskStore';
import { StorageTaskBroker } from './StorageTaskBroker';
@@ -35,6 +32,7 @@ import { WorkflowRunner } from './types';
import ObservableImpl from 'zen-observable';
import waitForExpect from 'wait-for-expect';
import { mockServices } from '@backstage/backend-test-utils';
import { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';
jest.mock('./NunjucksWorkflowRunner');
const MockedNunjucksWorkflowRunner =
@@ -14,10 +14,7 @@
* limitations under the License.
*/
import {
DatabaseManager,
loggerToWinstonLogger,
} from '@backstage/backend-common';
import { DatabaseManager } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
import express from 'express';
@@ -52,6 +49,7 @@ import { UrlReaders } from '@backstage/backend-defaults/urlReader';
import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils';
import { EventsService } from '@backstage/plugin-events-node';
import { DatabaseService } from '@backstage/backend-plugin-api';
import { loggerToWinstonLogger } from '../util/loggerToWinstonLogger';
const mockAccess = jest.fn();
@@ -14,10 +14,7 @@
* limitations under the License.
*/
import {
createLegacyAuthAdapters,
HostDiscovery,
} from '@backstage/backend-common';
import { createLegacyAuthAdapters } from '@backstage/backend-common';
import {
AuditorService,
AuthService,
@@ -112,6 +109,7 @@ import {
parseStringsParam,
} from './helpers';
import { scaffolderActionRules, scaffolderTemplateRules } from './rules';
import { HostDiscovery } from '@backstage/backend-defaults/discovery';
/**
*
@@ -0,0 +1,67 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { LoggerService } from '@backstage/backend-plugin-api';
import { JsonObject } from '@backstage/types';
import { Logger as WinstonLogger, createLogger } from 'winston';
import Transport, { TransportStreamOptions } from 'winston-transport';
class BackstageLoggerTransport extends Transport {
constructor(
private readonly backstageLogger: LoggerService,
opts?: TransportStreamOptions,
) {
super(opts);
}
log(info: unknown, callback: VoidFunction) {
if (typeof info !== 'object' || info === null) {
callback();
return;
}
const { level, message, ...meta } = info as JsonObject;
switch (level) {
case 'error':
this.backstageLogger.error(String(message), meta);
break;
case 'warn':
this.backstageLogger.warn(String(message), meta);
break;
case 'info':
this.backstageLogger.info(String(message), meta);
break;
case 'debug':
this.backstageLogger.debug(String(message), meta);
break;
default:
this.backstageLogger.info(String(message), meta);
}
callback();
}
}
/**
* A helper function to convert a Backstage LoggerService to a Winston Logger.
* @internal
*/
export function loggerToWinstonLogger(
logger: LoggerService,
opts?: TransportStreamOptions,
): WinstonLogger {
return createLogger({
transports: [new BackstageLoggerTransport(logger, opts)],
});
}
+1
View File
@@ -13,4 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './permissions';
@@ -40,10 +40,12 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"@backstage/types": "workspace:^"
"@backstage/types": "workspace:^",
"winston": "^3.2.1",
"winston-transport": "^4.7.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^",
@@ -0,0 +1,67 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { LoggerService } from '@backstage/backend-plugin-api';
import { JsonObject } from '@backstage/types';
import { Logger as WinstonLogger, createLogger } from 'winston';
import Transport, { TransportStreamOptions } from 'winston-transport';
class BackstageLoggerTransport extends Transport {
constructor(
private readonly backstageLogger: LoggerService,
opts?: TransportStreamOptions,
) {
super(opts);
}
log(info: unknown, callback: VoidFunction) {
if (typeof info !== 'object' || info === null) {
callback();
return;
}
const { level, message, ...meta } = info as JsonObject;
switch (level) {
case 'error':
this.backstageLogger.error(String(message), meta);
break;
case 'warn':
this.backstageLogger.warn(String(message), meta);
break;
case 'info':
this.backstageLogger.info(String(message), meta);
break;
case 'debug':
this.backstageLogger.debug(String(message), meta);
break;
default:
this.backstageLogger.info(String(message), meta);
}
callback();
}
}
/**
* A helper function to convert a Backstage LoggerService to a Winston Logger.
* @internal
*/
export function loggerToWinstonLogger(
logger: LoggerService,
opts?: TransportStreamOptions,
): WinstonLogger {
return createLogger({
transports: [new BackstageLoggerTransport(logger, opts)],
});
}
@@ -15,7 +15,6 @@
*/
import { PassThrough } from 'stream';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
createMockDirectory,
mockCredentials,
@@ -23,6 +22,7 @@ import {
} from '@backstage/backend-test-utils';
import { JsonObject, JsonValue } from '@backstage/types';
import { ActionContext } from '@backstage/plugin-scaffolder-node';
import { loggerToWinstonLogger } from './loggerToWinstonLogger';
/**
* A utility method to create a mock action context for scaffolder actions.
+1 -1
View File
@@ -54,7 +54,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "^0.25.0",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/errors": "workspace:^",
@@ -69,6 +68,7 @@
"p-limit": "^3.1.0",
"tar": "^6.1.12",
"winston": "^3.2.1",
"winston-transport": "^4.7.0",
"zod": "^3.22.4",
"zod-to-json-schema": "^3.20.4"
},
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { loggerToWinstonLogger } from '@backstage/backend-common';
import { Git } from '../scm';
import {
commitAndPushRepo,
@@ -25,6 +24,7 @@ import {
cloneRepo,
} from './gitHelpers';
import { mockServices } from '@backstage/backend-test-utils';
import { loggerToWinstonLogger } from './loggerToWinstonLogger';
jest.mock('../scm', () => ({
Git: {
@@ -0,0 +1,67 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { LoggerService } from '@backstage/backend-plugin-api';
import { JsonObject } from '@backstage/types';
import { Logger as WinstonLogger, createLogger } from 'winston';
import Transport, { TransportStreamOptions } from 'winston-transport';
class BackstageLoggerTransport extends Transport {
constructor(
private readonly backstageLogger: LoggerService,
opts?: TransportStreamOptions,
) {
super(opts);
}
log(info: unknown, callback: VoidFunction) {
if (typeof info !== 'object' || info === null) {
callback();
return;
}
const { level, message, ...meta } = info as JsonObject;
switch (level) {
case 'error':
this.backstageLogger.error(String(message), meta);
break;
case 'warn':
this.backstageLogger.warn(String(message), meta);
break;
case 'info':
this.backstageLogger.info(String(message), meta);
break;
case 'debug':
this.backstageLogger.debug(String(message), meta);
break;
default:
this.backstageLogger.info(String(message), meta);
}
callback();
}
}
/**
* A helper function to convert a Backstage LoggerService to a Winston Logger.
* @internal
*/
export function loggerToWinstonLogger(
logger: LoggerService,
opts?: TransportStreamOptions,
): WinstonLogger {
return createLogger({
transports: [new BackstageLoggerTransport(logger, opts)],
});
}
+4 -6
View File
@@ -7407,7 +7407,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:plugins/scaffolder-backend-module-confluence-to-markdown"
dependencies:
"@backstage/backend-common": ^0.25.0
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
@@ -7428,7 +7427,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-scaffolder-backend-module-cookiecutter@workspace:plugins/scaffolder-backend-module-cookiecutter"
dependencies:
"@backstage/backend-common": ^0.25.0
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
@@ -7503,7 +7501,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-scaffolder-backend-module-github@workspace:plugins/scaffolder-backend-module-github"
dependencies:
"@backstage/backend-common": ^0.25.0
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/catalog-client": "workspace:^"
@@ -7566,7 +7563,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-scaffolder-backend-module-rails@workspace:plugins/scaffolder-backend-module-rails"
dependencies:
"@backstage/backend-common": ^0.25.0
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
@@ -7705,7 +7701,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-scaffolder-node-test-utils@workspace:plugins/scaffolder-node-test-utils"
dependencies:
"@backstage/backend-common": ^0.25.0
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/plugin-scaffolder-node": "workspace:^"
@@ -7714,6 +7710,8 @@ __metadata:
react: ^18.0.2
react-dom: ^18.0.2
react-router-dom: ^6.3.0
winston: ^3.2.1
winston-transport: ^4.7.0
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0
react: ^17.0.0 || ^18.0.0
@@ -7729,7 +7727,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-scaffolder-node@workspace:plugins/scaffolder-node"
dependencies:
"@backstage/backend-common": ^0.25.0
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/catalog-model": "workspace:^"
@@ -7747,6 +7744,7 @@ __metadata:
p-limit: ^3.1.0
tar: ^6.1.12
winston: ^3.2.1
winston-transport: ^4.7.0
zod: ^3.22.4
zod-to-json-schema: ^3.20.4
languageName: unknown