Merge branch 'backstage:master' into update-custom-permission-rule-doc

This commit is contained in:
Stanley Nicholl
2023-12-13 13:51:08 +00:00
committed by GitHub
727 changed files with 17598 additions and 3014 deletions
+2
View File
@@ -27,6 +27,8 @@ To add Okta authentication, you must create an Application from Okta:
- `Controlled access`: (select as appropriate)
- Click Save
The configuration examples provided above are suitable for local development. For a production deployment, substitute `http://localhost:7007` with the url that your Backstage instance is available at.
# Configuration
The provider configuration can then be added to your `app-config.yaml` under the
@@ -330,7 +330,7 @@ depends on the appropriate extension point and interacts with it.
```ts title="packages/backend/src/index.ts"
/* highlight-add-start */
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-end */
@@ -344,7 +344,7 @@ const catalogModuleCustomExtensions = createBackendModule({
catalog: catalogProcessingExtensionPoint,
// ... and other dependencies as needed
},
init({ catalog /* ..., other dependencies */ }) {
async init({ catalog /* ..., other dependencies */ }) {
// Here you have the opportunity to interact with the extension
// point before the plugin itself gets instantiated
catalog.addEntityProvider(new MyEntityProvider()); // just an example
@@ -399,7 +399,7 @@ depends on the appropriate extension point and interacts with it.
```ts title="packages/backend/src/index.ts"
/* highlight-add-start */
import { eventsExtensionPoint } from '@backstage/plugin-events-node';
import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha';
import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-end */
@@ -413,7 +413,7 @@ const eventsModuleCustomExtensions = createBackendModule({
events: eventsExtensionPoint,
// ... and other dependencies as needed
},
init({ events /* ..., other dependencies */ }) {
async init({ events /* ..., other dependencies */ }) {
// Here you have the opportunity to interact with the extension
// point before the plugin itself gets instantiated
events.addSubscribers(new MySubscriber()); // just an example
@@ -464,7 +464,7 @@ depends on the appropriate extension point and interacts with it.
```ts title="packages/backend/src/index.ts"
/* highlight-add-start */
import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node';
import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha';
import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-end */
@@ -478,7 +478,7 @@ const scaffolderModuleCustomExtensions = createBackendModule({
scaffolder: scaffolderActionsExtensionPoint,
// ... and other dependencies as needed
},
init({ scaffolder /* ..., other dependencies */ }) {
async init({ scaffolder /* ..., other dependencies */ }) {
// Here you have the opportunity to interact with the extension
// point before the plugin itself gets instantiated
scaffolder.addActions(new MyAction()); // just an example
@@ -9,8 +9,8 @@ This section will guide you through how to:
- [Create a basic documentation setup](#create-a-basic-documentation-setup)
- [Use any software template](#use-any-software-template)
- [Use the documentation template](#use-the-documentation-template)
- [Enable documentation for an already existing entity](#enable-documentation-for-an-already-existing-entity)
- [Create a standalone documentation](#create-a-standalone-documentation)
- [Writing and previewing your documentation](#writing-and-previewing-your-documentation)
## Prerequisites
@@ -41,23 +41,6 @@ default, we highly recommend you to set that up. Follow our how-to guide
[How to add documentation setup to your software templates](./how-to-guides.md#how-to-add-the-documentation-setup-to-your-software-templates)
to get started.
### Use the documentation template
There could be _some_ situations where you don't want to keep your docs close to
your code, but still want to publish documentation - for example, an onboarding
tutorial. For this use case, we have put together a documentation template. Your
Backstage instance should by default have a documentation template added. If
not, copy the catalog locations from the
[create-app template](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/app-config.yaml.hbs)
to add the documentation template. The template creates a component with
**only** TechDocs configuration and default markdown files, and is otherwise
empty.
![Documentation Template](../../assets/techdocs/documentation-template.png)
Create an entity from the documentation template and you will get the needed
setup for free.
### Enable documentation for an already existing entity
Prerequisites:
@@ -115,6 +98,56 @@ This is a basic example of documentation.
Commit your changes, open a pull request and merge. You will now get your
updated documentation next time you run Backstage!
### Create a standalone documentation
There could be _some_ situations where you don't want to keep your docs close to
your code, but still want to publish documentation - for example, an onboarding
tutorial. For this case, you can create a documentation component, which will be
published as a standalone part of TechDocs.
First, create an entity for your documentation. A minimal example could look like
this:
```yaml title="catalog-info.yaml"
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: a-unique-name-for-your-docs
annotations:
# this could also be `url:<url>` if the documentation isn't in the same location
backstage.io/techdocs-ref: dir:.
spec:
type: documentation
lifecycle: experimental
owner: user-or-team-name
```
Next, create the config file for [mkdocs](https://www.mkdocs.org/), which will be
used to parse your docs:
```yaml title="mkdocs.yml"
site_name: a-unique-name-for-your-docs
site_description: An informative description
plugins:
- techdocs-core
nav:
- Getting Started: index.md
```
Finally, add your index.md Markdown file, in a folder named `docs/` with your desired
documentation in Markdown. Your file structure should now look like this:
```
your-great-documentation/
docs/
index.md
catalog-info.yaml
mkdocs.yml
```
Last but not least, register your component in the software catalog using
[one of several options](../software-catalog/index.md#adding-components-to-the-catalog).
## Writing and previewing your documentation
Using the [techdocs-cli](https://github.com/backstage/backstage/tree/master/packages/techdocs-cli) you can
+12
View File
@@ -504,6 +504,18 @@ folder (/docs) or replace the content in this file.
Done! You now have support for TechDocs in your own software template!
### Prevent download of Google fonts
If your Backstage instance does not have internet access, the generation will fail. TechDocs tries to download the Roboto font from Google. You can disable it by adding the following lines to mkdocs.yaml:
```yaml
theme:
name: material
font: false
```
> Note: The addition `name: material` is necessary. Otherwise it will not work
## How to enable iframes in TechDocs
TechDocs uses the [DOMPurify](https://github.com/cure53/DOMPurify) library to
@@ -18,6 +18,10 @@ Each extensions has a number of different properties that define how it behaves
### ID
<!--
Update this to be 3 different sections: name, kind and namespace
-->
The ID of an extension is used to uniquely identity it, and it should ideally by unique across the entire Backstage ecosystem. For each frontend app instance there can only be a single extension for any given ID. Installing multiple extensions with the same ID will either result in an error or one of the extensions will override the others. The ID is also used to reference the extensions from other extensions, in configuration, and in other places such as developer tools and analytics.
### Output
@@ -85,20 +89,64 @@ TODO
## Extension Inputs
TODO
<!--
## Configuration
Introduce the concept of extension inputs and how they use extension data to reference types just like outputs
TODO
Show how to use the `createExtensionInput` API to create an input for an extension.
## Configuration Schema
- Example of creating a single input
TODO
Talk about different types of inputs, singleton vs array + optional vs required.
- Example of creating an optional singleton input - not the value is no longer an array
Talk about the shape of the input values and that you have access to the AppNode node in addition to the data, but discourage use of AppNode.
- Example of how to access the AppNode next to the input data
-->
## Extension Configuration
<!--
Introduce the concept of extension configuration, highlight that it's different from app config
Show how to define a configuration schema for an extension, talk about it using zod (link to zod), in general explain everything there is to know about the schema
- Example that creates a configuration schema for an extension
Show how to provide configuration for an extension - keep this part short, and instead link to the architecture section that talks about writing configuration
- One example of a YAML configurations for the above extension
-->
## Extension Creators
TODO
<!--
Introduce the concept of extension creators, talk about how they are used to provide an opinionated way of creating extensions for specific use cases. Mention a few of the built-in creators, link to the reference section on built-in extension kinds (TBD).
- Example of using an existing extension creator to create an extension
Explain that each extension creator creates a specific "kind" of extensions - introduce the concept of extension kinds. Show an example of how the kind is used to build up the ID.
- Example of creating a new extension creator for creating a specific kind of extension
Explain that extension creators should be exported from library packages (`-react`) rather than plugin packages.
-->
## Extension Boundary
TODO
<!--
Introduce the need for extension specific React contexts, for example error boundaries and analytics.
Any React elements that are rendered by extension creators should be wrapped in the `ExtensionBoundary`
- Example of how to use the `ExtensionBoundary` in an extension creator
-->
@@ -7,3 +7,87 @@ description: Frontend plugins
---
> **NOTE: The new frontend system is in a highly experimental phase**
## Introduction
<!--
Introduce frontend plugins and how each of them is shipped as a separate package. Highlight that each package should only export a single plugin instance.
-->
## Creating a Plugin
<!--
How to create a simple plugin
-->
```ts
export const myPlugin = createPlugin({
id: 'my-plugin',
});
```
<!--
Note that this plugin is useless in itself, and you need to provide extra options to make it useful, in particular extensions.
-->
### Plugin ID
<!--
link to relevant docs
-->
### Plugin Extensions
<!--
- Example of how this option is used in `createPlugin`
link to relevant docs
-->
### Plugin Routes
<!--
- Example of how this option is used in `createPlugin`
link to relevant docs
-->
### Plugin External Routes
<!--
- Example of how this option is used in `createPlugin`
link to relevant docs
-->
### Plugin Feature Flags
<!--
- Example of how this option is used in `createPlugin`
link to relevant docs
-->
## Installing a Plugin in an App
<!--
Quick intro, but link back to app docs for more details
-->
@@ -7,3 +7,41 @@ description: Frontend extension overrides
---
> **NOTE: The new frontend system is in a highly experimental phase**
## Introduction
<!--
Introduce extension overrides and how they can be shipped in separate packages but also internally within a project too.
Talk about how extension overrides
-->
## Creating a Extension Override
<!--
How to create an extension override and export it from a package.A
- Example using the default exports
You can also create them directly withing the app for local overrides.
- Example of installing an override directly into an app
Mention that in can still be a good idea to split your overrides out into separate packages in large projects. But it's up to you to decide how to group the extensions into extension overrides.
-->
## Overriding Existing Extensions
<!--
To override an existing extension you need to provide an extension through an extension override that has the same ID as the existing extension. That is, all of kind, namespace and name must match the extension you want to override.
This means that you typically need to provide an explicit namespace when overriding extensions from a plugin.
- Example of how to create an extension override for an existing extension from some plugin
-->
@@ -9,3 +9,142 @@ description: Frontend routes
> **NOTE: The new frontend system is in a highly experimental phase**
See [routing system docs](../../plugins/composability.md#routing-system)
## Introduction
<!--
Routing system of backstage - what's the prupose
Explain the indirection needed to route between plugins. For example what do we do if plugin A want to link to plugin B, but plugin B is not installed? How can we support this in an app?
How can we let an integrator decice whether plugin A should link to plugin B or plugin C? (with some good real-work examples, e.g. catalog -> scaffolder create page / catalog-import plugin)
-->
## Route References
<!--
Explain what a route reference is - then explain how it solves the problem outlined above.
Explain that we use route references to represent a path in an app. Each referenced path is unique for each app, but in different apps the same route ref might point to different paths.
-->
### Creating a Route Reference
<!--
Example using `createRouteRef` + passing it to a page extension
-->
### Using a Route Reference
<!--
Example using `useRouteRef` in a component
-->
### Route Path Parameters
<!--
Example using path parameters, both createRouteRef and useRouteRef
-->
### Providing Route References to Plugins
<!--
Show how to provide routes through createPlugin({ routes: })
-->
## External Router References
<!--
Explain the need for external route refs
Explain all of create, use and provide
-->
### Binding External Route References
<!--
Example using `createApp`
Example using config
-->
### Optional External Route References
<!--
Talk about how external routes must be bound or app will crash, but you can make them optional too
useRouteRef can return undefined for optional external routes
-->
## Sub Route References
<!--
Explain the need for external route refs - both as a tool for routing within a plugin, but also allow external routes to point to sub routes
Talk about how sub routes declare an explicit path - can't be decided by the app/integrator. They are hard-coded in the plugin in parallel to the internal routing structure of the plugin itself.
Explain all of create, use and provide
-->
```ts
/*
Some examples
export const indexPageRouteRef = createRouteRef()
export const catalogPlugin = createPlugin({
id: 'catalog,
routes: {
index: indexPageRouteRef,
},
})
// in catalog plugin
import {indexPageRouteRef} from '../../routes
const link = useRouteRef(indexPageRouteRef)
// scaffolder
export const catalogIndexPageRouteRef = createExternalRouteRef({
defaultTarget: 'catalog/index',
})
export const scaffolderPlugin = createPlugin({
id: 'scaffolder,
externalRoutes: {
catalogIndex: catalogIndexPageRouteRef,
},
})
import {catalogIndexPageRouteRef} from '../../routes
const link = useRouteRef(catalogIndexPageRouteRef)
// app
import {catalogPlugin} from '@backstage/plugin-catalog'
const app = createApp({
bindRoutes({bind}) {
bind(scaffolderPlugin, {
catalogIndex: catalogPlugin.routes.index,
})
},
})
*/
```
@@ -0,0 +1,17 @@
---
id: references
title: Value References
sidebar_label: Value References
# prettier-ignore
description: Value References
---
> **NOTE: The new frontend system is in a highly experimental phase**
<!--
Describe the generic concept of references as used for ApiRef, ExtensionDataRef, RouteRef, ComponentRef, etc.
Talk about the usage and how helper functions allows type-safe access to the values that the references represent.
-->
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+69
View File
@@ -0,0 +1,69 @@
---
id: setup-opentelemetry
title: Setup OpenTelemetry
description: Tutorial to setup OpenTelemetry metrics and traces exporters in Backstage
---
Backstage uses [OpenTelemetery](https://opentelemetry.io/) to instrument its components by reporting traces and metrics.
This tutorial shows how to setup exporters in your Backstage backend package. For demonstration purposes we will use the simple console exporters.
## Install dependencies
We will use the OpenTelemetry Node SDK and the `auto-instrumentations-node` packages.
Backstage packages, such as the catalog, uses the OpenTelemetry API to send custom traces and metrics.
The `auto-instrumentations-node` will automatically create spans for code called in libraries like Express.
```bash
yarn --cwd packages/backend add @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/sdk-metrics
```
## Configure
In your `packages/backend/src` folder, create an `instrumentation.ts` file.
```typescript
import { NodeSDK } from '@opentelemetry/sdk-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import {
PeriodicExportingMetricReader,
ConsoleMetricExporter,
} from '@opentelemetry/sdk-metrics';
const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
metricReader: new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
```
In the `index.ts`, import this file **at the beginning**:
```typescript
import './instrumentation'; // Setup the OpenTelemetry instrumentation
// other imports and backend init...
```
It's important to setup the NodeSDK and the automatic instrumentation **before** importing any library.
## Run Backstage
You can now start your Backstage instance as usual, using `yarn dev`.
When the backend is started, you should see in your console traces and metrics emitted by OpenTelemetry.
Of course in production you probably won't use the console exporters but instead send traces and metrics to an OpenTelemetry Collector using [OTLP exporters](https://opentelemetry.io/docs/instrumentation/js/exporters/).
## References
- [Getting started with OpenTelemetry Node.js](https://opentelemetry.io/docs/instrumentation/js/getting-started/nodejs/)
- [OpenTelemetry NodeSDK API](https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_node.NodeSDK.html)