From 75848013f1a4bd57be5cc15042f46be03fba81ba Mon Sep 17 00:00:00 2001 From: Phillip Morton Date: Fri, 2 May 2025 21:09:23 +0100 Subject: [PATCH] Dotnet scaffolder (#3807) * chore: bootstrap workspace Signed-off-by: Phillip Morton * feat: add dotnet new to azure devops workspace. Signed-off-by: Phillip Morton * feat: add changeset, and tests Signed-off-by: Phillip Morton * chore: add docs Signed-off-by: Phillip Morton * chore: dedupe yarn file Signed-off-by: Phillip Morton * chore: delete file for rename Signed-off-by: Phillip Morton * fix: re-add dotnetnew action Signed-off-by: Phillip Morton * run prettier Signed-off-by: Phillip Morton * fix: add API report file. Signed-off-by: Phillip Morton * fix: correct api reports. Signed-off-by: Phillip Morton * fix: rename scaffolder.yaml to dotnetNew.yaml Signed-off-by: Phillip Morton --------- Signed-off-by: Phillip Morton --- .../.changeset/hot-ravens-tell.md | 5 + workspaces/azure-devops/app-config.yaml | 7 +- .../examples/scaffolder/dotnetNew.yaml | 40 +++++ .../runAzurePipeline.yaml} | 1 + workspaces/azure-devops/package.json | 2 +- .../packages/backend/package.json | 2 + .../packages/backend/src/index.ts | 5 + .../.eslintrc.js | 1 + .../README.md | 72 +++++++++ .../package.json | 56 +++++++ .../report.api.md | 11 ++ .../src/actions/dotnetNew.examples.ts | 85 ++++++++++ .../src/actions/dotnetNew.test.ts | 150 ++++++++++++++++++ .../src/actions/dotnetNew.ts | 78 +++++++++ .../src/index.ts | 23 +++ .../src/module.ts | 37 +++++ workspaces/azure-devops/yarn.lock | 63 +++++++- 17 files changed, 628 insertions(+), 10 deletions(-) create mode 100644 workspaces/azure-devops/.changeset/hot-ravens-tell.md create mode 100644 workspaces/azure-devops/examples/scaffolder/dotnetNew.yaml rename workspaces/azure-devops/examples/{scaffolder.yaml => scaffolder/runAzurePipeline.yaml} (98%) create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/.eslintrc.js create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/README.md create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/package.json create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/report.api.md create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.examples.ts create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.test.ts create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.ts create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/index.ts create mode 100644 workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/module.ts diff --git a/workspaces/azure-devops/.changeset/hot-ravens-tell.md b/workspaces/azure-devops/.changeset/hot-ravens-tell.md new file mode 100644 index 000000000..ba33555d9 --- /dev/null +++ b/workspaces/azure-devops/.changeset/hot-ravens-tell.md @@ -0,0 +1,5 @@ +--- +'@backstage-community/plugin-scaffolder-backend-module-dotnet': minor +--- + +Introduce the `dotnet:new` scaffolder action diff --git a/workspaces/azure-devops/app-config.yaml b/workspaces/azure-devops/app-config.yaml index 087953a03..d33c83999 100644 --- a/workspaces/azure-devops/app-config.yaml +++ b/workspaces/azure-devops/app-config.yaml @@ -55,6 +55,11 @@ catalog: # Local example scaffolder action - type: file - target: ../../examples/scaffolder.yaml + target: ../../examples/scaffolder/dotnetNew.yaml + rules: + - allow: [Template] + # Local example scaffolder action + - type: file + target: ../../examples/scaffolder/runAzurePipeline.yaml rules: - allow: [Template] diff --git a/workspaces/azure-devops/examples/scaffolder/dotnetNew.yaml b/workspaces/azure-devops/examples/scaffolder/dotnetNew.yaml new file mode 100644 index 000000000..8695f0d46 --- /dev/null +++ b/workspaces/azure-devops/examples/scaffolder/dotnetNew.yaml @@ -0,0 +1,40 @@ +apiVersion: scaffolder.backstage.io/v1beta3 +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template +kind: Template +metadata: + name: dotnet-new-example + title: Create New Project Example +spec: + type: service + parameters: + - title: Choose your project + required: + - project + - component_id + properties: + component_id: + title: Name + type: string + description: Unique name of your service. The name must contain only Alphabet characters (e.g MyPlugin) + maxLength: 20 + pattern: '^[A-Za-z]+$' + project: + title: Project + type: string + description: Choose what dotnet project to create + default: None + enum: + - webapi + - aspire + - webapp + # These steps are executed in the scaffolder backend, using data that we gathered + # via the parameters above. + steps: + - id: runAzurePipeline + name: Create New Project + action: dotnet:new + input: + template: ${{parameters.project}} + args: + - -n + - ${{parameters.component_id | replace("-", "_")}} diff --git a/workspaces/azure-devops/examples/scaffolder.yaml b/workspaces/azure-devops/examples/scaffolder/runAzurePipeline.yaml similarity index 98% rename from workspaces/azure-devops/examples/scaffolder.yaml rename to workspaces/azure-devops/examples/scaffolder/runAzurePipeline.yaml index 8736c3578..0b1e46aa7 100644 --- a/workspaces/azure-devops/examples/scaffolder.yaml +++ b/workspaces/azure-devops/examples/scaffolder/runAzurePipeline.yaml @@ -5,6 +5,7 @@ metadata: name: run-pipeline-example title: Run Azure Pipeline Example spec: + type: service parameters: - title: Choose a location required: diff --git a/workspaces/azure-devops/package.json b/workspaces/azure-devops/package.json index a0961178e..207d2d315 100644 --- a/workspaces/azure-devops/package.json +++ b/workspaces/azure-devops/package.json @@ -6,7 +6,7 @@ "node": "20 || 22" }, "scripts": { - "start": "backstage-cli repo start", + "start": "NODE_OPTIONS=--no-node-snapshot backstage-cli repo start", "tsc": "tsc", "tsc:full": "tsc --skipLibCheck false --incremental false", "build:all": "backstage-cli repo build --all", diff --git a/workspaces/azure-devops/packages/backend/package.json b/workspaces/azure-devops/packages/backend/package.json index fb071f964..de22a21b6 100644 --- a/workspaces/azure-devops/packages/backend/package.json +++ b/workspaces/azure-devops/packages/backend/package.json @@ -24,6 +24,7 @@ "@backstage-community/plugin-azure-devops-backend": "workspace:^", "@backstage-community/plugin-catalog-backend-module-azure-devops-annotator-processor": "workspace:^", "@backstage-community/plugin-scaffolder-backend-module-azure-devops": "workspace:^", + "@backstage-community/plugin-scaffolder-backend-module-dotnet": "workspace:^", "@backstage/backend-defaults": "^0.9.0", "@backstage/config": "^1.3.2", "@backstage/plugin-app-backend": "^0.5.1", @@ -31,6 +32,7 @@ "@backstage/plugin-auth-backend-module-guest-provider": "^0.2.7", "@backstage/plugin-auth-node": "^0.6.2", "@backstage/plugin-catalog-backend": "^1.32.1", + "@backstage/plugin-catalog-backend-module-logs": "^0.1.9", "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^0.2.7", "@backstage/plugin-permission-backend": "^0.6.0", "@backstage/plugin-permission-backend-module-allow-all-policy": "^0.2.7", diff --git a/workspaces/azure-devops/packages/backend/src/index.ts b/workspaces/azure-devops/packages/backend/src/index.ts index 0d523ebdf..902b3ef90 100644 --- a/workspaces/azure-devops/packages/backend/src/index.ts +++ b/workspaces/azure-devops/packages/backend/src/index.ts @@ -58,4 +58,9 @@ backend.add( import('@backstage-community/plugin-scaffolder-backend-module-azure-devops'), ); +backend.add( + import('@backstage-community/plugin-scaffolder-backend-module-dotnet'), +); +backend.add(import('@backstage/plugin-catalog-backend-module-logs')); + backend.start(); diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/.eslintrc.js b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/.eslintrc.js new file mode 100644 index 000000000..e2a53a6ad --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/README.md b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/README.md new file mode 100644 index 000000000..2f7dd4121 --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/README.md @@ -0,0 +1,72 @@ +# Dotnet Actions backend module for the Scaffolder plugin + +This is a [Backend Plugin](https://backstage.io/docs/plugins/backend-plugin/) containing a set of [Custom Actions](https://backstage.io/docs/features/software-templates/writing-custom-actions) using the [`dotnet cli`](https://learn.microsoft.com/en-us/dotnet/core/tools/) + +It contains the following actions: + +- `dotnet:new`: create a new dotnet project + +## Installation + +From your Backstage instance root folder: + +```shell +yarn --cwd packages/backend add @backstage-community/plugin-scaffolder-backend-module-dotnet +``` + +## Configuration + +### Code + +Import the module by modifying the `packages/backend/src/index.ts` file on your Backstage instance: + +```ts +// packages/backend/src/index.ts + +backend.add( + import('@backstage-community/plugin-scaffolder-backend-module-dotnet'), +); +``` + +## Usage + +You can use the action in any of the steps of your [Software Template](https://backstage.io/docs/features/software-templates/). +See [here](../../examples/scaffolder/scaffolder.yaml) for an example of a Software Template making use of the Dotnet New. + +### Example with the `dotnet:new` action + +```yaml +spec: + parameters: + - title: Choose your project + required: + - project + - component_id + properties: + component_id: + title: Name + type: string + description: Unique name of your service. The name must contain only Alphabet characters (e.g MyPlugin) + maxLength: 20 + pattern: '^[A-Za-z]+$' + project: + title: Project + type: string + description: Choose what dotnet project to create + default: None + enum: + - webapi + - aspire + - webapp + # These steps are executed in the scaffolder backend, using data that we gathered + # via the parameters above. + steps: + - id: runAzurePipeline + name: Create New Project + action: dotnet:new + input: + template: ${{parameters.project}} + args: + - -n + - ${{parameters.component_id | replace("-", "_")}} +``` diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/package.json b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/package.json new file mode 100644 index 000000000..28c051915 --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/package.json @@ -0,0 +1,56 @@ +{ + "version": "0.1.0", + "license": "Apache-2.0", + "name": "@backstage-community/plugin-scaffolder-backend-module-dotnet", + "description": "The azure-devops module for @backstage/plugin-scaffolder-backend", + "main": "src/index.ts", + "types": "src/index.ts", + "publishConfig": { + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "package.json": [ + "package.json" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/community-plugins", + "directory": "workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet" + }, + "backstage": { + "role": "backend-plugin-module", + "pluginId": "scaffolder", + "pluginPackage": "@backstage/plugin-scaffolder-backend" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-plugin-api": "^1.3.0", + "@backstage/plugin-scaffolder-node": "^0.8.1", + "fs-extra": "^11.3.0", + "yaml": "^2.6.0", + "zod": "^3.24.3" + }, + "devDependencies": { + "@backstage/cli": "^0.32.0", + "@backstage/plugin-scaffolder-node-test-utils": "^0.2.1", + "@types/fs-extra": "^11" + }, + "files": [ + "dist" + ] +} diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/report.api.md b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/report.api.md new file mode 100644 index 000000000..1e47d64a8 --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/report.api.md @@ -0,0 +1,11 @@ +## API Report File for "@backstage-community/plugin-scaffolder-backend-module-dotnet" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @public +const scaffolderModule: BackendFeature; +export default scaffolderModule; +``` diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.examples.ts b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.examples.ts new file mode 100644 index 000000000..5d1bed9da --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.examples.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2025 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: 'Create Dotnet Project', + example: yaml.stringify({ + steps: [ + { + id: 'createDotnetProject', + action: 'dotnet:new', + name: 'Create New webapi Project', + input: { + template: 'webapi', + }, + }, + ], + }), + }, + { + description: 'Create new dotnet project with arguments', + example: yaml.stringify({ + steps: [ + { + id: 'createDotnetProject', + action: 'dotnet:new', + name: 'Create New webapi Project with name', + input: { + template: 'webapi', + args: ['-n', 'myProjectName'], + }, + }, + ], + }), + }, + { + description: 'Create a new project to a specific path', + example: yaml.stringify({ + steps: [ + { + id: 'createDotnetProject', + action: 'dotnet:new', + name: 'Create New webapi Project', + input: { + template: 'webapi', + targetPath: '/my/path', + }, + }, + ], + }), + }, + { + description: 'Create a new project with arguments and target path', + example: yaml.stringify({ + steps: [ + { + id: 'createDotnetProject', + action: 'dotnet:new', + name: 'Create New webapi Project with name and target path', + input: { + template: 'webapi', + args: ['-n', 'myProjectName'], + targetPath: '/my/path', + }, + }, + ], + }), + }, +]; diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.test.ts b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.test.ts new file mode 100644 index 000000000..bfccd2c9a --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.test.ts @@ -0,0 +1,150 @@ +/* + * 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. + */ + +jest.mock('@backstage/plugin-scaffolder-node', () => { + return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), + initRepoAndPush: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + commitAndPushRepo: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + executeShellCommand: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + }; +}); + +import { createdotnetNewAction } from './dotnetNew'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; + +describe('dotnet:new', () => { + const action = createdotnetNewAction(); + + const mockContext = createMockActionContext({ + input: { + template: 'webapi', + }, + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should run dotnet new command', async () => { + await action.handler({ + ...mockContext, + input: { + template: 'webapi', + args: ['--name', 'myapp'], + }, + }); + // Assert that executeShellCommand was called with the correct command and args + const { + executeShellCommand, + } = require('@backstage/plugin-scaffolder-node'); + expect(executeShellCommand).toHaveBeenCalledWith( + expect.objectContaining({ + command: 'dotnet', + args: ['new', 'webapi', '--name', 'myapp'], + }), + ); + }); + it('should run dotnet new with only template', async () => { + await action.handler({ + ...mockContext, + input: { + template: 'console', + }, + }); + const { + executeShellCommand, + } = require('@backstage/plugin-scaffolder-node'); + expect(executeShellCommand).toHaveBeenCalledWith( + expect.objectContaining({ + command: 'dotnet', + args: ['new', 'console'], + }), + ); + }); + + it('should run dotnet new with template and args', async () => { + await action.handler({ + ...mockContext, + input: { + template: 'webapi', + args: ['--name', 'myapp'], + }, + }); + const { + executeShellCommand, + } = require('@backstage/plugin-scaffolder-node'); + expect(executeShellCommand).toHaveBeenCalledWith( + expect.objectContaining({ + command: 'dotnet', + args: ['new', 'webapi', '--name', 'myapp'], + }), + ); + }); + + it('should run dotnet new with template and targetPath', async () => { + await action.handler({ + ...mockContext, + input: { + template: 'classlib', + targetPath: 'src/libs', + }, + workspacePath: '/tmp/workspace', + }); + const { + executeShellCommand, + } = require('@backstage/plugin-scaffolder-node'); + expect(executeShellCommand).toHaveBeenCalledWith( + expect.objectContaining({ + command: 'dotnet', + args: ['new', 'classlib'], + options: expect.objectContaining({ + cwd: expect.stringContaining('src/libs'), + }), + }), + ); + }); + + it('should run dotnet new with template, args, and targetPath', async () => { + await action.handler({ + ...mockContext, + input: { + template: 'webapi', + args: ['--name', 'myweb'], + targetPath: 'src/web', + }, + workspacePath: '/tmp/workspace', + }); + const { + executeShellCommand, + } = require('@backstage/plugin-scaffolder-node'); + expect(executeShellCommand).toHaveBeenCalledWith( + expect.objectContaining({ + command: 'dotnet', + args: ['new', 'webapi', '--name', 'myweb'], + options: expect.objectContaining({ + cwd: expect.stringContaining('src/web'), + }), + }), + ); + }); +}); diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.ts b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.ts new file mode 100644 index 000000000..3c2d3e2e4 --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/actions/dotnetNew.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2025 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 { + createTemplateAction, + executeShellCommand, +} from '@backstage/plugin-scaffolder-node'; +import { resolveSafeChildPath } from '@backstage/backend-plugin-api'; + +export const createdotnetNewAction = () => { + return createTemplateAction({ + id: 'dotnet:new', + description: 'Runs a dotnet new command', + schema: { + input: { + template: z => z.string().describe('Template name'), + args: z => + z + .array(z.any()) + .describe('Arguments to pass to the command') + .optional(), + targetPath: z => + z + .string() + .describe( + 'Target path within the working directory to generate contents to. Defaults to the working directory root.', + ) + .optional(), + }, + }, + async handler(ctx) { + const { template, args, targetPath } = ctx.input; + + const outputDir = resolveSafeChildPath( + ctx.workspacePath, + targetPath ?? './', + ); + + ctx.logger.info( + `Running dotnet new ${template} script with dotnet:new scaffolder action, workspace path: ${outputDir}`, + ); + + await executeShellCommand({ + command: 'dotnet', + args: ['new', template, ...(args ?? []).map(x => stringify(x))], + options: { + cwd: outputDir, + }, + logger: ctx.logger, + }); + + ctx.logger.info(`Template written to ${outputDir}`); + }, + }); +}; + +function stringify(value: any) { + switch (typeof value) { + case 'string': + return value; + case 'object': + return JSON.stringify(value); + default: + return String(value); + } +} diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/index.ts b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/index.ts new file mode 100644 index 000000000..dd3b49bc8 --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2025 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. + */ + +/** + * The dotnet module for the Scaffolder. + * + * @packageDocumentation + */ + +export { scaffolderModule as default } from './module'; diff --git a/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/module.ts b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/module.ts new file mode 100644 index 000000000..f9106abef --- /dev/null +++ b/workspaces/azure-devops/plugins/scaffolder-backend-module-dotnet/src/module.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2025 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 { createBackendModule } from '@backstage/backend-plugin-api'; +import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; +import { createdotnetNewAction } from './actions/dotnetNew'; + +/** + * A backend module that registers the action into the scaffolder + * @public + */ +export const scaffolderModule = createBackendModule({ + moduleId: 'dotnet', + pluginId: 'scaffolder', + register({ registerInit }) { + registerInit({ + deps: { + scaffolderActions: scaffolderActionsExtensionPoint, + }, + async init({ scaffolderActions }) { + scaffolderActions.addActions(createdotnetNewAction()); + }, + }); + }, +}); diff --git a/workspaces/azure-devops/yarn.lock b/workspaces/azure-devops/yarn.lock index 125fb0378..a1a0bb4e5 100644 --- a/workspaces/azure-devops/yarn.lock +++ b/workspaces/azure-devops/yarn.lock @@ -2768,6 +2768,21 @@ __metadata: languageName: unknown linkType: soft +"@backstage-community/plugin-scaffolder-backend-module-dotnet@workspace:^, @backstage-community/plugin-scaffolder-backend-module-dotnet@workspace:plugins/scaffolder-backend-module-dotnet": + version: 0.0.0-use.local + resolution: "@backstage-community/plugin-scaffolder-backend-module-dotnet@workspace:plugins/scaffolder-backend-module-dotnet" + dependencies: + "@backstage/backend-plugin-api": "npm:^1.3.0" + "@backstage/cli": "npm:^0.32.0" + "@backstage/plugin-scaffolder-node": "npm:^0.8.1" + "@backstage/plugin-scaffolder-node-test-utils": "npm:^0.2.1" + "@types/fs-extra": "npm:^11" + fs-extra: "npm:^11.3.0" + yaml: "npm:^2.6.0" + zod: "npm:^3.24.3" + languageName: unknown + linkType: soft + "@backstage/app-defaults@npm:^1.6.1": version: 1.6.1 resolution: "@backstage/app-defaults@npm:1.6.1" @@ -4076,6 +4091,17 @@ __metadata: languageName: node linkType: hard +"@backstage/plugin-catalog-backend-module-logs@npm:^0.1.9": + version: 0.1.9 + resolution: "@backstage/plugin-catalog-backend-module-logs@npm:0.1.9" + dependencies: + "@backstage/backend-plugin-api": "npm:^1.3.0" + "@backstage/plugin-catalog-backend": "npm:^1.32.1" + "@backstage/plugin-events-node": "npm:^0.4.10" + checksum: 10/811e5fc8498b83815989d48c7da2c5487a2d60da270291354b9c49e22dd3ade6ffd466fb01709597b39635ce09ebf655341c8b206fba554cbdb41d9234658bd0 + languageName: node + linkType: hard + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model@npm:^0.2.7": version: 0.2.7 resolution: "@backstage/plugin-catalog-backend-module-scaffolder-entity-model@npm:0.2.7" @@ -12553,6 +12579,16 @@ __metadata: languageName: node linkType: hard +"@types/fs-extra@npm:^11": + version: 11.0.4 + resolution: "@types/fs-extra@npm:11.0.4" + dependencies: + "@types/jsonfile": "npm:*" + "@types/node": "npm:*" + checksum: 10/acc4c1eb0cde7b1f23f3fe6eb080a14832d8fa9dc1761aa444c5e2f0f6b6fa657ed46ebae32fb580a6700fc921b6165ce8ac3e3ba030c3dd15f10ad4dd4cae98 + languageName: node + linkType: hard + "@types/graceful-fs@npm:^4.1.3": version: 4.1.9 resolution: "@types/graceful-fs@npm:4.1.9" @@ -12685,6 +12721,15 @@ __metadata: languageName: node linkType: hard +"@types/jsonfile@npm:*": + version: 6.1.4 + resolution: "@types/jsonfile@npm:6.1.4" + dependencies: + "@types/node": "npm:*" + checksum: 10/309fda20eb5f1cf68f2df28931afdf189c5e7e6bec64ac783ce737bb98908d57f6f58757ad5da9be37b815645a6f914e2d4f3ac66c574b8fe1ba6616284d0e97 + languageName: node + linkType: hard + "@types/jsonwebtoken@npm:^9.0.0": version: 9.0.7 resolution: "@types/jsonwebtoken@npm:9.0.7" @@ -14784,6 +14829,7 @@ __metadata: "@backstage-community/plugin-azure-devops-backend": "workspace:^" "@backstage-community/plugin-catalog-backend-module-azure-devops-annotator-processor": "workspace:^" "@backstage-community/plugin-scaffolder-backend-module-azure-devops": "workspace:^" + "@backstage-community/plugin-scaffolder-backend-module-dotnet": "workspace:^" "@backstage/backend-defaults": "npm:^0.9.0" "@backstage/cli": "npm:^0.32.0" "@backstage/config": "npm:^1.3.2" @@ -14792,6 +14838,7 @@ __metadata: "@backstage/plugin-auth-backend-module-guest-provider": "npm:^0.2.7" "@backstage/plugin-auth-node": "npm:^0.6.2" "@backstage/plugin-catalog-backend": "npm:^1.32.1" + "@backstage/plugin-catalog-backend-module-logs": "npm:^0.1.9" "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "npm:^0.2.7" "@backstage/plugin-permission-backend": "npm:^0.6.0" "@backstage/plugin-permission-backend-module-allow-all-policy": "npm:^0.2.7" @@ -19702,14 +19749,14 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.0.0, fs-extra@npm:^11.2.0": - version: 11.2.0 - resolution: "fs-extra@npm:11.2.0" +"fs-extra@npm:^11.0.0, fs-extra@npm:^11.2.0, fs-extra@npm:^11.3.0": + version: 11.3.0 + resolution: "fs-extra@npm:11.3.0" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/0579bf6726a4cd054d4aa308f10b483f52478bb16284f32cf60b4ce0542063d551fca1a08a2af365e35db21a3fa5a06cf2a6ed614004b4368982bc754cb816b3 + checksum: 10/c9fe7b23dded1efe7bbae528d685c3206477e20cc60e9aaceb3f024f9b9ff2ee1f62413c161cb88546cc564009ab516dec99e9781ba782d869bb37e4fe04a97f languageName: node linkType: hard @@ -33497,10 +33544,10 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.22.4": - version: 3.23.8 - resolution: "zod@npm:3.23.8" - checksum: 10/846fd73e1af0def79c19d510ea9e4a795544a67d5b34b7e1c4d0425bf6bfd1c719446d94cdfa1721c1987d891321d61f779e8236fde517dc0e524aa851a6eff1 +"zod@npm:^3.22.4, zod@npm:^3.24.3": + version: 3.24.3 + resolution: "zod@npm:3.24.3" + checksum: 10/1b15db625ca633324084f3a8587bfb907043bbca407a09f7d5da6a9781b3838c68e9312b49e91e479d2f8bf04cdda5810803ac9504e3b7ccbec3adf2de625fb8 languageName: node linkType: hard