From 0a9b3b14e904a0a1df746c36b3bb1a4499960c47 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Fri, 28 Jul 2023 15:35:25 -0500 Subject: [PATCH 1/3] Added example for confluece to markdown action Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/chilly-chicken-fix.md | 5 +++ .../confluenceToMarkdown.examples.ts | 43 +++++++++++++++++++ .../confluence/confluenceToMarkdown.ts | 3 ++ 3 files changed, 51 insertions(+) create mode 100644 .changeset/chilly-chicken-fix.md create mode 100644 plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts diff --git a/.changeset/chilly-chicken-fix.md b/.changeset/chilly-chicken-fix.md new file mode 100644 index 0000000000..451789a56f --- /dev/null +++ b/.changeset/chilly-chicken-fix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch +--- + +Added example for the `confluence:transform:markdown` that will show in the installed actions list diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts new file mode 100644 index 0000000000..29249d2dc3 --- /dev/null +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts @@ -0,0 +1,43 @@ +/* + * Copyright 2023 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 yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: + 'Downloads content from provided Confluence URLs and converts it to Markdown.', + example: yaml.stringify({ + steps: [ + { + action: 'confluence:transform:markdown', + id: 'confluence-transform-markdown', + name: 'Transform Confluence content to Markdown', + input: { + confluenceUrls: [ + 'https://confluence.example.com/display/SPACEKEY/Page+Title', + 'https://confluence.example.com/prefix/display/PREFIXSPACEKEY/Prefix+Page+Title', + 'https://example.atlassian.net/wiki/spaces/CLOUDSPACEKEY/pages/1234567/Cloud+Page+Title', + ], + repoUrl: + 'https://github.com/organization-name/repo-name/blob/main/mkdocs.yml', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.ts index 71a3af11ae..e88f42e39c 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.ts +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.ts @@ -33,6 +33,7 @@ import { createConfluenceVariables, getConfluenceConfig, } from './helpers'; +import { examples } from './confluenceToMarkdown.examples'; /** * @public @@ -53,6 +54,8 @@ export const createConfluenceToMarkdownAction = (options: { repoUrl: string; }>({ id: 'confluence:transform:markdown', + description: 'Transforms Confluence content to Markdown', + examples, schema: { input: { properties: { From 5cfde96dd7ee46cb64d1748dae62e849a0261db2 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:58:26 -0500 Subject: [PATCH 2/3] Added test for example Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../confluenceToMarkdown.examples.test.ts | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts new file mode 100644 index 0000000000..1a3e249fb0 --- /dev/null +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts @@ -0,0 +1,176 @@ +/* + * 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. + */ + +/* + * Copyright 2023 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 { PassThrough } from 'stream'; +import { createConfluenceToMarkdownAction } from './confluenceToMarkdown'; +import { getVoidLogger } from '@backstage/backend-common'; +import { UrlReader } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import mockFs from 'mock-fs'; +import os from 'os'; +import { readFile, writeFile, createWriteStream } from 'fs-extra'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { examples } from './confluenceToMarkdown.examples'; +import yaml from 'yaml'; + +jest.mock('fs-extra', () => ({ + mkdirSync: jest.fn(), + readFile: jest.fn().mockResolvedValue('File contents'), + writeFile: jest.fn().mockImplementation(() => { + return Promise.resolve(); + }), + outputFile: jest.fn(), + openSync: jest.fn(), + createWriteStream: jest.fn().mockReturnValue(new PassThrough()), + ensureDir: jest.fn(), +})); + +describe('confluence:transform:markdown examples', () => { + const baseUrl = `https://nodomain.confluence.com`; + const worker = setupServer(); + setupRequestMockHandlers(worker); + + const config = new ConfigReader({ + confluence: { + baseUrl: baseUrl, + auth: { + token: 'fake_token', + }, + }, + }); + + const integrations = ScmIntegrations.fromConfig( + new ConfigReader({ + integrations: { + github: [{ host: 'github.com', token: 'token' }], + }, + }), + ); + + const logger = getVoidLogger(); + jest.spyOn(logger, 'info'); + + const mockTmpDir = os.tmpdir(); + + const mockContext = { + workspacePath: '/tmp', + logger, + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + }; + + const reader: UrlReader = { + readUrl: jest.fn(), + readTree: jest.fn().mockResolvedValue({ + dir: jest.fn(), + }), + search: jest.fn(), + }; + mockFs({ [`${mockTmpDir}/src/docs`]: {} }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + afterEach(() => { + jest.clearAllMocks(); + mockFs.restore(); + }); + + it('should call confluence to markdown action successfully with results array', async () => { + const options = { + reader, + integrations, + config, + }; + const responseBody = { + results: [ + { + id: '4444444', + type: 'page', + title: 'Testing', + body: { + export_view: { + value: '
hello world
', + }, + }, + }, + ], + }; + const responseBodyTwo = { + results: [ + { + id: '4444444', + type: 'attachment', + title: 'testing.pdf', + metadata: { + mediaType: 'application/pdf', + }, + _links: { + download: '/download/attachments/4444444/testing.pdf', + }, + }, + ], + }; + + worker.use( + rest.get(`${baseUrl}/rest/api/content`, (_, res, ctx) => + res(ctx.status(200, 'OK'), ctx.json(responseBody)), + ), + rest.get( + `${baseUrl}/rest/api/content/4444444/child/attachment`, + (_, res, ctx) => res(ctx.status(200, 'OK'), ctx.json(responseBodyTwo)), + ), + rest.get( + `${baseUrl}/download/attachments/4444444/testing.pdf`, + (_, res, ctx) => res(ctx.status(200, 'OK'), ctx.body('hello')), + ), + ); + + const action = createConfluenceToMarkdownAction(options); + + await action.handler({ + ...mockContext, + input: yaml.parse(examples[0].example).steps[0].input, + }); + + expect(logger.info).toHaveBeenCalledWith( + `Fetching the mkdocs.yml catalog from https://notreal.github.com/space/backstage/mkdocs.yml`, + ); + expect(logger.info).toHaveBeenCalledTimes(5); + expect(createWriteStream).toHaveBeenCalledTimes(1); + expect(readFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledTimes(1); + }); +}); From 27e7db7709b5df68635152e57c8ea7bfbe8aafe0 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:51:25 -0500 Subject: [PATCH 3/3] Fixed failing test Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../confluenceToMarkdown.examples.test.ts | 66 ++++++++----------- .../confluenceToMarkdown.examples.ts | 2 - 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts index 1a3e249fb0..e5aeadbf00 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.test.ts @@ -1,19 +1,3 @@ -/* - * 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. - */ - /* * Copyright 2023 The Backstage Authors * @@ -43,6 +27,7 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { examples } from './confluenceToMarkdown.examples'; import yaml from 'yaml'; +import { ActionContext } from '@backstage/plugin-scaffolder-node'; jest.mock('fs-extra', () => ({ mkdirSync: jest.fn(), @@ -57,7 +42,7 @@ jest.mock('fs-extra', () => ({ })); describe('confluence:transform:markdown examples', () => { - const baseUrl = `https://nodomain.confluence.com`; + const baseUrl = `https://confluence.example.com`; const worker = setupServer(); setupRequestMockHandlers(worker); @@ -78,30 +63,34 @@ describe('confluence:transform:markdown examples', () => { }), ); + let reader: UrlReader; + let mockContext: ActionContext<{ + confluenceUrls: string[]; + repoUrl: string; + }>; + const logger = getVoidLogger(); jest.spyOn(logger, 'info'); const mockTmpDir = os.tmpdir(); - const mockContext = { - workspacePath: '/tmp', - logger, - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), - }; - - const reader: UrlReader = { - readUrl: jest.fn(), - readTree: jest.fn().mockResolvedValue({ - dir: jest.fn(), - }), - search: jest.fn(), - }; - mockFs({ [`${mockTmpDir}/src/docs`]: {} }); - beforeEach(() => { - jest.resetAllMocks(); + reader = { + readUrl: jest.fn(), + readTree: jest.fn().mockResolvedValue({ + dir: jest.fn(), + }), + search: jest.fn(), + }; + mockContext = { + input: yaml.parse(examples[0].example).steps[0].input, + workspacePath: '/tmp', + logger, + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + }; + mockFs({ [`${mockTmpDir}/src/docs`]: {} }); }); afterEach(() => { jest.clearAllMocks(); @@ -160,13 +149,10 @@ describe('confluence:transform:markdown examples', () => { const action = createConfluenceToMarkdownAction(options); - await action.handler({ - ...mockContext, - input: yaml.parse(examples[0].example).steps[0].input, - }); + await action.handler(mockContext); expect(logger.info).toHaveBeenCalledWith( - `Fetching the mkdocs.yml catalog from https://notreal.github.com/space/backstage/mkdocs.yml`, + `Fetching the mkdocs.yml catalog from https://github.com/organization-name/repo-name/blob/main/mkdocs.yml`, ); expect(logger.info).toHaveBeenCalledTimes(5); expect(createWriteStream).toHaveBeenCalledTimes(1); diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts index 29249d2dc3..e5d10644a6 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/src/actions/confluence/confluenceToMarkdown.examples.ts @@ -30,8 +30,6 @@ export const examples: TemplateExample[] = [ input: { confluenceUrls: [ 'https://confluence.example.com/display/SPACEKEY/Page+Title', - 'https://confluence.example.com/prefix/display/PREFIXSPACEKEY/Prefix+Page+Title', - 'https://example.atlassian.net/wiki/spaces/CLOUDSPACEKEY/pages/1234567/Cloud+Page+Title', ], repoUrl: 'https://github.com/organization-name/repo-name/blob/main/mkdocs.yml',