diff --git a/.changeset/beige-papayas-relax.md b/.changeset/beige-papayas-relax.md new file mode 100644 index 0000000000..9fb6fc1c12 --- /dev/null +++ b/.changeset/beige-papayas-relax.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +created an action to write a catalog-info file diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 69c54343e3..792913749b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -124,6 +124,9 @@ export function createCatalogRegisterAction(options: { integrations: ScmIntegrations; }): TemplateAction; +// @public (undocumented) +export function createCatalogWriteAction(): TemplateAction; + // @public export function createDebugLogAction(): TemplateAction; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/index.ts index 45d0a18787..1cd683dcf5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/index.ts @@ -15,3 +15,4 @@ */ export { createCatalogRegisterAction } from './register'; +export { createCatalogWriteAction } from './write'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts new file mode 100644 index 0000000000..0af6822ccf --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 fs from 'fs-extra'; + +jest.mock('fs-extra'); + +const fsMock = fs as jest.Mocked; + +import { PassThrough } from 'stream'; +import os from 'os'; +import { getVoidLogger } from '@backstage/backend-common'; +import { ORIGIN_LOCATION_ANNOTATION } from '@backstage/catalog-model'; +import { createCatalogWriteAction } from './write'; +import { resolve as resolvePath } from 'path'; +import * as yaml from 'yaml'; + +describe('catalog:write', () => { + const action = createCatalogWriteAction(); + + const mockContext = { + workspacePath: os.tmpdir(), + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('should write the catalog-info.yml in the workspace', async () => { + const entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'n', + namespace: 'ns', + annotations: { + [ORIGIN_LOCATION_ANNOTATION]: 'url:https://example.com', + }, + }, + spec: {}, + }; + + await action.handler({ + ...mockContext, + input: { + entity, + }, + }); + + expect(fsMock.writeFile).toHaveBeenCalledTimes(1); + expect(fsMock.writeFile).toHaveBeenCalledWith( + resolvePath(mockContext.workspacePath, 'catalog-info.yaml'), + yaml.stringify(entity), + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.ts new file mode 100644 index 0000000000..d7f302031e --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2021 Spotify AB + * + * 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 fs from 'fs-extra'; +import { createTemplateAction } from '../../createTemplateAction'; +import * as yaml from 'yaml'; +import { Entity } from '@backstage/catalog-model'; + +export function createCatalogWriteAction() { + return createTemplateAction<{ name?: string; entity: Entity }>({ + id: 'catalog:write', + description: 'Writes the catalog-info.yaml for your template', + schema: { + input: { + type: 'object', + properties: { + entity: { + title: 'Entity info to write catalog-info.yaml', + description: + 'You can provide the same values used in the Entity schema.', + type: 'object', + }, + }, + }, + }, + async handler(ctx) { + ctx.logStream.write(`Writing catalog-info.yaml`); + const { entity } = ctx.input; + + await fs.writeFile( + `${ctx.workspacePath}/catalog-info.yaml`, + yaml.stringify(entity), + ); + }, + }); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 3ca627475a..598d36938e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -18,7 +18,10 @@ import { UrlReader } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { ScmIntegrations } from '@backstage/integration'; import { TemplaterBuilder } from '../../stages'; -import { createCatalogRegisterAction } from './catalog'; +import { + createCatalogRegisterAction, + createCatalogWriteAction, +} from './catalog'; import { createDebugLogAction } from './debug'; import { createFetchCookiecutterAction, createFetchPlainAction } from './fetch'; import { @@ -64,5 +67,6 @@ export const createBuiltinActions = (options: { }), createDebugLogAction(), createCatalogRegisterAction({ catalogClient, integrations }), + createCatalogWriteAction(), ]; }; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index ed58e8a739..d6067280c3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -48,6 +48,11 @@ export class TaskWorker { return JSON.stringify(parseRepoUrl(repoUrl)); }); + this.handlebars.registerHelper('projectSlug', repoUrl => { + const { owner, repo } = parseRepoUrl(repoUrl); + return `${owner}/${repo}`; + }); + this.handlebars.registerHelper('json', obj => JSON.stringify(obj)); this.handlebars.registerHelper('not', value => !isTruthy(value));