From 97b972978fc2050050dc663757e4ef240f8c9b41 Mon Sep 17 00:00:00 2001 From: Stefan Petrovic Date: Fri, 4 Aug 2023 09:12:31 +0200 Subject: [PATCH 1/4] added fs delete and rename examples Signed-off-by: Stefan Petrovic --- .../filesystem/delete.examples.test.ts | 15 +++++++ .../builtin/filesystem/delete.examples.ts | 36 +++++++++++++++++ .../actions/builtin/filesystem/delete.ts | 2 + .../filesystem/rename.examples.test.ts | 15 +++++++ .../builtin/filesystem/rename.examples.ts | 39 +++++++++++++++++++ .../actions/builtin/filesystem/rename.ts | 2 + 6 files changed, 109 insertions(+) create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts 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..7f0d9bd499 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ 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..7f0d9bd499 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ 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..bceee899fc --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts @@ -0,0 +1,39 @@ +/* + * 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: 'file.txt', to: 'fileRenamed.txt', overwrite: true }, + { from: 'file1.txt', to: 'file1Renamed.txt' }, + ], + }, + }, + ], + }), + }, +]; 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'], From 1777c5f52b3c3539d5be436443d74ae63d03df53 Mon Sep 17 00:00:00 2001 From: Stefan Petrovic Date: Fri, 4 Aug 2023 21:10:37 +0200 Subject: [PATCH 2/4] added test classes for delete and rename examples Signed-off-by: Stefan Petrovic --- .../filesystem/delete.examples.test.ts | 64 +++++++++++++ .../filesystem/rename.examples.test.ts | 95 +++++++++++++++++++ .../builtin/filesystem/rename.examples.ts | 3 +- 3 files changed, 161 insertions(+), 1 deletion(-) 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 index 7f0d9bd499..10994e3824 100644 --- 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 @@ -13,3 +13,67 @@ * 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/rename.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts index 7f0d9bd499..d28403fe80 100644 --- 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 @@ -13,3 +13,98 @@ * 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: [ + { + from: sourceFile, + to: destFile, + overwrite: true, + }, + ], + }, + }); + + 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 index bceee899fc..59d7483a10 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.ts @@ -28,8 +28,9 @@ export const examples: TemplateExample[] = [ name: 'Rename files', input: { files: [ - { from: 'file.txt', to: 'fileRenamed.txt', overwrite: true }, { from: 'file1.txt', to: 'file1Renamed.txt' }, + { from: 'file2.txt', to: 'file2Renamed.txt' }, + { from: 'file3.txt', to: 'file3Renamed.txt', overwrite: true }, ], }, }, From 33c76caef72a7d72b3cd838b8bdf1b4d72e5fd46 Mon Sep 17 00:00:00 2001 From: Stefan Petrovic Date: Fri, 4 Aug 2023 22:06:19 +0200 Subject: [PATCH 3/4] added changeset Signed-off-by: Stefan Petrovic --- .changeset/funny-dancers-deliver.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/funny-dancers-deliver.md 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 From a93cb09398780c05205bc14aaa7377e7b54d56fa Mon Sep 17 00:00:00 2001 From: Stefan Petrovic Date: Fri, 4 Aug 2023 22:35:20 +0200 Subject: [PATCH 4/4] minor fs:rename example test change Signed-off-by: Stefan Petrovic --- .../actions/builtin/filesystem/rename.examples.test.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) 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 index d28403fe80..c4c27cc68e 100644 --- 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 @@ -93,13 +93,7 @@ describe('fs:rename examples', () => { await action.handler({ ...mockContext, input: { - files: [ - { - from: sourceFile, - to: destFile, - overwrite: true, - }, - ], + files, }, });