Merge branch 'master' into feat/myGroupsPickerPresentationApi

This commit is contained in:
Julien
2024-08-12 09:03:26 +02:00
666 changed files with 20474 additions and 4077 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': patch
---
Add access restrictions to the JWKS external access method config schema
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': patch
---
Fixing issue with extension blueprints `inputs` merging.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Fixed a bug in `DefaultTableOutputs` where output elements overlapped on smaller screen sizes
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': patch
---
The entity relation cards available for the new frontend system via `/alpha` now have more accurate and granular default filters.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-plugin-api': patch
---
Added `createBackendFeatureLoader`, which can be used to create an installable backend feature that can in turn load in additional backend features in a dynamic way.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': patch
---
Added support for using the `params` in other properties of the `createExtensionBlueprint` options by providing a callback.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-test-utils': patch
---
Added new APIs for testing extensions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': patch
---
Added support for the latest version of `BackendFeature`s from `@backstage/backend-plugin-api`, including feature loaders.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
Internal updates to support latest version of `BackendFeauture`s from `@backstage/backend-plugin-api`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-scaffolder-node': patch
---
Add support for status filtering in scaffolder tasks endpoint
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-permission-common': patch
---
Add the MetadataResponse type from @backstage/plugin-permission-node, since this
type might be used in frontend code.
+43
View File
@@ -0,0 +1,43 @@
---
'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch
'@backstage/plugin-auth-backend-module-cloudflare-access-provider': patch
'@backstage/plugin-search-backend-module-stack-overflow-collator': patch
'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch
'@backstage/plugin-catalog-backend-module-bitbucket-server': patch
'@backstage/plugin-auth-backend-module-microsoft-provider': patch
'@backstage/plugin-auth-backend-module-aws-alb-provider': patch
'@backstage/plugin-scaffolder-backend-module-bitbucket': patch
'@backstage/plugin-scaffolder-backend-module-gerrit': patch
'@backstage/plugin-scaffolder-backend-module-sentry': patch
'@backstage/plugin-catalog-backend-module-puppetdb': patch
'@backstage/plugin-scaffolder-backend-module-gitea': patch
'@backstage/plugin-catalog-backend-module-msgraph': patch
'@backstage/plugin-search-backend-module-techdocs': patch
'@backstage/plugin-catalog-backend-module-gerrit': patch
'@backstage/plugin-catalog-backend-module-github': patch
'@backstage/plugin-catalog-backend-module-gitlab': patch
'@backstage/plugin-search-backend-module-explore': patch
'@backstage/plugin-catalog-backend-module-azure': patch
'@backstage/plugin-notifications-backend': patch
'@backstage/plugin-kubernetes-backend': patch
'@backstage/plugin-notifications-node': patch
'@backstage/plugin-permission-backend': patch
'@backstage/backend-defaults': patch
'@backstage/backend-app-api': patch
'@backstage/plugin-devtools-backend': patch
'@backstage/plugin-techdocs-backend': patch
'@backstage/backend-common': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-kubernetes-node': patch
'@backstage/plugin-signals-backend': patch
'@backstage/config-loader': patch
'@backstage/plugin-proxy-backend': patch
'@backstage/plugin-auth-backend': patch
'@backstage/create-app': patch
'@backstage/plugin-app-backend': patch
'@backstage/plugin-auth-node': patch
'@backstage/cli': patch
---
Make sure node-fetch is version 2.7.0 or greater
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch
---
Added autocompletion support for resource `branches`
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-azure': patch
---
Added examples for publish:azure action and updated its test cases
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/plugin-permission-node': patch
---
The MetadataResponse type has been moved to @backstage/plugin-permission-common
to match the recent move of MetadataResponseSerializedRule, and should be
imported from there going forward. To avoid an immediate breaking change, this
type is still re-exported from this package, but is marked as deprecated and
will be removed in a future release.
+8
View File
@@ -0,0 +1,8 @@
---
'@backstage/frontend-test-utils': patch
'@backstage/frontend-app-api': patch
'@backstage/core-compat-api': patch
'@backstage/plugin-app-visualizer': patch
---
Updated usage of `useRouteRef`, which can now always return `undefined`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Switched the `process` polyfill to use `require.resolve` for greater compatability.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
---
Added test cases for gitlab:issues:create examples
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Allow for more granular control of TechDocsReaderPage styling. Theme overrides can now be provided to TechDocs without affecting the theme in other areas of Backstage.
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/plugin-search-backend-node': patch
'@backstage/plugin-search-backend': patch
'@backstage/plugin-search-common': patch
'@backstage/plugin-search-react': patch
'@backstage/plugin-search': patch
---
Fix package metadata
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/backend-plugin-api': patch
'@backstage/backend-defaults': patch
---
The `SchedulerService` now allows tasks with `frequency: { trigger: 'manual' }`. This means that the task will not be scheduled, but rather run only when manually triggered with `SchedulerService.triggerTask`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-github': patch
---
Added examples for github:repo:create action and improved test cases
+26
View File
@@ -0,0 +1,26 @@
---
'@backstage/backend-plugin-api': patch
---
Added `createBackendFeatureLoader`, which can be used to programmatically select and install backend features.
A feature loader can return an list of features to be installed, for example in the form on an `Array` or other for of iterable, which allows for the loader to be defined as a generator function. Both synchronous and asynchronous loaders are supported.
Additionally, a loader can depend on services in its implementation, with the restriction that it can only depend on root-scoped services, and it may not override services that have already been instantiated.
```ts
const searchLoader = createBackendFeatureLoader({
deps: {
config: coreServices.rootConfig,
},
*loader({ config }) {
// Example of a custom config flag to enable search
if (config.getOptionalString('customFeatureToggle.search')) {
yield import('@backstage/plugin-search-backend/alpha');
yield import('@backstage/plugin-search-backend-module-catalog/alpha');
yield import('@backstage/plugin-search-backend-module-explore/alpha');
yield import('@backstage/plugin-search-backend-module-techdocs/alpha');
}
},
});
```
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-tasks': patch
---
The `PluginTaskScheduler` now allows tasks with `frequency: { trigger: 'manual' }`. This means that the task will not be scheduled, but rather run only when manually triggered with `PluginTaskScheduler.triggerTask`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': minor
---
Introduces the HasSubdomainsCard component that displays the subdomains of a given domain
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': patch
---
Update the `ServiceRegister` implementation to enable registering multiple service implementations for a given service ref.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications-backend': patch
---
Allow using notifications without users in the catalog
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-auth-node': minor
---
**BREAKING**: Sign-in resolvers configured via `.signIn.resolvers` now take precedence over sign-in resolvers passed to `signInResolver` option of `createOAuthProviderFactory`. This effectively makes sign-in resolvers passed via the `signInResolver` the default one, which you can then override through configuration.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': patch
---
Add support for accessing extensions definitions provided by a plugin via `plugin.getExtension(...)`. For this to work the extensions must be defined using the v2 format, typically using an extension blueprint.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
TechDocs redirect feature now includes a notification to the user before they are redirected.
+39
View File
@@ -190,41 +190,62 @@
"@backstage/plugin-techdocs-common": "0.0.0"
},
"changesets": [
"angry-dolphins-camp",
"big-eagles-grab",
"blue-pumas-cheer",
"breezy-jeans-tie",
"breezy-rings-fly",
"bright-donkeys-buy",
"bright-trainers-brake",
"calm-crabs-drop",
"chilly-days-peel",
"chilly-trains-sleep",
"clever-pans-brake",
"cool-insects-remember",
"cool-schools-vanish",
"create-app-1722413762",
"cuddly-zebras-crash",
"curvy-pillows-joke",
"cyan-shrimps-push",
"dry-squids-tap",
"dull-ghosts-double",
"early-trees-dance",
"eighty-emus-leave",
"eighty-jokes-deny",
"eighty-mirrors-flow",
"fair-hairs-mix",
"fair-pumas-hang",
"fast-bulldogs-relax",
"few-wasps-hug",
"flat-plums-grow",
"forty-ties-agree",
"forty-ties-disagree",
"friendly-cherries-applaud",
"friendly-chicken-cry",
"friendly-feet-refuse",
"gentle-dryers-smile",
"good-steaks-report",
"green-planets-reflect",
"grumpy-owls-suffer",
"healthy-timers-divide",
"heavy-numbers-love",
"hip-fishes-guess",
"hip-hairs-exist",
"khaki-lamps-peel",
"late-games-protect",
"light-pianos-exercise",
"little-bulldogs-guess",
"little-suns-fly",
"mean-apricots-perform",
"metal-planes-nail",
"metal-rice-call",
"mighty-apricots-taste",
"mighty-dolls-retire",
"mighty-geckos-kiss",
"modern-parrots-protect",
"neat-bears-divide",
"neat-gifts-join",
"neat-socks-cheer",
"new-scissors-try",
"nice-peas-retire",
"nine-cherries-decide",
@@ -236,16 +257,26 @@
"orange-gifts-protect",
"pink-gorillas-brake",
"plenty-tools-exist",
"purple-carrots-crash",
"quick-roses-juggle",
"rare-foxes-compete",
"red-radios-promise",
"renovate-147ac48",
"renovate-f04beb1",
"rich-mugs-dress",
"selfish-bees-think",
"seven-eggs-admire",
"shaggy-dodos-applaud",
"shy-games-poke",
"shy-waves-share",
"silly-candles-sin",
"silly-cycles-tan",
"six-rats-kick",
"slow-ducks-rush",
"slow-ligers-drum",
"slow-toes-jog",
"small-bottles-cough",
"small-ears-poke",
"small-spoons-shout",
"smooth-countries-relate",
"soft-gorillas-refuse",
@@ -258,15 +289,23 @@
"sweet-oranges-buy",
"swift-kings-sparkle",
"tall-snakes-fix",
"tasty-ads-rescue",
"thick-hotels-know",
"thirty-adults-grab",
"thirty-paws-hope",
"tiny-oranges-pretend",
"tough-goats-hang",
"tough-lies-repair",
"tricky-ducks-juggle",
"two-emus-work",
"violet-jokes-wave",
"warm-monkeys-marry",
"wicked-bobcats-teach",
"wild-eggs-exist",
"wise-spiders-walk",
"witty-bears-behave",
"witty-geese-battle",
"witty-timers-marry",
"young-games-visit",
"young-peaches-shake"
]
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
Update the `ServiceFactoryTester` to be able to test services that enables multi implementation installation.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Fix undefined in the title of Scaffolder Runs on the page load
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-api-docs': patch
---
Updated dependency `@graphiql/react` to `^0.23.0`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-plugin-api': patch
---
Fixed a type issue where plugin and modules depending on multiton services would not receive the correct type.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs-backend': patch
---
Update configuration schema to match actual behavior
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications-backend-module-email': patch
---
Add support for stream transport for debugging purposes
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': patch
---
Update the `UrlReader` service to depends on multiple instances of `UrlReaderFactoryProvider` service.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
TechDocs now supports the `mkdocs-redirects` plugin. Redirects defined using the `mkdocs-redirect` plugin will be handled automatically in TechDocs. Redirecting to external urls is not supported. In the case that an external redirect url is provided, TechDocs will redirect to the current documentation site home.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-kubernetes-backend': patch
---
Add `kubernetes.clusterLocatorMethods[].clusters[].customResources` to the configuration schema.
This was already documented and supported by the plugin.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Included permission config and enabled it out of the box
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Internal type refactor.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': patch
---
Support merging of `inputs` in extension blueprints, but stop merging `output`. In addition, the original factory in extension blueprints now returns a data container that both provides access to the returned data, but can also be forwarded as output.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-compat-api': patch
---
Both `compatWrapper` and `convertLegacyRouteRef` now support converting from the new system to the old.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Fix null check in `isJsonObject` utility function for scaffolder review state component
+58
View File
@@ -0,0 +1,58 @@
---
'@backstage/backend-plugin-api': minor
---
The `createServiceRef` function now accepts a new boolean `multiple` option. The `multiple` option defaults to `false` and when set to `true`, it enables that multiple implementation are installed for the created service ref.
We're looking for ways to make it possible to augment services without the need to replace the entire service.
Typical example of that being the ability to install support for additional targets for the `UrlReader` service without replacing the service itself. This achieves that by allowing us to define services that can have multiple simultaneous implementation, allowing the `UrlReader` implementation to depend on such a service to collect all possible implementation of support for external targets:
```diff
// @backstage/backend-defaults
+ export const urlReaderFactoriesServiceRef = createServiceRef<ReaderFactory>({
+ id: 'core.urlReader.factories',
+ scope: 'plugin',
+ multiton: true,
+ });
...
export const urlReaderServiceFactory = createServiceFactory({
service: coreServices.urlReader,
deps: {
config: coreServices.rootConfig,
logger: coreServices.logger,
+ factories: urlReaderFactoriesServiceRef,
},
- async factory({ config, logger }) {
+ async factory({ config, logger, factories }) {
return UrlReaders.default({
config,
logger,
+ factories,
});
},
});
```
With that, you can then add more custom `UrlReader` factories by installing more implementations of the `urlReaderFactoriesServiceRef` in your backend instance. Something like:
```ts
// packages/backend/index.ts
import { createServiceFactory } from '@backstage/backend-plugin-api';
import { urlReaderFactoriesServiceRef } from '@backstage/backend-defaults';
...
backend.add(createServiceFactory({
service: urlReaderFactoriesServiceRef,
deps: {},
async factory() {
return CustomUrlReader.factory;
},
}));
...
```
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/frontend-plugin-api': minor
---
**BREAKING**: All types of route refs are always considered optional by `useRouteRef`, which means the caller must always handle a potential `undefined` return value. Related to this change, the `optional` option from `createExternalRouteRef` has been removed, since it is no longer necessary.
This is released as an immediate breaking change as we expect the usage of the new route refs to be extremely low or zero, since plugins that support the new system will still use route refs and `useRouteRef` from `@backstage/core-plugin-api` in combination with `convertLegacyRouteRef` from `@backstage/core-compat-api`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': patch
---
Avoid excessive numbers of error listeners on cache clients
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications': minor
---
By default, set notification as read when opening snackbar or web notification link
+34
View File
@@ -0,0 +1,34 @@
---
'@backstage/frontend-plugin-api': patch
'@backstage/frontend-test-utils': patch
---
Added support for being able to override extension definitions.
```tsx
const TestCard = EntityCardBlueprint.make({
...
});
TestCard.override({
// override attachment points
attachTo: { id: 'something-else', input: 'overridden' },
// extend the config schema
config: {
schema: {
newConfig: z => z.string().optional(),
}
},
// override factory
*factory(originalFactory, { inputs, config }){
const originalOutput = originalFactory();
yield coreExentsionData.reactElement(
<Wrapping>
{originalOutput.get(coreExentsionData.reactElement)}
</Wrapping>
);
}
});
```
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-github': patch
---
Added examples for action github:pages and improved its test cases
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-search-backend-node': patch
'@backstage/plugin-catalog-node': patch
---
Explicit declare if the service ref accepts `single` or `multiple` implementations.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-test-utils': patch
---
Deprecate existing `ExtensionCreators` in favour of their new Blueprint counterparts.
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/frontend-test-utils': patch
---
Refactor `.make` method on Blueprints into two different methods, `.make` and `.makeWithOverrides`.
When using `createExtensionBlueprint` you can define parameters for the factory function, if you wish to take advantage of these parameters you should use `.make` when creating an extension instance of a Blueprint. If you wish to override more things other than the standard `attachTo`, `name`, `namespace` then you should use `.makeWithOverrides` instead.
`.make` is reserved for simple creation of extension instances from Blueprints using higher level parameters, whereas `.makeWithOverrides` is lower level and you have more control over the final extension.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': minor
---
Added field extension `RepoBranchPicker` that supports autocompletion for Bitbucket
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': patch
---
Added configuration for the `packages` options to config schema
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs-node': patch
---
Fix TechDocs Edit URL for nested docs
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-sentry': patch
---
Added test cases for sentry:project:create examples
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Fixed issue where header styles were incorrectly generated when themes used CSS variables to define font size.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
Entity page extensions created for the new frontend system via the `/alpha` exports will now be enabled by default.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications-backend-module-email': patch
---
Notification email processor supports allowing or denying specific email addresses from receiving notifications
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-bitbucket-cloud-common': patch
---
Added method `listBranchesByRepository` to `BitbucketCloudClient`
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/catalog-model': minor
---
Introduce an optional spec.type attribute on the Domain and System entity kinds
@@ -245,6 +245,7 @@ Monorepo
monorepos
msgraph
msw
multiton
mutex
mutexes
mysql
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
- run: yarn build-storybook
- uses: chromaui/action@5991575112b472a4fa85429f29cc17e2fb83a2a2 # v11
- uses: chromaui/action@fdbe7756d4dbf493e2fbb822df73be7accd07e1c # v11
with:
token: ${{ secrets.GITHUB_TOKEN }}
# projectToken intentionally shared to allow collaborators to run Chromatic on forks
+1 -1
View File
@@ -193,7 +193,7 @@ backend.add(import('@backstage/plugin-auth-backend-module-github-provider'));
backend.add(customAuth);
```
Check out [the naming patterns article](../backend-system/architecture/07-naming-patterns.md) for what rules
Check out [the naming patterns article](../backend-system/architecture/08-naming-patterns.md) for what rules
apply regarding how to form valid IDs. In this example we also put the module
declaration directly in `packages/backend/src/index.ts` but that's just for
simplicity. You can place it anywhere you like, including in other packages, and
@@ -38,7 +38,7 @@ export const fooServiceRef = createServiceRef<FooService>({
The `fooServiceRef` that we create above should be exported, and can then be used to declare a dependency on the `FooService` interface and receive an implementation of it at runtime.
When creating a service reference you need to give it an ID. This ID needs to be globally unique, and should generally be of the format `'<pluginId>.<serviceName>'`. For more naming patterns surrounding services, see the [naming patterns](./07-naming-patterns.md#services) page.
When creating a service reference you need to give it an ID. This ID needs to be globally unique, and should generally be of the format `'<pluginId>.<serviceName>'`. For more naming patterns surrounding services, see the [naming patterns](./08-naming-patterns.md#services) page.
A note on naming: the frontend and backend systems intentionally use the separate names "APIs" and "Services" for concepts that are quite similar. This is to avoid confusion between the two, both in documentation and discussion, but also in code. While the two systems are quite similar, they are not identical, and they can't be used interchangeably.
@@ -10,7 +10,7 @@ Plugins provide the actual base features of a Backstage backend. Each plugin ope
## Defining a Plugin
Plugins are created using the `createBackendPlugin` function, and should typically be exported from a plugin package. All plugins must have an ID and a `register` method, where the ID matches the plugin ID in the package name, without the `-backend` suffix. See also the [dedicated section](./07-naming-patterns.md) about proper naming patterns.
Plugins are created using the `createBackendPlugin` function, and should typically be exported from a plugin package. All plugins must have an ID and a `register` method, where the ID matches the plugin ID in the package name, without the `-backend` suffix. See also the [dedicated section](./08-naming-patterns.md) about proper naming patterns.
```ts
// plugins/example-backend/src/plugin.ts
@@ -52,7 +52,7 @@ This allows you to install the module in your backend instance by just referenci
```ts
backend.add(
import('backstage-plugin-catalog-backend-module-example-processor'),
import('@internal/backstage-plugin-catalog-backend-module-example-processor'),
);
```
@@ -0,0 +1,101 @@
---
id: feature-loaders
title: Backend Feature Loaders
sidebar_label: Feature Loaders
# prettier-ignore
description: Backend feature loaders
---
Backend feature loaders are used to programmatically select and install features in a Backstage backend. They can service a wide range of use cases, such as enabling or disabling features based on static configuration, dynamically load features at runtime, or conditionally load features based on the state of a system.
Feature loaders are defined using the `createBackendFeatureLoader` function, exported by `@backstage/backend-plugin-api`. It accepts a `loader` function, as well as an optional `deps` object for declaring service dependencies. Unlike plugins and modules, feature loaders are limited to only depending on root-scoped services, but that still allows access to for example the [root config](../core-services/root-config.md) and [root logger](../core-services/root-logger.md) services.
The `loader` function can be defined in many different ways, with the main requirement being that it returns a list of `BackendFeature`s in some form. A backend feature is the kind of object that you can pass to `backend.add(...)`, for example services factories, plugins, modules, or even other feature loaders. The `loader` function can be synchronous or asynchronous, and can be defined as a generator function to allow for more complex logic.
## Examples
The following are a few example of how feature loaders can be used:
### Simple list of features
A feature loader can simply return a list of features to be installed:
```ts
export default createBackendFeatureLoader({
loader() {
return [
import('@backstage/plugin-search-backend/alpha'),
import('@backstage/plugin-search-backend-module-catalog/alpha'),
import('@backstage/plugin-search-backend-module-explore/alpha'),
import('@backstage/plugin-search-backend-module-techdocs/alpha'),
];
},
});
```
It can also encapsulate a collection of custom features:
```ts
export default createBackendFeatureLoader({
// Async loader is fine too
async loader() {
return [
createBackendPlugin({
...
}),
createBackendModule({
...
}),
]
},
});
```
### Conditional loading
A feature loader can access root-scoped services, such as the config service. This allows for conditional loading of features based on configuration. It is often convenient to use a generator function for this purpose:
```ts
export default createBackendFeatureLoader({
deps: {
config: coreServices.rootConfig,
},
// The `*` in front of the function name makes it a generator function
*loader({ config }) {
// Example of a custom config flag to enable search
if (config.getOptionalString('customFeatureToggle.search')) {
yield import('@backstage/plugin-search-backend/alpha');
yield import('@backstage/plugin-search-backend-module-catalog/alpha');
yield import('@backstage/plugin-search-backend-module-explore/alpha');
yield import('@backstage/plugin-search-backend-module-techdocs/alpha');
}
},
});
```
### Dynamic logic
A feature loader can also be asynchronous, and for example fetch data from an external source to determine which features to load:
```ts
export default createBackendFeatureLoader({
// The `async *` in front of the function name makes it an async generator function.
async *loader() {
const localMetadata = await readMetadataFromDisk();
if (localMetadata.enableSearch) {
yield import('@backstage/plugin-search-backend/alpha');
yield import('@backstage/plugin-search-backend-module-catalog/alpha');
const remoteMetadata = await fetchMetadata();
if (remoteMetadata.enableExplore) {
yield import('@backstage/plugin-search-backend-module-explore/alpha');
}
if (remoteMetadata.enableTechDocs) {
yield import('@backstage/plugin-search-backend-module-techdocs/alpha');
}
}
},
});
```
@@ -68,7 +68,7 @@ that's specific to your plugin. In the example above, the logger might tag
messages with your plugin ID, and the HTTP router might prefix API routes with
your plugin ID, depending on the implementation used.
See [the article on naming patterns](../architecture/07-naming-patterns.md) for
See [the article on naming patterns](../architecture/08-naming-patterns.md) for
details on how to best choose names/IDs for plugins and related backend system
items.
@@ -124,7 +124,7 @@ export const catalogModuleExampleCustomProcessor = createBackendModule({
export { catalogModuleExampleCustomProcessor as default } from './module';
```
See [the article on naming patterns](../architecture/07-naming-patterns.md) for
See [the article on naming patterns](../architecture/08-naming-patterns.md) for
details on how to best choose names/IDs for modules and related backend system
items.
@@ -17,7 +17,8 @@ The following example is how you can override the root logger service to add add
```ts
import { coreServices } from '@backstage/backend-plugin-api';
import { WinstonLogger } from '@backstage/backend-app-api';
import { WinstonLogger } from '@backstage/backend-defaults/rootLogger';
import { createConfigSecretEnumerator } from '@backstage/backend-defaults/rootConfig';
const backend = createBackend();
@@ -43,6 +44,12 @@ backend.add(
transports: [new transports.Console()],
});
const secretEnumerator = await createConfigSecretEnumerator({
logger,
});
logger.addRedactions(secretEnumerator(config));
config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));
return logger;
},
}),
@@ -1243,6 +1243,18 @@ system belongs to, e.g. `artists`. This field is optional.
| --------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- |
| [`Domain`](#kind-domain) (default) | Same as this entity, typically `default` | [`partOf`, and reverse `hasPart`](well-known-relations.md#partof-and-haspart) |
### `spec.type` [optional]
The type of system. There is currently no enforced set of values for this field,
so it is left up to the adopting organization to choose a nomenclature that
matches their catalog hierarchy. This field is optional.
Some common values for this field could be:
- `product`
- `service`
- `feature-set`
## Kind: Domain
Describes the following entity kind:
@@ -1303,6 +1315,18 @@ which the domain is a part, e.g. `audio`. This field is optional.
| --------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------- |
| [`Domain`](#kind-domain) (default) | Same as this entity, typically `default` | [`partOf`, and reverse `hasPart`](well-known-relations.md#partof-and-haspart) |
### `spec.type` [optional]
The type of domain. There is currently no enforced set of values for this field,
so it is left up to the adopting organization to choose a nomenclature that
matches their catalog hierarchy. This field is optional.
Some common values for this field could be:
- `product-area`
- `product-group`
- `bundle`
## Kind: Location
Describes the following entity kind:
@@ -0,0 +1,79 @@
---
id: dry-run-testing
title: Dry Run Testing
description: How to enable and implement dry run testing in actions
---
Scaffolder templates can be tested using the dry run feature of scaffolder actions. This allows you to simulate the effects of running a scaffolder action without making any actual changes to your environment, for example creating a webhook in Github. Once dry run is enabled in the scaffolder action, you can add handling to actions you use in your scaffolder templates to define how an action should operate in a dry run scenario.
## Enabling dry run testing
To enable dry run for your scaffolder action you need to add `supportsDryRun: true` to the configuration object of `createTemplateAction` in the function where the behavior of your action is defined:
```typescript
export function exampleAction() {
return createTemplateAction<{
example: string;
}>({
id: 'action:example',
description: 'Example action',
schema: {
input: {
type: 'object',
properties: {
example: {
title: 'example',
type: 'string',
},
},
},
},
supportsDryRun: true,
async handler(ctx) {
...
},
});
}
```
## Adding handling for dry run
To add handling for dry run functionality you need to add a check for `ctx.isDryRun` inside the handler of the configuration object which is being passed into `createTemplateAction` in the function where the behavior of your action is defined. Once the check is successful, you can perform the desired actions expected in a dry run, e.g. outputting non-sensitive inputs.
```typescript
async handler(ctx) {
...
// If this is a dry run, log and return
if (ctx.isDryRun) {
ctx.logger.info(`Dry run complete`);
return;
}
...
},
```
## Testing dry run handling
You will also need to add tests for the dry run handling, for example:
```typescript
it('should not perform action during dry run', async () => {
...
// Create the context object with the necessary properties for a dry run
const ctx = {
...mockContext,
isDryRun: true,
input: {
...
},
};
// Call the handler with the context
await action.handler(ctx);
expect(...);
});
```
@@ -441,3 +441,30 @@ repoUrl:
`secretsKey` is the key used within the template secrets context to store the credential and `additionalScopes` is any additional permission scopes to request.
The supported `additionalScopes` values are `gerrit`, `github`, `gitlab`, `bitbucket`, and `azure`.
## RepoBranchPicker
The input props that can be specified under `ui:options` for the `RepoBranchPicker` field extension.
### `requestUserCredentials`
If defined will request user credentials to auth against the given SCM platform.
```yaml
repoUrl:
title: Repository Branch
type: string
ui:field: RepoBranchPicker
ui:options:
requestUserCredentials:
secretsKey: USER_OAUTH_TOKEN
additionalScopes:
github:
- workflow:write
```
`secretsKey` is the key used within the template secrets context to store the credential and `additionalScopes` is any additional permission scopes to request.
The supported `additionalScopes` values are `gerrit`, `github`, `gitlab`, `bitbucket`, and `azure`.
If you're also using the `RepoUrlPicker` field extension, you should simply duplicate this part from there.
@@ -477,6 +477,34 @@ template can be published to multiple providers.
Note, that you will need to configure an [authentication provider](../../auth/index.md#configuring-authentication-providers), alongside the
[`ScmAuthApi`](../../auth/index.md#scaffolder-configuration-software-templates) for your source code management (SCM) service to make this feature work.
### The Repository Branch Picker
Similar to the repository picker, there is a picker for branches to support autocompletion. A full example could look like this:
```yaml
- title: Choose a branch
required:
- repoBranch
properties:
repoBranch:
title: Repository Branch
type: string
ui:field: RepoBranchPicker
ui:options:
requestUserCredentials:
secretsKey: USER_OAUTH_TOKEN
```
Passing the `requestUserCredentials` object is required for autocompletion to work.
If you're also using the repository picker, you should simply duplicate this part from there.
For more information regarding the `requestUserCredentials` object, please refer to the [Using the Users `oauth` token](#using-the-users-oauth-token) section under [The Repository Picker](#the-repository-picker).
For a list of all possible `ui:options` input props for `RepoBranchPicker`, please visit [here](./ui-options-examples.md#repobranchpicker).
The `RepoBranchPicker` is a custom field that we provide part of the
`plugin-scaffolder`. You can provide your own custom fields by
[writing your own Custom Field Extensions](./writing-custom-field-extensions.md)
### Accessing the signed-in users details
Sometimes when authoring templates, you'll want to access the user that is running the template, and get details from the profile or the users `Entity` in the Catalog.
+1 -1
View File
@@ -20,7 +20,7 @@ techdocs:
# spin up the techdocs-container docker image or to run mkdocs locally (assuming all the dependencies are taken care of).
# You want to change this to 'local' if you are running Backstage using your own custom Docker setup and want to avoid running
# into Docker in Docker situation. Read more here
# https://backstage.io/docs/features/techdocs/getting-started#disable-docker-in-docker-situation-optional
# https://backstage.io/docs/features/techdocs/getting-started/#disabling-docker-in-docker-situation-optional
runIn: 'docker'
+31 -56
View File
@@ -101,23 +101,26 @@ export const IndexPage = () => {
return (
<div>
<h1>Index Page</h1>
<a
{/* highlight-start */}
href={getDetailsPath({
kind: 'component',
namespace: 'default',
name: 'foo',
})}
{/* highlight-end */}
>
See "Foo" details
</a>
{/* highlight-next-line */}
{getDetailsPath && (
<a
{/* highlight-start */}
href={getDetailsPath({
kind: 'component',
namespace: 'default',
name: 'foo',
})}
{/* highlight-end */}
>
See "Foo" details
</a>
)}
</div>
);
};
```
We use the `useRouteRef` hook to create a link generator function that returns the details page path. We then call the link generator, passing it an object with the kind, namespace, and name. These parameters are used to construct a concrete path to the "Foo" details page.
We use the `useRouteRef` hook to create a link generator function that returns the details page path. First we need to check whether the route is available, the link generator function will be `undefined` if it isn't. We then call the link generator, passing it an object with the kind, namespace, and name. These parameters are used to construct a concrete path to the "Foo" details page.
Let's see how the details page can get the parameters from the URL:
@@ -176,8 +179,11 @@ export const IndexPage = () => {
return (
<div>
<h1>Index Page</h1>
{/* highlight-next-line */}
<a href={getCreateComponentPath()}>Create Component</a>
{/* highlight-start */}
{getCreateComponentPath && (
<a href={getCreateComponentPath()}>Create Component</a>
)}
{/* highlight-end */}
</div>
);
};
@@ -289,42 +295,6 @@ export const createComponentExternalRouteRef = createExternalRouteRef({
});
```
### Optional External Route References
It is possible to define an `ExternalRouteRef` as optional, so it is not required to bind it in the app.
```tsx title="plugins/catalog/src/routes.ts"
import { createExternalRouteRef } from '@backstage/frontend-plugin-api';
export const createComponentExternalRouteRef = createExternalRouteRef({
// highlight-next-line
optional: true,
});
```
When calling `useRouteRef` with an optional external route, its return signature is changed to `RouteFunc | undefined`, and the returned value can be used to decide whether a certain link should be displayed or if an action should be taken:
```tsx title="plugins/catalog/src/components/IndexPage.tsx"
import React from 'react';
import { useRouteRef } from '@backstage/frontend-plugin-api';
import { createComponentExternalRouteRef } from '../routes';
export const IndexPage = () => {
const getCreateComponentPath = useRouteRef(createComponentExternalRouteRef);
return (
<div>
<h1>Index Page</h1>
{/* Rendering the link only if the getCreateComponentPath is defined */}
{/* highlight-start */}
{getCreateComponentPath && (
<a href={getCreateComponentPath()}>Create Component</a>
)}
{/* highlight-end */}
</div>
);
};
```
## Sub Route References
The last kind of route ref that can be created is a `SubRouteRef`, which can be used to create a route ref with a fixed path relative to an absolute `RouteRef`. They are useful if you have a page that internally is mounted at a sub route of a page extension component, and you want other plugins to be able to route to that page. And they can be a useful utility to handle routing within a plugin itself as well.
@@ -368,17 +338,21 @@ import { DetailsPage } from './DetailsPage';
export const IndexPage = () => {
const { pathname } = useLocation();
// highlight-start
const getIndexPath = useRouteRef(indexRouteRef);
const getDetailsPath = useRouteRef(detailsSubRouteRef);
// highlight-end
return (
<div>
<h1>Index Page</h1>
{/* Linking to the details sub route */}
{pathname === getIndexPath() ? (
// highlight-start
{/* highlight-start */}
{pathname === getIndexPath?.() ? (
<a
{/* Setting the details sub route params */}
href={getDetailsPath({
href={getDetailsPath?.({
kind: 'component',
namespace: 'default',
name: 'foo',
@@ -386,13 +360,14 @@ export const IndexPage = () => {
>
Show details
</a>
// highlight-end
{/* highlight-end */}
) : (
// highlight-next-line
<a href={getIndexPath()}>Hide details</a>
{/* highlight-next-line */}
<a href={getIndexPath?.()}>Hide details</a>
)}
{/* Registering the details sub route */}
<Routes>
{/* highlight-next-line */}
<Route path={detailsSubRouteRef.path} element={<DetailsPage />} />
</Routes>
</div>
@@ -28,6 +28,51 @@ app:
If your [`app-config.yaml`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/app-config.yaml#L5) file does not have this configuration, you may have to adjust your [`packages/app/public/index.html`](https://github.com/backstage/backstage/blob/e0506af8fc54074a160fb91c83d6cae8172d3bb3/packages/app/public/index.html#L69) to include the Datadog RUM `init()` section manually.
Please note that the env value MUST be specified at build time
:::note
In case after a proper configuration, the events still are not being captured: Copy and paste this section in to your `packages/app/public/index.html` under the `<head>` tag.
```html
<% if (config.has('app.datadogRum')) { %>
<script>
(function (h, o, u, n, d) {
h = h[d] = h[d] || {
q: [],
onReady: function (c) {
h.q.push(c);
},
};
d = o.createElement(u);
d.async = 1;
d.src = n;
n = o.getElementsByTagName(u)[0];
n.parentNode.insertBefore(d, n);
})(
window,
document,
'script',
'https://www.datadoghq-browser-agent.com/datadog-rum-v3.js',
'DD_RUM',
);
DD_RUM.onReady(function () {
DD_RUM.init({
clientToken: '<%= config.getString("app.datadogRum.clientToken") %>',
applicationId: '<%= config.getString("app.datadogRum.applicationId") %>',
site: '<%= config.getOptionalString("app.datadogRum.site") || "datadoghq.com" %>',
service: 'backstage',
env: '<%= config.getString("app.datadogRum.env") %>',
sampleRate:
'<%= config.getOptionalNumber("app.datadogRum.sessionSampleRate") || 100 %>',
sessionReplaySampleRate:
'<%= config.getOptionalNumber("app.datadogRum.sessionReplaySampleRate") || 0 %>',
trackInteractions: true,
});
});
</script>
<% } %>
```
The `clientToken` and `applicationId` are generated from the Datadog RUM page
following
[these instructions](https://docs.datadoghq.com/real_user_monitoring/browser/).
+320
View File
@@ -0,0 +1,320 @@
---
id: index
title: Getting Started
description: How to get started with the notifications and signals
---
The Backstage Notifications System provides a way for plugins and external services to send notifications to Backstage users.
These notifications are displayed in the dedicated page of the Backstage frontend UI or by frontend plugins per specific scenarios.
Additionally, notifications can be sent to external channels (like email) via "processors" implemented within plugins.
Notifications can be optionally integrated with the signals (a push mechanism) to ensure users receive them immediately.
### Upgrade to the latest version of Backstage
To ensure your version of Backstage has all the latest notifications and signals related functionality, its important to upgrade to the latest version. The [Backstage upgrade helper](https://backstage.github.io/upgrade-helper/) is a great tool to help ensure that youve made all the necessary changes during the upgrade!
## About notifications
Notifications are messages sent to either individual users or groups.
They are not intended for inter-process communication of any kind.
There are two basic types of notifications:
- **Broadcast**: Messages sent to all users of Backstage.
- **Entity**: Messages delivered to specific listed entities, such as Users or Groups.
Example of use-cases:
- System-wide announcements or alerts
- Notifications for component owners: e.g., build failures, successful deployments, new vulnerabilities
- Notifications for individuals: e.g., updates you have subscribed to, new required training courses
- Notifications pertaining to a particular entity in the catalog: A notification might apply to an entity and the owning team.
## Installation in Older Environments
Newer versions of instances created by the create-app have both the notifications and signals plugins included by default, this section can be skipped right to the Configuration.
Following installation instructions are valid for enabling the plugins in older environments.
### Add Notifications Backend
```bash
yarn workspace backend add @backstage/plugin-notifications-backend
```
Add the notifications to your `backend/src/index.ts`:
```ts
const backend = createBackend();
// ...
backend.add(import('@backstage/plugin-notifications-backend'));
```
### Add Notifications Frontend
```bash
yarn workspace app add @backstage/notifications
```
To add the notifications main menu, add following to your `packages/app/src/components/Root/Root.tsx`:
```tsx
import { NotificationsSidebarItem } from '@backstage/plugin-notifications';
<SidebarPage>
<Sidebar>
<SidebarGroup>
// ...
<NotificationsSidebarItem />
</SidebarGroup>
</Sidebar>
</SidebarPage>;
```
Also add the route to notifications to `packages/app/src/App.tsx`:
```tsx
import { NotificationsPage } from '@backstage/plugin-notifications';
<FlatRoutes>
// ...
<Route path="/notifications" element={<NotificationsPage />} />
</FlatRoutes>;
```
### Optional: Add Signals Backend
Optionally add Signals to your backend by
```bash
yarn workspace backend add @backstage/plugin-signals-backend
```
Add the signals to your `backend/src/index.ts`:
```ts
const backend = createBackend();
// ...
backend.add(import('@backstage/plugin-signals-backend'));
```
### Optional: Signals Frontend
The use of signals is optional but improves user experience.
Start with:
```bash
yarn workspace app add @backstage/plugin-signals
```
To install the plugin, you have to add the following to your `packages/app/src/plugins.ts`:
```ts
export { signalsPlugin } from '@backstage/plugin-signals';
```
And make sure that your `packages/app/src/App.tsx` contains:
```ts
import * as plugins from './plugins';
const app = createApp({
// ...
plugins: Object.values(plugins),
// ...
});
```
If the signals plugin is properly configured, it will be automatically discovered by the notifications plugin and used.
## Configuration
### Notifications Backend
The Notifications backend plugin provides an API to create notifications, list notifications per logged-in user, and search based on parameters.
The plugin uses a relational [database](https://backstage.io/docs/getting-started/config/database) for persistence, no specifics are introduced in this context.
No additional configuration in the app-config is needed, except for optional additional modules for `processors`.
### Notifications Frontend
The recipients of notifications have to be entities in the catalog, e.g. of the User or Group kind.
Otherwise no specific configuration is needed for the front-end notifications plugin.
All parametrization is done through component properties, such as the `NotificationsSidebarItem`, which can be used as an active left-side menu item in the front-end.
![Notifications Page](notificationsPage.png)
In the `packages/app/src/components/Root/Root.tsx`, tweak the [properties](https://backstage.io/docs/reference/plugin-notifications.notificationssidebaritem) of the `<NotificationsSidebarItem />` per specific needs.
## Use
New notifications can be sent either by a backend plugin or an external service through the REST API.
### Backend
Regardless of technical feasibility, a backend plugin should avoid directly accessing the notifications REST API.
Instead, it should integrate with the `@backstage/plugin-notifications-node` to `send` (create) a new notification.
The reasons for this approach include the propagation of authorization in the API request and improved maintenance and backward compatibility in the future.
```ts
import { notificationService } from '@backstage/plugin-notifications-node';
export const myPlugin = createBackendPlugin({
pluginId: 'myPlugin',
register(env) {
env.registerInit({
deps: {
// ...
notificationService: notificationService,
},
async init({ config, logger, httpRouter, notificationService }) {
httpRouter.use(
await createRouter({
// ...
notificationService,
}),
);
},
});
},
});
```
To emit a new notification:
```ts
notificationService.send({
recipients /* of the broadcast or entity type */,
payload /* actual message */,
});
```
Refer the [API documentation](https://github.com/backstage/backstage/blob/master/plugins/notifications-node/api-report.md) for further details.
### Signals
The use of signals with notifications is optional but generally enhances user experience and performance.
When a notification is created, a new signal is emitted to a general-purpose message bus to announce it to subscribed listeners.
The frontend maintains a persistent connection (WebSocket) to receive these announcements from the notifications channel.
The specific details of the updated or created notification should be retrieved via a request to the notifications API, except for new notifications, where the payload is included in the signal for performance reasons.
In a frontend plugin, to subscribe for notifications' signals:
```ts
import { useSignal } from '@backstage/plugin-signals-react';
const { lastSignal } = useSignal<NotificationSignal>('notifications');
React.useEffect(() => {
/* ... */
}, [lastSignal, notificationsApi]);
```
### Consuming Notifications
In a front-end plugin, the simplest way to query a notification is by its ID:
```ts
import { useApi } from '@backstage/core-plugin-api';
import { notificationsApiRef } from '@backstage/plugin-notifications';
const notificationsApi = useApi(notificationsApiRef);
notificationsApi.getNotification(yourId);
// or with connection to signals:
notificationsApi.getNotification(lastSignal.notification_id);
```
### Extending Notifications via Processors
The notifications can be extended with `NotificationProcessor`. These processors allow to decorate notifications before they are sent or/and send the notifications to external services.
Depending on the needs, a processor can modify the content of a notification or route it to different systems like email, Slack, or other services.
A good example of how to write a processor is the [Email Processor](https://github.com/backstage/backstage/tree/master/plugins/notifications-backend-module-email).
Start off by creating a notification processor:
```ts
import { Notification } from '@backstage/plugin-notifications-common';
import { NotificationProcessor } from '@backstage/plugin-notifications-node';
class MyNotificationProcessor implements NotificationProcessor {
async decorate(notification: Notification): Promise<Notification> {
if (notification.origin === 'plugin-my-plugin') {
notification.payload.icon = 'my-icon';
}
return notification;
}
async send(notification: Notification): Promise<void> {
nodemailer.sendEmail({
from: 'backstage',
to: 'user',
subject: notification.payload.title,
text: notification.payload.description,
});
}
}
```
Both of the processing functions are optional, and you can implement only one of them.
Add the notification processor to the notification system by:
```ts
import { notificationsProcessingExtensionPoint } from '@backstage/plugin-notifications-node';
import { Notification } from '@backstage/plugin-notifications-common';
export const myPlugin = createBackendPlugin({
pluginId: 'myPlugin',
register(env) {
env.registerInit({
deps: {
notifications: notificationsProcessingExtensionPoint,
// ...
},
async init({ notifications }) {
// ...
notifications.addProcessor(new MyNotificationProcessor());
},
});
},
});
```
### External Services
When the emitter of a notification is a Backstage backend plugin, it is mandatory to use the integration via `@backstage/plugin-notifications-node` as described above.
If the emitter is a service external to Backstage, an HTTP POST request can be issued directly to the API, assuming that authentication is properly configured.
Refer to the [service-to-service auth documentation](https://backstage.io/docs/auth/service-to-service-auth) for more details, focusing on the Static Tokens section for the simplest setup option.
An example request for creating a broadcast notification might look like:
```bash
curl -X POST https://[BACKSTAGE_BACKEND]/api/notifications -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_BASE64_SHARED_KEY_TOKEN" -d '{"recipients":{"type":"broadcast"},"payload": {"title": "Title of broadcast message","link": "http://foo.com/bar","severity": "high","topic": "The topic"}}'
```
## Additional info
An example of a backend plugin sending notifications can be found in https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend-module-notifications.
Sources of the notifications and signal plugins:
- https://github.com/backstage/backstage/blob/master/plugins/notifications
- https://github.com/backstage/backstage/blob/master/plugins/notifications-backend
- https://github.com/backstage/backstage/blob/master/plugins/notifications-node
- https://github.com/backstage/backstage/blob/master/plugins/signals-react
Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

@@ -199,7 +199,8 @@ const routes = (
<RequirePermission permission={todoListCreatePermission}>
<TodoListPage />
</RequirePermission>
{/* highlight-add-end */}}
{/* highlight-add-end */}
}>
{/* ... */}
</Route>
</FlatRoutes>
+21 -4
View File
@@ -17,7 +17,12 @@ See how to install Datadog Events in your app
### New Backend
The backend supplies a central logging service, [`rootLogger`](../backend-system/core-services/root-logger.md), as well as a plugin based logger, [`logger`](../backend-system/core-services/logger.md) from `coreServices`. To add additional granularity to your logs, you can create children from the plugin based logger, using the `.child()` method and provide is with JSON data. For example, if you wanted to log items for a specific span in your plugin, you could do
The backend supplies a central logging service,
[`rootLogger`](../backend-system/core-services/root-logger.md), as well as a plugin
based logger, [`logger`](../backend-system/core-services/logger.md) from `coreServices`.
To add additional granularity to your logs, you can create children from the plugin
based logger, using the `.child()` method and provide is with JSON data. For example,
if you wanted to log items for a specific span in your plugin, you could do
```ts
export function createRouter({ logger }) {
@@ -37,7 +42,9 @@ export function createRouter({ logger }) {
}
```
You can also add additional metadata to all logs for your Backstage instance by overriding the `rootLogger` implementation, you can see an example in [the `logger` docs](../backend-system/core-services/logger.md#configuring-the-service).
You can also add additional metadata to all logs for your Backstage instance by
overriding the `rootLogger` implementation, you can see an example in
[the `rootLogger` docs](../backend-system/core-services/root-logger.md#configuring-the-service).
### Old Backend
@@ -63,9 +70,19 @@ An example log line could look as follows:
## Health Checks
### New Backend
### New Backend (post 1.29.0)
The new backend is moving towards health checks being plugin-based, as such there is no current plugin for providing a health check route. You can add this yourself easily though,
The new backend provides a `RootHealthService` which implements
`/.backstage/health/v1/readiness` and `/.backstage/health/v1/liveness` endpoints
to provide health checks for the entire backend instance.
You can read more about this new service and how to customize it in the
[Root Health Service documentation](../backend-system/core-services/root-health.md).
### New Backend (pre 1.29.0)
The new backend is moving towards health checks being plugin-based, as such there is no
current plugin for providing a health check route. You can add this yourself easily though,
```ts
import {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -4,9 +4,9 @@ author: Deepankumar
authorUrl: https://github.com/deepan10
category: Infrastructure
description: Explore Azure Storage Blobs in Backstage.
documentation: https://github.com/deepan10/backstage-plugins/tree/main/plugins/azure-storage
documentation: https://github.com/backstage/community-plugins/tree/main/workspaces/azure-storage-explorer/plugins/azure-storage
iconUrl: /img/azure-storage-folder.png
npmPackageName: 'backstage-plugin-azure-storage'
npmPackageName: '@backstage-community/plugin-azure-storage-explorer'
tags:
- Azure
- Azure Storage
+15
View File
@@ -0,0 +1,15 @@
---
title: VeeCode Infracost
author: VeeCode Platform
authorUrl: https://platform.vee.codes/
category: FinOps
description: The Infracost plug-in works in conjunction with terraform and provides a graphical representation and cost estimate data for your entity at your respective provider.
documentation: https://platform.vee.codes/plugin/Infracost
iconUrl: https://veecode-platform.github.io/support/imgs/logo_5.svg
npmPackageName: '@veecode-platform/backstage-plugin-infracost'
tags:
- finops
- infracost
- estimate
- terraform
addedDate: '2024-07-25'
+1 -1
View File
@@ -6,7 +6,7 @@ category: Discovery
description: Visualize, understand and optimize your team's tech health.
documentation: https://roadie.io/backstage/plugins/tech-insights/
iconUrl: https://roadie.io/images/logos/tech-insights.png
npmPackageName: '@backstage/plugin-tech-insights'
npmPackageName: '@backstage-community/plugin-tech-insights'
tags:
- tech-insights
- reporting
+4 -1
View File
@@ -121,7 +121,8 @@
"features/software-templates/writing-custom-step-layouts",
"features/software-templates/authorizing-scaffolder-template-details",
"features/software-templates/migrating-to-rjsf-v5",
"features/software-templates/migrating-from-v1beta2-to-v1beta3"
"features/software-templates/migrating-from-v1beta2-to-v1beta3",
"features/software-templates/dry-run-testing"
]
},
{
@@ -296,6 +297,7 @@
"conf/writing",
"conf/defining"
],
"Notifications": ["notifications/index"],
"Auth and identity": [
"auth/index",
{
@@ -393,6 +395,7 @@
"backend-system/architecture/plugins",
"backend-system/architecture/extension-points",
"backend-system/architecture/modules",
"backend-system/architecture/feature-loaders",
"backend-system/architecture/naming-patterns"
]
},
+1
View File
@@ -64,6 +64,7 @@ nav:
- Writing Custom Actions: 'features/software-templates/writing-custom-actions.md'
- Writing Custom Step Layouts: 'features/software-templates/writing-custom-step-layouts.md'
- Migrating from v1beta2 to v1beta3 templates: 'features/software-templates/migrating-from-v1beta2-to-v1beta3.md'
- Dry Run Testing: 'features/software-templates/dry-run-testing.md'
- Backstage Search:
- Overview: 'features/search/README.md'
- Getting Started: 'features/search/getting-started.md'
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "root",
"version": "1.30.0-next.2",
"version": "1.30.0-next.3",
"private": true,
"repository": {
"type": "git",
+11
View File
@@ -1,5 +1,16 @@
# @backstage/app-defaults
## 1.5.10-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-permission-react@0.4.25-next.1
- @backstage/core-app-api@1.14.2-next.0
- @backstage/core-components@0.14.10-next.0
- @backstage/core-plugin-api@1.9.3
- @backstage/theme@0.5.6
## 1.5.10-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/app-defaults",
"version": "1.5.10-next.1",
"version": "1.5.10-next.2",
"description": "Provides the default wiring of a Backstage App",
"backstage": {
"role": "web-library"
@@ -1,5 +1,13 @@
# app-next-example-plugin
## 0.0.14-next.2
### Patch Changes
- Updated dependencies
- @backstage/frontend-plugin-api@0.7.0-next.2
- @backstage/core-components@0.14.10-next.0
## 0.0.14-next.1
### Patch Changes
@@ -7,7 +7,7 @@ import { BackstagePlugin } from '@backstage/frontend-plugin-api';
import { default as React_2 } from 'react';
// @public (undocumented)
const examplePlugin: BackstagePlugin<{}, {}>;
const examplePlugin: BackstagePlugin<{}, {}, {}>;
export default examplePlugin;
// @public (undocumented)
@@ -1,6 +1,6 @@
{
"name": "app-next-example-plugin",
"version": "0.0.14-next.1",
"version": "0.0.14-next.2",
"description": "Backstage internal example plugin",
"backstage": {
"role": "frontend-plugin",
+43
View File
@@ -1,5 +1,48 @@
# example-app-next
## 0.0.14-next.3
### Patch Changes
- Updated dependencies
- @backstage/plugin-scaffolder-react@1.11.0-next.2
- @backstage/plugin-catalog@1.22.0-next.2
- @backstage/frontend-plugin-api@0.7.0-next.2
- @backstage/cli@0.27.0-next.3
- @backstage/frontend-app-api@0.7.5-next.2
- @backstage/core-compat-api@0.2.8-next.2
- @backstage/plugin-app-visualizer@0.1.9-next.2
- @backstage/plugin-search-common@1.2.14-next.1
- @backstage/plugin-search-react@1.7.14-next.2
- @backstage/plugin-search@1.4.15-next.2
- @backstage/plugin-api-docs@0.11.8-next.2
- @backstage/plugin-techdocs@1.10.8-next.2
- @backstage/plugin-scaffolder@1.24.0-next.2
- @backstage/plugin-catalog-react@1.12.3-next.2
- @backstage/plugin-catalog-graph@0.4.8-next.3
- @backstage/plugin-catalog-import@0.12.2-next.2
- @backstage/plugin-org@0.6.28-next.2
- @backstage/plugin-user-settings@0.8.11-next.2
- @backstage/plugin-home@0.7.9-next.2
- @backstage/plugin-kubernetes@0.11.13-next.2
- @backstage/plugin-catalog-common@1.0.26-next.1
- @backstage/plugin-permission-react@0.4.25-next.1
- @backstage/app-defaults@1.5.10-next.2
- @backstage/catalog-model@1.5.0
- @backstage/config@1.2.0
- @backstage/core-app-api@1.14.2-next.0
- @backstage/core-components@0.14.10-next.0
- @backstage/core-plugin-api@1.9.3
- @backstage/integration-react@1.1.30-next.0
- @backstage/theme@0.5.6
- @backstage/plugin-auth-react@0.1.5-next.0
- @backstage/plugin-catalog-unprocessed-entities@0.2.7-next.0
- @backstage/plugin-kubernetes-cluster@0.0.14-next.2
- @backstage/plugin-notifications@0.2.4-next.0
- @backstage/plugin-signals@0.0.9-next.0
- @backstage/plugin-techdocs-module-addons-contrib@1.1.13-next.0
- @backstage/plugin-techdocs-react@1.2.7-next.0
## 0.0.14-next.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-app-next",
"version": "0.0.14-next.2",
"version": "0.0.14-next.3",
"private": true,
"repository": {
"type": "git",
@@ -47,9 +47,11 @@ const IndexPage = createPageExtension({
return (
<div>
op
<div>
<Link to={page1Link()}>Page 1</Link>
</div>
{page1Link && (
<div>
<Link to={page1Link()}>Page 1</Link>
</div>
)}
<div>
<Link to="/home">Home</Link>
</div>
@@ -82,10 +84,10 @@ const Page1 = createPageExtension({
return (
<div>
<h1>This is page 1</h1>
<Link to={indexLink()}>Go back</Link>
{indexLink && <Link to={indexLink()}>Go back</Link>}
<Link to="./page2">Page 2</Link>
{/* <Link to={page2Link()}>Page 2</Link> */}
<Link to={xLink()}>Page X</Link>
{xLink && <Link to={xLink()}>Page X</Link>}
<div>
Sub-page content:
@@ -115,7 +117,7 @@ const ExternalPage = createPageExtension({
return (
<div>
<h1>This is page X</h1>
<Link to={indexLink()}>Go back</Link>
{indexLink && <Link to={indexLink()}>Go back</Link>}
</div>
);
};

Some files were not shown because too many files have changed in this diff Show More