Onboarding Software to Backstage

45 MINS

Writing new Software Templates

Note: Software Templates = Scaffolder, used interchangeably as it is the name of the Backstage plugin enabling that functionality.

Let’s create a simple Software Template and register in the Software Catalog.

  1. In your local computer, create a directory called test-docs-template anywhere.
  2. Inside the directory, create a template.yaml file with the following content:
<span class="line"><span style="color:#85E89D">apiVersion</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">scaffolder.backstage.io/v1beta3</span></span>
<span class="line"><span style="color:#85E89D">kind</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Template</span></span>
<span class="line"><span style="color:#85E89D">metadata</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">  name</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">docs-template</span></span>
<span class="line"><span style="color:#85E89D">  title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Documentation Template</span></span>
<span class="line"><span style="color:#85E89D">  description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Create a new standalone documentation project</span></span>
<span class="line"><span style="color:#85E89D">  tags</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#9ECBFF">recommended</span></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#9ECBFF">techdocs</span></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#9ECBFF">mkdocs</span></span>
<span class="line"><span style="color:#85E89D">spec</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">  owner</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">my-awesome-team</span></span>
<span class="line"><span style="color:#85E89D">  type</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">documentation</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">  parameters</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#85E89D">title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Fill in some steps</span></span>
<span class="line"><span style="color:#85E89D">      required</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">        - </span><span style="color:#9ECBFF">name</span></span>
<span class="line"><span style="color:#E1E4E8">        - </span><span style="color:#9ECBFF">description</span></span>
<span class="line"><span style="color:#85E89D">      properties</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">        name</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">          title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Name</span></span>
<span class="line"><span style="color:#85E89D">          type</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">string</span></span>
<span class="line"><span style="color:#85E89D">          description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Unique name of the component</span></span>
<span class="line"><span style="color:#85E89D">          ui:field</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">EntityNamePicker</span></span>
<span class="line"><span style="color:#85E89D">          ui:autofocus</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">true</span></span>
<span class="line"><span style="color:#85E89D">        description</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">          title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Description</span></span>
<span class="line"><span style="color:#85E89D">          type</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">string</span></span>
<span class="line"><span style="color:#85E89D">          description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">A description for the component</span></span>
<span class="line"><span style="color:#85E89D">        owner</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">          title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Owner</span></span>
<span class="line"><span style="color:#85E89D">          type</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">string</span></span>
<span class="line"><span style="color:#85E89D">          description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Owner of the component</span></span>
<span class="line"><span style="color:#85E89D">          ui:field</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">OwnerPicker</span></span>
<span class="line"><span style="color:#85E89D">          ui:options</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">            allowedKinds</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">              - </span><span style="color:#9ECBFF">Group</span></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#85E89D">title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Choose a location</span></span>
<span class="line"><span style="color:#85E89D">      required</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">        - </span><span style="color:#9ECBFF">repoUrl</span></span>
<span class="line"><span style="color:#85E89D">      properties</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">        repoUrl</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">          title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Repository Location</span></span>
<span class="line"><span style="color:#85E89D">          type</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">string</span></span>
<span class="line"><span style="color:#85E89D">          ui:field</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">RepoUrlPicker</span></span>
<span class="line"><span style="color:#85E89D">          ui:options</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">            allowedHosts</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">              - </span><span style="color:#9ECBFF">github.com</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">  # This template is meant to be used on top of an existing template.</span></span>
<span class="line"><span style="color:#6A737D">  # By adding the following and fetching from an absolute URL you can</span></span>
<span class="line"><span style="color:#6A737D">  # add in the docs template</span></span>
<span class="line"><span style="color:#85E89D">  steps</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#85E89D">id</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">fetch</span></span>
<span class="line"><span style="color:#85E89D">      name</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Template Docs Skeleton</span></span>
<span class="line"><span style="color:#85E89D">      action</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">fetch:template</span></span>
<span class="line"><span style="color:#85E89D">      input</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">        url</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">./skeleton</span></span>
<span class="line"><span style="color:#85E89D">        values</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">          name</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ parameters.name }}</span></span>
<span class="line"><span style="color:#85E89D">          description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ parameters.description }}</span></span>
<span class="line"><span style="color:#85E89D">          destination</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ parameters.repoUrl | parseRepoUrl }}</span></span>
<span class="line"><span style="color:#85E89D">          owner</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ parameters.owner }}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#85E89D">id</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">publish</span></span>
<span class="line"><span style="color:#85E89D">      name</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Publish</span></span>
<span class="line"><span style="color:#85E89D">      action</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">publish:github</span></span>
<span class="line"><span style="color:#85E89D">      input</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">        allowedHosts</span><span style="color:#E1E4E8">: [</span><span style="color:#9ECBFF">'github.com'</span><span style="color:#E1E4E8">]</span></span>
<span class="line"><span style="color:#85E89D">        description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">This is ${{ parameters.name }}</span></span>
<span class="line"><span style="color:#85E89D">        repoUrl</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ parameters.repoUrl }}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">    - </span><span style="color:#85E89D">id</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">register</span></span>
<span class="line"><span style="color:#85E89D">      name</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Register</span></span>
<span class="line"><span style="color:#85E89D">      action</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">catalog:register</span></span>
<span class="line"><span style="color:#85E89D">      input</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">        repoContentsUrl</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ steps.publish.output.repoContentsUrl }}</span></span>
<span class="line"><span style="color:#85E89D">        catalogInfoPath</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">'/catalog-info.yaml'</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">  output</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">    links</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#E1E4E8">      - </span><span style="color:#85E89D">title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Repository</span></span>
<span class="line"><span style="color:#85E89D">        url</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ steps.publish.output.remoteUrl }}</span></span>
<span class="line"><span style="color:#E1E4E8">      - </span><span style="color:#85E89D">title</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Open in catalog</span></span>
<span class="line"><span style="color:#85E89D">        icon</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">catalog</span></span>
<span class="line"><span style="color:#85E89D">        entityRef</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{ steps.register.output.entityRef }}</span></span>
<span class="line"></span>

To learn more about the specific fields, read the following docs https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template

  1. Now create a skeleton directory at the same level as template.yaml. Inside the skeleton directory, create a README.md file with some template values. These template values will be overwritten in the first step defined in the template with id fetch.
<span class="line"><span style="color:#79B8FF;font-weight:bold"># ${{ values.name }}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">${{ values.description }}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8">Owned by ${{ values.owner }}</span></span>
<span class="line"></span>
  1. Lastly, next to README.md, create a catalog-info.yaml file with the following content:
<span class="line"><span style="color:#85E89D">apiVersion</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">backstage.io/v1alpha1</span></span>
<span class="line"><span style="color:#85E89D">kind</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">Component</span></span>
<span class="line"><span style="color:#85E89D">metadata</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">  name</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{values.name | dump}}</span></span>
<span class="line"><span style="color:#85E89D">  description</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{values.description | dump}}</span></span>
<span class="line"><span style="color:#85E89D">  annotations</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">    github.com/project-slug</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{values.destination.owner + "/" + values.destination.repo}}</span></span>
<span class="line"><span style="color:#85E89D">spec</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#85E89D">  type</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">documentation</span></span>
<span class="line"><span style="color:#85E89D">  lifecycle</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">experimental</span></span>
<span class="line"><span style="color:#85E89D">  owner</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">${{values.owner | dump}}</span></span>
<span class="line"></span>

This file will be used in automatically registering the newly created software components using the template you have just created.

At this point, the structure of the template directory should look like this:

test-docs-template/
	template.yaml
	skeleton/
		README.md
		catalog-info.yaml

It’s now time to import the template into your Backstage local instance and use it.

  1. Update your app-config.yaml in your Backstage app and add the following line under catalog.locations section.
<span class="line"><span style="color:#B392F0">catalog:</span></span>
<span class="line"><span style="color:#B392F0">  locations:</span></span>
<span class="line"><span style="color:#6A737D">    #....</span></span>
<span class="line"><span style="color:#B392F0">    -</span><span style="color:#9ECBFF"> type:</span><span style="color:#9ECBFF"> file</span></span>
<span class="line"><span style="color:#B392F0">      target:</span><span style="color:#9ECBFF"> /path/to/test-docs-template/template.yaml</span></span>
<span class="line"></span>

💡 NOTE: You can also use a relative path, relative to where the backend is running i.e. packages/backend/ in your Backstage app, not the root of the project.

  1. Restart your backend and now load the /create screen by clicking Create in the sidebar. You should be able to find your newly created Software Template.
New template on create page
  1. Click on choose, fill in the minimum details needed to publish and hit run. Make sure your integrations: section in app-config.yaml has all the necessary tokens to publish to GitHub, Gitlab, etc. If not, checkout the Integrations section in the Standing Up Backstage module.
Fill in details of the template Fill in details of the template
  1. In a few seconds, you can see the logs and find your component created and registered in the Software Catalog for you!
End result of using the template