diff --git a/.changeset/funny-dancers-deliver.md b/.changeset/funny-dancers-deliver.md new file mode 100644 index 0000000000..8d0b1f823d --- /dev/null +++ b/.changeset/funny-dancers-deliver.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Added examples for the fs:delete and fs:rename actions diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts new file mode 100644 index 0000000000..10994e3824 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright 2021 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 { createFilesystemDeleteAction } from './delete'; +import { getVoidLogger } from '@backstage/backend-common'; +import { PassThrough } from 'stream'; +import { resolve as resolvePath } from 'path'; +import * as os from 'os'; +import mockFs from 'mock-fs'; +import fs from 'fs-extra'; +import yaml from 'yaml'; +import { examples } from './delete.examples'; + +const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; +const workspacePath = resolvePath(root, 'my-workspace'); + +describe('fs:delete examples', () => { + const action = createFilesystemDeleteAction(); + + const files: string[] = yaml.parse(examples[0].example).steps[0].input.files; + + const mockContext = { + input: { + files: files, + }, + workspacePath, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.restoreAllMocks(); + + mockFs({ + [workspacePath]: { + [files[0]]: 'hello', + [files[1]]: 'world', + 'a-folder': { + 'unit-test-in-a-folder.js2': 'content', + }, + }, + }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should call fs.rm with the correct values', async () => { + files.forEach(file => { + const filePath = resolvePath(workspacePath, file); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(true); + }); + + await action.handler(mockContext); + + files.forEach(file => { + const filePath = resolvePath(workspacePath, file); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(false); + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.ts new file mode 100644 index 0000000000..8aea076b9d --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2021 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import * as yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Delete specified files', + example: yaml.stringify({ + steps: [ + { + action: 'fs:delete', + id: 'deleteFiles', + name: 'Delete files', + input: { + files: ['file1.txt', 'file2.txt'], + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts index 2f955c16ff..5787d245ab 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts @@ -18,6 +18,7 @@ import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { InputError } from '@backstage/errors'; import { resolveSafeChildPath } from '@backstage/backend-common'; import fs from 'fs-extra'; +import { examples } from './delete.examples'; /** * Creates new action that enables deletion of files and directories in the workspace. @@ -27,6 +28,7 @@ export const createFilesystemDeleteAction = () => { return createTemplateAction<{ files: string[] }>({ id: 'fs:delete', description: 'Deletes files and directories from the workspace', + examples, schema: { input: { required: ['files'], diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts new file mode 100644 index 0000000000..c4c27cc68e --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2021 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 * as os from 'os'; +import mockFs from 'mock-fs'; +import { resolve as resolvePath } from 'path'; +import { createFilesystemRenameAction } from './rename'; +import { getVoidLogger } from '@backstage/backend-common'; +import { PassThrough } from 'stream'; +import fs from 'fs-extra'; +import yaml from 'yaml'; +import { examples } from './rename.examples'; + +const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; +const workspacePath = resolvePath(root, 'my-workspace'); + +describe('fs:rename examples', () => { + const action = createFilesystemRenameAction(); + const files: { from: string; to: string }[] = yaml.parse(examples[0].example) + .steps[0].input.files; + + const mockContext = { + input: { + files: files, + }, + workspacePath, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.restoreAllMocks(); + + mockFs({ + [workspacePath]: { + [files[0].from]: 'hello', + [files[1].from]: 'world', + [files[2].from]: '!!!', + 'file3Renamed.txt': 'I will be overwritten :(', + 'a-folder': { + 'file.md': 'content', + }, + }, + }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should call fs.move with the correct values', async () => { + mockContext.input.files.forEach(file => { + const filePath = resolvePath(workspacePath, file.from); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(true); + }); + + await action.handler(mockContext); + + mockContext.input.files.forEach(file => { + const filePath = resolvePath(workspacePath, file.from); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(false); + }); + }); + + it('should override when requested', async () => { + const sourceFile = files[2].from; + const destFile = files[2].to; + const sourceFilePath = resolvePath(workspacePath, sourceFile); + const destFilePath = resolvePath(workspacePath, destFile); + + const sourceBeforeContent = fs.readFileSync(sourceFilePath, 'utf-8'); + const destBeforeContent = fs.readFileSync(destFilePath, 'utf-8'); + + expect(sourceBeforeContent).not.toEqual(destBeforeContent); + + await action.handler({ + ...mockContext, + input: { + files, + }, + }); + + const destAfterContent = fs.readFileSync(destFilePath, 'utf-8'); + + expect(sourceBeforeContent).toEqual(destAfterContent); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts new file mode 100644 index 0000000000..59d7483a10 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2021 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import * as yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Rename specified files ', + example: yaml.stringify({ + steps: [ + { + action: 'fs:rename', + id: 'renameFiles', + name: 'Rename files', + input: { + files: [ + { from: 'file1.txt', to: 'file1Renamed.txt' }, + { from: 'file2.txt', to: 'file2Renamed.txt' }, + { from: 'file3.txt', to: 'file3Renamed.txt', overwrite: true }, + ], + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts index c29ba221c4..5d9d666d15 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts @@ -18,6 +18,7 @@ import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { resolveSafeChildPath } from '@backstage/backend-common'; import { InputError } from '@backstage/errors'; import fs from 'fs-extra'; +import { examples } from './rename.examples'; /** * Creates a new action that allows renames of files and directories in the workspace. @@ -33,6 +34,7 @@ export const createFilesystemRenameAction = () => { }>({ id: 'fs:rename', description: 'Renames files and directories within the workspace', + examples, schema: { input: { required: ['files'],