From 8de182a42ae62132e05805c89ed6c9f176c6eff1 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 17:20:47 +0200 Subject: [PATCH 1/5] WIP. Add custom filters doc section Signed-off-by: cmoulliard --- .../software-templates/writing-templates.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index ad542ba4a3..0f5c10b96d 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -654,6 +654,8 @@ how to use them in the Scaffolder templates. It's important to mention that Back native filters from the Nunjucks library. For a complete list of these native filters and their usage, refer to the [Nunjucks documentation](https://mozilla.github.io/nunjucks/templating.html#builtin-filters). +To create your own custom filters, look to the section [Custom Filters](#custom-filters) hereafter. + ### parseRepoUrl The `parseRepoUrl` filter parse a repository URL into @@ -738,3 +740,26 @@ The `projectSlug` filter generates a project slug from a repository URL - **Input**: `github.com?repo=backstage&org=backstage` - **Output**: `backstage/backstage` + +## Custom Filters + +Whenever it is needed to extend the built-in filters with yours `${{ parameters.name | my-filter1 | my-filter2 | etc }}`, then you have the option to add them using the property `addTemplateFilters` of the type `RouterOptions` that you typically define + +```ts title="plugins/scaffolder-backend/src/service/router.ts" +export interface RouterOptions { + ... + additionalTemplateFilters?: Record; +} +``` + +The `addTemplateFilters` function accepts the filters as a JSON array of records where each record starts +with the name of the filter, get as input a list of `JSON value` arguments and will return a JsonValue. + +```ts title="plugins/scaffolder-node/stc/types.ts" +export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; +``` + +OR + +function of the `ScaffolderTemplatingExtensionPoint` interface +addTemplateFilters(filters: Record): void; From 6c58521e5b8974941df7605a9c7da9327be47afd Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 18:10:21 +0200 Subject: [PATCH 2/5] Review the section custom filter and fix vale error Signed-off-by: cmoulliard --- .../software-templates/writing-templates.md | 73 ++++++++++++++++--- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 0f5c10b96d..0b5f8c4948 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -743,23 +743,74 @@ The `projectSlug` filter generates a project slug from a repository URL ## Custom Filters -Whenever it is needed to extend the built-in filters with yours `${{ parameters.name | my-filter1 | my-filter2 | etc }}`, then you have the option to add them using the property `addTemplateFilters` of the type `RouterOptions` that you typically define +Whenever it is needed to extend the built-in filters with yours `${{ parameters.name | my-filter1 | my-filter2 | etc }}`, then you can add them +using the property `addTemplateFilters` that you typically define using the `createRouter()` function of the `Scaffolder plugin` -```ts title="plugins/scaffolder-backend/src/service/router.ts" -export interface RouterOptions { +```ts title="packages/backend/src/plugins/scaffolder.ts" +export default async function createPlugin({ + logger, + config, +}: PluginEnvironment): Promise { ... - additionalTemplateFilters?: Record; -} + return await createRouter({ + logger, + config, + + additionalTemplateFilters: { + + } + }); ``` -The `addTemplateFilters` function accepts the filters as a JSON array of records where each record starts -with the name of the filter, get as input a list of `JSON value` arguments and will return a JsonValue. +The `addTemplateFilters` property accepts a `Record` -```ts title="plugins/scaffolder-node/stc/types.ts" +```ts title="plugins/scaffolder-backend/src/service/Router.ts" + additionalTemplateFilters?: Record; +``` + +where the first parameter is the name of the filter and the second `TemplateFilter` receives a list of `JSON value` arguments. The `templateFilter()` function should return a JsonValue (Json array, object or primitive). + +```ts title="plugins/scaffolder-node/src/types.ts" export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; ``` -OR +From a practical coding point of view, you will translate that into the following snippet code -function of the `ScaffolderTemplatingExtensionPoint` interface -addTemplateFilters(filters: Record): void; +```ts title="packages/backend/src/plugins/scaffolder.ts" +... + return await createRouter({ + logger: env.logger, + config: env.config, + additionalTemplateFilters: { + base64: (...args: JsonValue[]) => btoa(args.join("")), + betterFilter: (...args: JsonValue[]) => { return `This is a much better string than "${args}", don't you think?` } + }, +}); +``` + +And within your template, you will be able to use the filters like this + +```yaml +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: test + title: Test +spec: + owner: user:guest + type: service + + parameters: + - title: Test custom filters + properties: + userName: + title: Name of the user + type: string + + steps: + - id: debug + name: debug + action: debug:log + input: + message: ${{ parameters.userName | betterFilter | base64 }} +``` From 6200d6204bc471fa49d8c826ca469bdb7586c453 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 18:11:07 +0200 Subject: [PATCH 3/5] Change should to switch. #24002 Signed-off-by: cmoulliard --- docs/features/software-templates/writing-templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 0b5f8c4948..4b169a0714 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -768,7 +768,7 @@ The `addTemplateFilters` property accepts a `Record` additionalTemplateFilters?: Record; ``` -where the first parameter is the name of the filter and the second `TemplateFilter` receives a list of `JSON value` arguments. The `templateFilter()` function should return a JsonValue (Json array, object or primitive). +where the first parameter is the name of the filter and the second `TemplateFilter` receives a list of `JSON value` arguments. The `templateFilter()` function must return a JsonValue (Json array, object or primitive). ```ts title="plugins/scaffolder-node/src/types.ts" export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; From b10a8cb578d3821920133b7c6ecf68d5e43ddd12 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Mon, 22 Apr 2024 18:36:24 +0200 Subject: [PATCH 4/5] Include the section covering: Register Custom Filters with the New Backend System Signed-off-by: cmoulliard --- .../software-templates/writing-templates.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 4b169a0714..766a58d01b 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -814,3 +814,44 @@ spec: input: message: ${{ parameters.userName | betterFilter | base64 }} ``` + +### Register Custom Filters with the New Backend System + +To register the custom filters using the new Backend System, you will have to create a [backend module](../../backend-system/architecture/06-modules.md) calling following extension point: `scaffolderTemplatingExtensionPoint`. + +Here is a very simplified example of how to do that: + +```ts title="packages/backend/src/index.ts" +/* highlight-add-start */ +import { scaffolderTemplatingExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; +import { createBackendModule } from '@backstage/backend-plugin-api'; +/* highlight-add-end */ + +/* highlight-add-start */ +const scaffolderModuleCustomFilters = createBackendModule({ + pluginId: 'scaffolder', // name of the plugin that the module is targeting + moduleId: 'custom-filters', + register(env) { + env.registerInit({ + deps: { + scaffolder: scaffolderTemplatingExtensionPoint, + // ... and other dependencies as needed + }, + async init({ scaffolder /* ..., other dependencies */ }) { + scaffolder.addTemplateFilters({ + base64: (...args: JsonValue[]) => btoa(args.join('')), + betterFilter: (...args: JsonValue[]) => { + return `This is a much better string than "${args}", don't you think?`; + }, + }); + }, + }); + }, +}); +/* highlight-add-end */ + +const backend = createBackend(); +backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); +/* highlight-add-next-line */ +backend.add(scaffolderModuleCustomFilters()); +``` From 686e31b9614112cdd3ff20636464659de8de9511 Mon Sep 17 00:00:00 2001 From: cmoulliard Date: Fri, 3 May 2024 15:03:06 +0200 Subject: [PATCH 5/5] Refactoring the documentation to cover first the new backend system and at the end the legacy Signed-off-by: cmoulliard --- .../software-templates/writing-templates.md | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 766a58d01b..f64925068a 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -744,51 +744,31 @@ The `projectSlug` filter generates a project slug from a repository URL ## Custom Filters Whenever it is needed to extend the built-in filters with yours `${{ parameters.name | my-filter1 | my-filter2 | etc }}`, then you can add them -using the property `addTemplateFilters` that you typically define using the `createRouter()` function of the `Scaffolder plugin` +using the property `additionalTemplateFilters`. -```ts title="packages/backend/src/plugins/scaffolder.ts" -export default async function createPlugin({ - logger, - config, -}: PluginEnvironment): Promise { - ... - return await createRouter({ - logger, - config, - - additionalTemplateFilters: { - - } - }); -``` - -The `addTemplateFilters` property accepts a `Record` +The `additionalTemplateFilters` property accepts as type a `Record` ```ts title="plugins/scaffolder-backend/src/service/Router.ts" additionalTemplateFilters?: Record; ``` -where the first parameter is the name of the filter and the second `TemplateFilter` receives a list of `JSON value` arguments. The `templateFilter()` function must return a JsonValue (Json array, object or primitive). +where the first parameter is the name of the filter and the second receives a list of `JSON value` arguments. The `templateFilter()` function must return a JsonValue which is either a Json array, object or primitive. ```ts title="plugins/scaffolder-node/src/types.ts" export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; ``` -From a practical coding point of view, you will translate that into the following snippet code +From a practical coding point of view, you will translate that into the following snippet code handling 2 filters: -```ts title="packages/backend/src/plugins/scaffolder.ts" +```ts" ... - return await createRouter({ - logger: env.logger, - config: env.config, - additionalTemplateFilters: { - base64: (...args: JsonValue[]) => btoa(args.join("")), - betterFilter: (...args: JsonValue[]) => { return `This is a much better string than "${args}", don't you think?` } - }, -}); +additionalTemplateFilters: { + base64: (...args: JsonValue[]) => btoa(args.join("")), + betterFilter: (...args: JsonValue[]) => { return `This is a much better string than "${args}", don't you think?` } +} ``` -And within your template, you will be able to use the filters like this +And within your template, you will be able to use the filters using a parameter and the filter passed using the pipe symbol ```yaml apiVersion: scaffolder.backstage.io/v1beta3 @@ -815,13 +795,11 @@ spec: message: ${{ parameters.userName | betterFilter | base64 }} ``` -### Register Custom Filters with the New Backend System - -To register the custom filters using the new Backend System, you will have to create a [backend module](../../backend-system/architecture/06-modules.md) calling following extension point: `scaffolderTemplatingExtensionPoint`. +Next, you will have to register the property `addTemplateFilters` using the `scaffolderTemplatingExtensionPoint` of a new `BackendModule` [created](../../backend-system/architecture/06-modules.md). Here is a very simplified example of how to do that: -```ts title="packages/backend/src/index.ts" +```ts title="packages/backend-next/src/index.ts" /* highlight-add-start */ import { scaffolderTemplatingExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; import { createBackendModule } from '@backstage/backend-plugin-api'; @@ -855,3 +833,21 @@ backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); /* highlight-add-next-line */ backend.add(scaffolderModuleCustomFilters()); ``` + +If you still use the legacy backend system, then you will use the `createRouter()` function of the `Scaffolder plugin` + +```ts title="packages/backend/src/plugins/scaffolder.ts" +export default async function createPlugin({ + logger, + config, +}: PluginEnvironment): Promise { + ... + return await createRouter({ + logger, + config, + + additionalTemplateFilters: { + + } + }); +```