Merge branch 'backstage:master' into feature/asyncapi3

This commit is contained in:
Fabrizio Lazzaretti
2024-01-30 14:16:06 +01:00
committed by GitHub
233 changed files with 3763 additions and 1137 deletions
+28
View File
@@ -474,6 +474,34 @@ Response type is JSON, on the form
]
```
### `GET /locations/{id}`
Gets a location by it's location ID.
Response type is JSON, on the form
```json
{
"id": "b9784c38-7118-472f-9e22-5638fc73bab0",
"target": "https://git.example.com/example-project/example-repository/blob/main/catalog-info.yaml",
"type": "url"
}
```
### `GET /locations/by-entity/{kind}/{namespace}/{name}`
Gets a location referring to a given entity.
Response type is JSON, on the form
```json
{
"id": "b9784c38-7118-472f-9e22-5638fc73bab0",
"target": "https://git.example.com/example-project/example-repository/blob/main/catalog-info.yaml",
"type": "url"
}
```
### `POST /locations`
Adds a location to be ingested by the catalog.
@@ -114,7 +114,7 @@ const extension = createExtension({
### Extension Data Uniqueness
Note that the key used in the output map, in this case `element`, is only used internally within the definition of the extension itself. That actual identifier for the data when consumed by other extensions is the ID of the reference, in this case `core.reactElement`. This means that you can not output multiple different values for the same extension data reference, as they would conflict with each other. That in turn makes overly generic extension data references a bad idea, for example a generic "string" type. Instead create separate references for each type of data that you want to share.
Note that the key used in the output map, in this case `element`, is only used internally within the definition of the extension itself. That actual identifier for the data when consumed by other extensions is the ID of the reference, in this case [`core.reactElement`](https://github.com/backstage/backstage/blob/916da47e8abdb880877daa18881eb8fdbb33e70a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts#L23). This means that you can not output multiple different values for the same extension data reference, as they would conflict with each other. That in turn makes overly generic extension data references a bad idea, for example a generic "string" type. Instead create separate references for each type of data that you want to share.
```tsx
const extension = createExtension({
@@ -160,7 +160,7 @@ const extension = createExtension({
## Extension Inputs
The Extension Data can be passed up to other extensions through their extension inputs. Similar to the outputs seen before, let's create an example an extension with a extension input:
The Extension Data can be passed up to other extensions through their extension inputs. Similar to the outputs seen before, let's create an example of an extension with a extension input:
```tsx
const navigationExtension = createExtension({
@@ -254,7 +254,7 @@ With the `inputs` not only the `output` of an extensions item is passed to the e
## Extension Configuration
With the `app-config.yaml` there is already the option to pass configuration to plugins or the app to e.g. define the `baseURL` of your app. For extensions this concept would be limiting as an extension can be independent of the plugin & initiated several times. Therefor we created a possibility to configure each extension individually through config. The extension config schema is created using the [`zod`](https://zod.dev/) library, which in addition to TypeScript type checking also provides runtime validation and coercion. If we continue with the example of the `navigationExtension` and now want it to contain a configurable title, we could make it available like the following:
With the `app-config.yaml` there is already the option to pass configuration to plugins or the app to e.g. define the `baseURL` of your app. For extensions this concept would be limiting as an extension can be independent of the plugin & initiated several times. Therefore we created a possibility to configure each extension individually through config. The extension config schema is created using the [`zod`](https://zod.dev/) library, which in addition to TypeScript type checking also provides runtime validation and coercion. If we continue with the example of the `navigationExtension` and now want it to contain a configurable title, we could make it available like the following:
```tsx
const navigationExtension = createExtension({
@@ -297,7 +297,7 @@ app:
With creating an extension by using `createExtension(...)` you have the advantage that the extension can be anything in your Backstage application. We realised that this comes with the trade-off of having to repeat boilerplate code for similar building blocks. Here extension creators come into play for covering common building blocks in Backstage like pages using `createPageExtension`, themes using the `createThemeExtension` or items for the navigation using `createNavItemExtension`.
If we follow the example from above all items of the navigation have similarities, like they all want to be attached to the same extension with the same input as well as rendering the same navigation item component. Therefor `createExtension` can be abstracted for this use case to `createNavItemExtension` and if we add the extension to the app it will end up in the right place & looks like we expect a navigation item to look.
If we follow the example from above all items of the navigation have similarities, like they all want to be attached to the same extension with the same input as well as rendering the same navigation item component. Therefore `createExtension` can be abstracted for this use case to `createNavItemExtension` and if we add the extension to the app it will end up in the right place & looks like we expect a navigation item to look.
```tsx
export const HomeNavIcon = createNavItemExtension({
@@ -14,7 +14,7 @@ Utility APIs are pieces of standalone functionality, interfaces that can be requ
A common example of a utility API is a client interface to interact with the backend part of a plugin, such as the catalog client. Any frontend plugin can then request an implementation of that interface to make requests through.
The following diagram shows a hypothetical application, which depends on two plugins and also provides some extra overrides. Note that both the plugins and the core framework provide utility APIs, and that they depended on each other. The app also chooses to use its overrides mechanism to supply a replacement implementation of one API, which takes precedence over the default one. Thus, all consumers of that API will be sure to get that new implementation provided to them.
The following diagram shows a hypothetical application, which depends on two plugins and also provides some extra overrides. Note that both the plugins and the core framework provide utility APIs, and that they depend on each other. The app also chooses to use its overrides mechanism to supply a replacement implementation of one API, which takes precedence over the default one. Thus, all consumers of that API will be sure to get that new implementation provided to them.
![frontend system utility apis diagram](../../assets/frontend-system/architecture-utility-apis.drawio.svg)
@@ -66,7 +66,7 @@ export default createPlugin({
});
```
In the example above we associated the `indexRouteRef` with the `catalogIndexPage` extension and provided both the route ref and page via the Catalog plugin. So, When this plugin is installed in the app, the index page will become associated with the newly created `RouteRef`, making it possible to use the route ref to navigate the page extension.
In the example above we associated the `indexRouteRef` with the `catalogIndexPage` extension and provided both the route ref and page via the Catalog plugin. So, when this plugin is installed in the app, the index page will become associated with the newly created `RouteRef`, making it possible to use the route ref to navigate the page extension.
It may seem unclear why we configure the `routes` option when creating a plugin as the route has already been passed to the extension. We do that to make it possible for other plugins to route to our page, which is explained in detail in the [binding routes](#binding-external-route-references) section.
@@ -70,7 +70,7 @@ describe('Entity details component', () => {
await renderInTestApp(
<TestApiProvider apis={[[catalogApiRef, catalogApiMock]]}>
<EntityDetails entitRef={entityRef} />
<EntityDetails entityRef={entityRef} />
</TestApiProvider>,
);
+1 -1
View File
@@ -52,7 +52,7 @@ As part of signing in with an identity resolver, a Backstage Token is issued con
The token is used to prove the identity of the user within the Backstage system, and is used throughout Backstage plugins to control access. It is important that the ownership resolution logic is consistent across the entire Backstage ecosystem, with no possibility of misinterpreting the ownership information.
For cross backend communication the Backstage Token is typically forwarded or in strict backend to backend communication without a user party the backend itself issues a service token based on a pre-shared secret which is then validated on the receiving end. There are no unique service identities tied to these tokens at this point, meaning the tokens can be used across all services in a Backstage installation, this is something that we aim to improve in the future.
For cross-backend communication, the Backstage Token is typically forwarded or, in strict backend-to-backend communication without a user party, the backend itself issues a service token based on a pre-shared secret which is then validated on the receiving end. There are no unique service identities tied to these tokens at this point, meaning the tokens can be used across all services in a Backstage installation. This is something that we aim to improve in the future.
Backstage also supports authentication through a proxy where the user identity is read from the incoming request from the proxy, which has been decorated by an authenticating reverse proxy such as [AWS ALB](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/). The following proxy auth providers verify the signature of incoming requests, and are therefore safe to deploy with direct access by users: `awsAlb`, `cfAccess`, and `gcpIap`. Providers like `oauth2Proxy` does not verify the incoming request and can therefore be spoofed by a malicious internal user to supply the `auth` backend with forged identity information. Its therefore highly recommended to restrict access to the `oauth2Proxy` endpoints, or use a different provider.
+1 -1
View File
@@ -39,7 +39,7 @@ Contributed by [@davidfestal](https://github.com/davidfestal) in [#18862](https:
### New Scaffolder action `gitlab:issues:create`
You can now create GitHub issues in your scaffolder flows! Contributed by [@elaine-mattos](https://github.com/elaine-mattos) in [#21929](https://github.com/backstage/backstage/pull/21929)
You can now create GitLab issues in your scaffolder flows! Contributed by [@elaine-mattos](https://github.com/elaine-mattos) in [#21929](https://github.com/backstage/backstage/pull/21929)
### New Scaffolder action `gitlab:repo:push`
+2 -2
View File
@@ -21,9 +21,9 @@ To switch a project to React 18, there are generally three changes that need to
// highlight-remove-next-line
"@types/react": "^17",
// highlight-remove-next-line
"@types/react": "^17",
"@types/react-dom": "^17",
// highlight-add-next-line
"@types/react-dom": "^18",
"@types/react": "^18",
// highlight-add-next-line
"@types/react-dom": "^18",
},