diff --git a/docs/features/software-templates/extending/create-your-own-preparer.md b/docs/features/software-templates/extending/create-your-own-preparer.md deleted file mode 100644 index 5419748c3a..0000000000 --- a/docs/features/software-templates/extending/create-your-own-preparer.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -id: extending-preparer -title: Create your own Preparer -description: Documentation on Creating your own Preparer ---- - -Preparers are responsible for reading the location of the definition of a -[Template Entity](../../software-catalog/descriptor-format.md#kind-template) and -making a temporary folder with the contents of the selected skeleton. - -Currently, we provide two different providers that can parse two different -location protocols: - -- `file://` -- `github://` - -These two are added to the `PreparersBuilder` and then passed into the -`createRouter` function of the `@backstage/plugin-scaffolder-backend`. - -A full example backend can be found in -[`scaffolder.ts`](https://github.com/backstage/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), -but it looks something like the following - -```ts -import { - createRouter, - FilePreparer, - GithubPreparer, - Preparers, -} from '@backstage/plugin-scaffolder-backend'; -import type { PluginEnvironment } from '../types'; - -export default async function createPlugin({ logger }: PluginEnvironment) { - const preparers = new Preparers(); - - const filePreparer = new FilePreparer(); - const githubPreparer = new GithubPreparer(); - - preparers.register('file', filePreparer); - preparers.register('github', githubPreparer); - - return await createRouter({ - preparers, - templaters, - logger, - }); -} -``` - -As you can see in the above code, a `PreparerBuilder` is created, and then two -of the `preparers` are registered with the different protocols that they accept. - -The `protocol` is set on the -[Template Entity](../../software-catalog/descriptor-format.md#kind-template) -when added to the service catalog. You can see more about this `PreparerKey` -here in [Register your own template](../adding-templates.md) - -**note:** Currently the catalog supports loading definitions from GitHub + Local -Files, which translate into the two `PreparerKeys`: `file` and `github`. To load -from other places, not only will there need to be another preparer, but the -support to load the location will also need to be added to the Catalog. - -### Creating your own Preparer to add to the `PreparerBuilder` - -All preparers need to implement the `PreparerBase` type. - -That type looks like the following: - -```ts -export type PreparerBase = { - prepare( - template: TemplateEntityV1alpha1, - opts: { logger: Logger }, - ): Promise; -}; -``` - -The `prepare` function will be given the -[Template Entity](../../software-catalog/descriptor-format.md#kind-template) -along with the source of where the `template.yaml` was loaded from under the -`metedata.annotations.managed-by-location` property. - -Now it's up to you to implement a function which can go and fetch the skeleton -and put the contents into a temporary directory and return that directory path. - -Some good examples exist here: - -- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts -- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts - -### Registering your own Preparer - -You can register the preparer that you have created with the `PreparerBuilder` -by using the `PreparerKey` from the Catalog, for example like this: - -```ts -const preparers = new Preparers(); -preparers.register('gcs', new GoogleCloudStoragePreparer()); -``` - -And then pass this into the `createRouter` function. diff --git a/docs/features/software-templates/extending/create-your-own-publisher.md b/docs/features/software-templates/extending/create-your-own-publisher.md deleted file mode 100644 index 5e2809e006..0000000000 --- a/docs/features/software-templates/extending/create-your-own-publisher.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: extending-publisher -title: Create your own Publisher -description: Documentation on Creating your own Publisher ---- - -Publishers are responsible for pushing and storing the templated skeleton after -the values have been templated by the `Templater`. See -[Create your own templater](./create-your-own-templater.md) for more info. - -They receive a directory or location where the templater has successfully run -and is now ready to store somewhere. They also are given some other options -which are sent from the frontend, such as the `storePath` which is a string of -where the frontend thinks we should save this templated folder. - -Currently we provide the following `publishers`: - -- `github` - -This publisher is passed through to the `createRouter` function of the -`@backstage/plugin-scaffolder-backend`. Currently, only one publisher is -supported, but PR's are always welcome. - -An full example backend can be found -[here](https://github.com/backstage/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), -but it looks something like the following - -```ts -import { - createRouter, - GithubPublisher, -} from '@backstage/plugin-scaffolder-backend'; -import { Octokit } from '@octokit/rest'; -import type { PluginEnvironment } from '../types'; - -export default async function createPlugin({ logger }: PluginEnvironment) { - const githubClient = new Octokit({ auth: process.env.GITHUB_TOKEN }); - const publisher = new GithubPublisher({ client: githubClient }); - - return await createRouter({ - publisher, - logger, - }); -} -``` - -The publisher will always be called with the location from the selected -`Preparer`. - -### Create your own Publisher and register it with the Scaffolder - -All `publishers` need to implement the `PublisherBase` type. - -That type looks like the following: - -```ts -export type PublisherBase = { - publish(opts: { - entity: TemplateEntityV1alpha1; - values: TemplaterValues; - directory: string; - }): Promise<{ remoteUrl: string }>; -}; -``` - -The `publisher` function will be called with an `options` object which contains -the following: - -- `entity` - the - [Template Entity](../../software-catalog/descriptor-format.md#kind-template) - which is currently being scaffolded -- `values` - a json object which will resemble the `spec.schema` from the - [Template Entity](../../software-catalog/descriptor-format.md#kind-template) - which is defined here under spec.schema`. More info can be found here - [Register your own template](../adding-templates.md#adding-form-values-in-the-scaffolder-wizard) -- `directory` - a string containing the returned path from the `templater`. See - more information here in - [Create your own templater](./create-your-own-templater.md) - -Now it's up to you to implement the `publish` function and return -`{ remoteUrl: string }` which can be used to identify the finished product. - -Some good examples exist here: - -- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts - -### Registering your own Publisher - -Currently, we only support one `publisher` (PR's welcome), but you can register -any single `publisher` with the `createRouter`. - -```ts -return await createRouter({ - publisher: new MyGitlabPublisher(), -}); -``` diff --git a/docs/features/software-templates/extending/create-your-own-templater.md b/docs/features/software-templates/extending/create-your-own-templater.md deleted file mode 100644 index 28769d77e1..0000000000 --- a/docs/features/software-templates/extending/create-your-own-templater.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -id: extending-templater -title: Creating your own Templater -description: Documentation on Creating your own Templater ---- - -Templaters are responsible for taking the directory path for the skeleton -returned by the preparers, and then executing the templating command on top of -the file and returning the completed template path. This may or may not be the -same directory as the input directory. - -They also receive additional values from the frontend, which can be used to -interpolate into the skeleton files. - -Currently we provide the following templaters: - -- `cookiecutter` - -This templater is added to the `TemplaterBuilder` and then passed into the -`createRouter` function of the `@backstage/plugin-scaffolder-backend` - -An full example backend can be found -[here](https://github.com/backstage/backstage/blob/d91c10f654475a60829fa33a5c81018e517a319a/packages/backend/src/plugins/scaffolder.ts), -but it looks something like the following - -```ts -import { - CookieCutter, - createRouter, - Templaters, -} from '@backstage/plugin-scaffolder-backend'; -import type { PluginEnvironment } from '../types'; - -export default async function createPlugin({ logger }: PluginEnvironment) { - const templaters = new Templaters(); - const cookiecutterTemplater = new CookieCutter(); - templaters.register('cookiecutter', cookiecutterTemplater); - - return await createRouter({ - templaters, - }); -} -``` - -As you can see in the above code a `TemplaterBuilder` is created and the default -`cookiecutter` `templater` is registered under the key `cookicutter`. - -This `TemplaterKey` is used to select the correct templater from the -`spec.templater` in the -[Template Entity](../../software-catalog/descriptor-format.md#kind-template). - -If you wish to add a new templater, you'll need to register it with the -`TemplaterBuilder`. - -### Creating your own Templater to add to the `TemplaterBuilder` - -All templaters need to implement the `TemplaterBase` type. - -That type looks like the following: - -```ts -export type TemplaterRunOptions = { - directory: string; - values: TemplaterValues; - logStream?: Writable; - dockerClient: Docker; -}; - -export type TemplaterBase = { - run(opts: TemplaterRunOptions): Promise; -}; -``` - -The `run` function will be given a `TemplaterRunOptions` object which is as -follows: - -- `directory`- the skeleton directory returned from the `Preparer`, more info at - [Create your own preparer](./create-your-own-preparer.md). -- `values` - a json object which will resemble the `spec.schema` from the - [Template Entity](../../software-catalog/descriptor-format.md#kind-template) - which is defined here under spec.schema`. More info can be found here - [Register your own template](../adding-templates.md#adding-form-values-in-the-scaffolder-wizard) -- `logStream` - a stream that you can write to for displaying in the frontend. -- `dockerClient` - a [dockerode](https://github.com/apocas/dockerode) client to - be able to run docker containers. - -_note_ Currently the templaters that we provide are basically Docker action -containers that are run on top of the skeleton folder. This keeps dependencies -to a minimum for running Backstage scaffolder, but you don't _have_ to use -Docker. You can `pip install cookiecutter` to run it locally in your backend. -You could create your own templater that spins up an EC2 instance and downloads -the folder and does everything using an AMI if you want. It's entirely up to -you! - -Now it's up to you to implement the `run` function, and then return a -`TemplaterRunResult` which is `{ resultDir: string }`. - -Some good examples exist here: - -- https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts - -### Registering your own Templater - -If you try to process a -[Template Entity](../../software-catalog/descriptor-format.md#kind-template) -with a new `spec.templater` value, you'll need to register that with the -`TemplaterBuilder`. - -For example let's say you have the following -[Template Entity](../../software-catalog/descriptor-format.md#kind-template): - -```yaml -apiVersion: backstage.io/v1alpha1 -kind: Template -metadata: - name: react-ssr-template - title: React SSR Template - description: - Next.js application skeleton for creating isomorphic web applications. - tags: - - recommended - - react -spec: - owner: web@example.com - templater: handlebars - type: website - path: '.' - schema: - required: - - component_id - - description - properties: - component_id: - title: Name - type: string - description: Unique name of the component - description: - title: Description - type: string - description: Description of the component -``` - -You see that the `spec.templater` is set as `handlebars`, so you'll need to -register this with the `TemplaterBuilder` like so: - -```ts -const templaters = new Templaters(); -templaters.register('handlebars', new HandlebarsTemplater()); -``` - -And then pass this into the `createRouter` function. diff --git a/docs/features/software-templates/extending/index.md b/docs/features/software-templates/extending/index.md deleted file mode 100644 index aaf42d6b12..0000000000 --- a/docs/features/software-templates/extending/index.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: extending-index -title: Extending the Scaffolder ---- - -Welcome. Take a seat. You're at the Scaffolder Documentation. - -So, you want to create stuff inside your company from some prebaked templates? -You're at the right place. - -This guide is going to take you through how the Scaffolder in Backstage works. -We'll dive into some jargon and run through what's going on in the backend to be -able to create these templates. There's also more guides that you might find -useful at the bottom of this document. At its core, there are 3 simple stages. - -1. Pick a skeleton -2. Template some variables into the skeleton -3. Send the templated skeleton somewhere - -These three steps are translated to the following stages under the hood in the -scaffolder that you will need to know: - -1. Prepare -2. Template -3. Publish - -Each of these steps can be configured for your own use case, but we provide some -sensible defaults, too. - -Let's dive a little deeper into these phases. - -### Glossary and Jargon - -**Preparer** - The preparer is responsible for fetching the skeleton code and -placing it into a directory and then will return that directory. It is -registered with the `Preparers` with a particular type, which is then used in -the router to pick the correct `Preparer` to run for the `Template` entity. - -**Templater** - The templater is responsible for actually running the chosen -templater on top of the previously returned temporary directory from the -**Preparer**. We advise making these Docker containers as it can keep all -dependencies--for example Cookiecutter--self contained and not a dependency on -the host machine. - -**Publisher** - The publisher is responsible for taking the finished directory, -and publishing it to a remote registry. This could be a Git repository or -something similar. Right now, the scaffolder only supports one publishing method -for the entire lifecycle, but it could be configured from the frontend and -passed through to the scaffolder backend. - -### How it works - -Most of the heavy lifting is done in the -[router.ts](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/src/service/router.ts#L93) -file in the `scaffolder-backend` plugin. - -There are two routes defined in the router: `POST /v1/jobs` and -`GET /v1/job/:jobId` - -To create a scaffolding job, a JSON object containing the -[Template Entity](../../software-catalog/descriptor-format.md#kind-template) + -additional templating values must be posted as the post body. - -```js -{ - "template": { - "apiVersion": "backstage/v1alpha1", - "kind": "Template", - // more stuff here - }, - "values": { - "component_id": "test", - "description": "somethingelse" - } -} -``` - -The values should represent something that is valid with the `schema` part of -the [Template Entity](../../software-catalog/descriptor-format.md#kind-template) - -Once that has been posted, a job will be setup with different stages, and the -job processor will complete each stage before moving onto the next stage, whilst -collecting logs and mutating the running job. - -Here's some further reading that you might find useful: - -- [Adding your own Template](../adding-templates.md) -- [Creating your own Templater](./create-your-own-templater.md) -- [Creating your own Publisher](./create-your-own-publisher.md) -- [Creating your own Preparer](./create-your-own-preparer.md)