diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 00a171523c..23c5e87f7d 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -141,6 +141,88 @@ Prefer to use `camelCase` over `snake_case` or `kebab-case` for these actions if > We're aware that there are some exceptions to this, but try to follow as close as possible. We'll be working on migrating these in the repository over time too. + +### Template Example + +A Template Example is a predefined format or structure that can be used to create custom actions in your software templates. It serves as a blueprint to ensure consistency and standardization across different custom actions. + +#### How to Use a Template Example: + +1. Identify the custom action you want to create. +2. Refer to the Template Example to understand the required structure and components. +3. Fill in the necessary details in the template, such as action name, parameters, and logic. +4. Integrate the completed template into your software template to enable the custom action. + +#### Benefits: + +- Ensures consistency in custom actions. +- Simplifies the creation process by providing a clear structure. +- Helps in maintaining standardization across different templates. + +#### Define an Example and add to your Custom Action + +```ts title="With JSON Schema" +import { TemplateExample } from "@backstage/plugin-scaffolder-node"; +import yaml from "yaml"; + +export const AcmeExample: TemplateExample[] = [ + { + description: "Template Example for Creating an Acme file", + example: yaml.stringify({ + steps: [ + { + action: "acme:file:create", + name: "Create an Acme file.", + input: { + contents: "file contents...", + filename: "ACME.properties" + }, + }, + ], + }), + }, +]; +``` + +Add the example to the `createTemplateAction` under the object property `examples`: + +```ts title="With JSON Schema" +export const createNewFileAction = () => { + return createTemplateAction<{ contents: string; filename: string }>({ + id: 'acme:file:create', + description: 'Create an Acme file.', + examples: AcmeExample, + schema: { + input: { + required: ['contents', 'filename'], + type: 'object', + properties: { + contents: { + type: 'string', + title: 'Contents', + description: 'The contents of the file', + }, + filename: { + type: 'string', + title: 'Filename', + description: 'The filename of the file that will be created', + }, + }, + }, + }, + async handler(ctx) { + const { signal } = ctx; + await writeFile( + resolveSafeChildPath(ctx.workspacePath, ctx.input.filename), + ctx.input.contents, + { signal }, + _ => {}, + ); + }, + }); +}; +``` + ### The context object When the action `handler` is called, we provide you a `context` as the only