diff --git a/.changeset/clean-suits-hear.md b/.changeset/clean-suits-hear.md index 9c167ff15e..911a46a55a 100644 --- a/.changeset/clean-suits-hear.md +++ b/.changeset/clean-suits-hear.md @@ -2,4 +2,5 @@ '@backstage/plugin-scaffolder-backend': patch --- -Added a type parameter to `TaskStoreEmitOptions` to type the `body` property +- **DEPRECATED** - Deprecated the `runCommand` export in favour of `executeShellCommand`. Please migrate to using the new method. +- Added a type parameter to `TaskStoreEmitOptions` to type the `body` property diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts index 2c1ecd06f9..18a6722663 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const runCommand = jest.fn(); +const executeShellCommand = jest.fn(); const commandExists = jest.fn(); const fetchContents = jest.fn(); jest.mock('@backstage/plugin-scaffolder-backend', () => ({ ...jest.requireActual('@backstage/plugin-scaffolder-backend'), fetchContents, - runCommand, + executeShellCommand, })); jest.mock('command-exists', () => commandExists); @@ -115,8 +115,8 @@ describe('fetch:cookiecutter', () => { }); }); - // Mock when runCommand is called it creats some new files in the mock filesystem - runCommand.mockImplementation(async () => { + // Mock when executeShellCommand is called it creats some new files in the mock filesystem + executeShellCommand.mockImplementation(async () => { mockFs({ [`${join(mockTmpDir, 'intermediate')}`]: { 'testfile.json': '{}', @@ -163,12 +163,12 @@ describe('fetch:cookiecutter', () => { ); }); - it('should call out to cookiecutter using runCommand when cookiecutter is installed', async () => { + it('should call out to cookiecutter using executeShellCommand when cookiecutter is installed', async () => { commandExists.mockResolvedValue(true); await action.handler(mockContext); - expect(runCommand).toHaveBeenCalledWith( + expect(executeShellCommand).toHaveBeenCalledWith( expect.objectContaining({ command: 'cookiecutter', args: [ diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts index 0455f01989..6b0cb4695d 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts @@ -27,9 +27,9 @@ import fs from 'fs-extra'; import path, { resolve as resolvePath } from 'path'; import { Writable } from 'stream'; import { - runCommand, createTemplateAction, fetchContents, + executeShellCommand, } from '@backstage/plugin-scaffolder-backend'; export class CookiecutterRunner { @@ -89,7 +89,7 @@ export class CookiecutterRunner { () => false, ); if (cookieCutterInstalled) { - await runCommand({ + await executeShellCommand({ command: 'cookiecutter', args: ['--no-input', '-o', intermediateDir, templateDir, '--verbose'], logStream, diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts index 03d894f832..0767e63f29 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts @@ -14,10 +14,12 @@ * limitations under the License. */ -const runCommand = jest.fn(); +const executeShellCommand = jest.fn(); const commandExists = jest.fn(); -jest.mock('@backstage/plugin-scaffolder-backend', () => ({ runCommand })); +jest.mock('@backstage/plugin-scaffolder-backend', () => ({ + executeShellCommand, +})); jest.mock('command-exists', () => commandExists); jest.mock('fs-extra'); @@ -195,7 +197,7 @@ describe('Rails Templater', () => { logStream: stream, }); - expect(runCommand).toHaveBeenCalledWith({ + expect(executeShellCommand).toHaveBeenCalledWith({ command: 'rails', args: expect.arrayContaining([ 'new', @@ -225,7 +227,7 @@ describe('Rails Templater', () => { logStream: stream, }); - expect(runCommand).toHaveBeenCalledWith({ + expect(executeShellCommand).toHaveBeenCalledWith({ command: 'rails', args: expect.arrayContaining([ 'new', diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts index f7817c7fb5..4a4672795a 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts @@ -17,7 +17,7 @@ import { ContainerRunner } from '@backstage/backend-common'; import fs from 'fs-extra'; import path from 'path'; -import { runCommand } from '@backstage/plugin-scaffolder-backend'; +import { executeShellCommand } from '@backstage/plugin-scaffolder-backend'; import commandExists from 'command-exists'; import { railsArgumentResolver, @@ -64,7 +64,7 @@ export class RailsNewRunner { railsArguments as RailsRunOptions, ); - await runCommand({ + await executeShellCommand({ command: baseCommand, args: [ ...baseArguments, diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index b4a094285a..bbbcf680c7 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -354,14 +354,13 @@ export class DatabaseTaskStore implements TaskStore { options: TaskStoreCreateTaskOptions, ): Promise; // (undocumented) - emitLogEvent({ - taskId, - body, - }: TaskStoreEmitOptions< - { - message: string; - } & JsonObject - >): Promise; + emitLogEvent( + options: TaskStoreEmitOptions< + { + message: string; + } & JsonObject + >, + ): Promise; // (undocumented) getTask(taskId: string): Promise; // (undocumented) @@ -381,6 +380,11 @@ export class DatabaseTaskStore implements TaskStore { // @public @deprecated export type DispatchResult = TaskBrokerDispatchResult; +// Warning: (ae-forgotten-export) The symbol "RunCommandOptions" needs to be exported by the entry point index.d.ts +// +// @public +export const executeShellCommand: (options: RunCommandOptions) => Promise; + // @public export function fetchContents({ reader, @@ -437,16 +441,8 @@ export interface RouterOptions { taskWorkers?: number; } -// Warning: (ae-forgotten-export) The symbol "RunCommandOptions" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "runCommand" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export const runCommand: ({ - command, - args, - logStream, - options, -}: RunCommandOptions) => Promise; +// @public @deprecated +export const runCommand: (options: RunCommandOptions) => Promise; // @public (undocumented) export class ScaffolderEntitiesProcessor implements CatalogProcessor { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index 9303b5e487..7ee334a3f7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -34,15 +34,18 @@ export type RunCommandOptions = { /** * Run a command in a sub-process, normally a shell command. + * + * @public */ -export const runCommand = async ({ - command, - args, - logStream = new PassThrough(), - options, -}: RunCommandOptions) => { +export const executeShellCommand = async (options: RunCommandOptions) => { + const { + command, + args, + options: spawnOptions, + logStream = new PassThrough(), + } = options; await new Promise((resolve, reject) => { - const process = spawn(command, args, options); + const process = spawn(command, args, spawnOptions); process.stdout.on('data', stream => { logStream.write(stream); @@ -67,6 +70,13 @@ export const runCommand = async ({ }); }; +/** + * Run a command in a sub-process, normally a shell command. + * @public + * @deprecated use {@link executeShellCommand} instead + */ +export const runCommand = executeShellCommand; + export async function initRepoAndPush({ dir, remoteUrl, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts index 5f4c04cc7d..8930c23126 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts @@ -25,4 +25,4 @@ export * from './github'; /** @deprecated please add this package to your own installation manually */ export { createFetchCookiecutterAction } from '@backstage/plugin-scaffolder-backend-module-cookiecutter'; -export { runCommand } from './helpers'; +export { runCommand, executeShellCommand } from './helpers'; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index b81cbc9dcc..65b890c265 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -252,15 +252,15 @@ export class DatabaseTaskStore implements TaskStore { }); } - async emitLogEvent({ - taskId, - body, - }: TaskStoreEmitOptions<{ message: string } & JsonObject>): Promise { - const serializedBo = JSON.stringify(body); + async emitLogEvent( + options: TaskStoreEmitOptions<{ message: string } & JsonObject>, + ): Promise { + const { taskId, body } = options; + const serializedBody = JSON.stringify(body); await this.db('task_events').insert({ task_id: taskId, event_type: 'log', - body: serializedBo, + body: serializedBody, }); }