Merge branch 'master' into patch-2

This commit is contained in:
Andy Ladjadj
2022-04-27 16:18:16 +02:00
committed by GitHub
36 changed files with 428 additions and 46 deletions
+20
View File
@@ -0,0 +1,20 @@
---
'@backstage/plugin-tech-insights-backend': minor
---
**BREAKING**: The `buildTechInsightsContext` function now takes an additional
field in its options argument: `tokenManager`. This is an instance of
`TokenManager`, which can be found in your backend initialization code's
`env`.
```diff
const builder = buildTechInsightsContext({
logger: env.logger,
config: env.config,
database: env.database,
discovery: env.discovery,
scheduler: env.scheduler,
+ tokenManager: env.tokenManager,
factRetrievers: [ /* ... */ ],
});
```
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-tech-insights-node': minor
---
**BREAKING**: The `FactRetrieverContext` type now contains an additional
field: `tokenManager`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-tech-insights-backend-module-jsonfc': patch
---
Updated usages of `buildTechInsightsContext` in README.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-rollbar-backend': patch
---
Updated README to include clearer installation instructions on how to install and configure.
+4 -2
View File
@@ -118,5 +118,7 @@ _If you're using Backstage in your organization, please try to add your company
| [Pachama](https://pachama.com/) | [Aron Gates](https://github.com/agates4) | Internal Developer Portal, a catalog of all microservices, architecture documentation, and templates to generate developer resources. |
| [SEEK](https://www.seek.com.au) | [Jahred Hope](https://github.com/jahredhope) | Developer portal for developer tooling and technical documentation. |
| [Marks & Spencer](https://www.marksandspencer.com/) | [Kamal Cheriyath](https://github.com/kcheriyath) | Centralised discovery, adoption and devops automation hub for Engineering & Architecture. |
| [McKesson](https://www.mckesson.com/) | [Agnel Antony](https://github.com/aantony2) | Internal Developer Platform for developer gated CI/CD templates, technical documentation, cloud automation service catalog, etc. |
| [leboncoin](https://www.leboncoin.fr/) | [Andy Ladjadj](https://github.com/aladjadj) | Centralize our multiple UI in a single portal. Simplify onbording, new features and harmonize how people search information. Core features (catalog,api,docs,scafolder) are good to start the adoption. status: internal beta. |
| [McKesson](https://www.mckesson.com/) | [Agnel Antony](https://github.com/aantony2) | Internal Developer Platform for developer gated CI/CD templates, technical documentation, cloud automation service catalog, etc. |
| [World Fuel Services](https://www.wfscorp.com/) | [Anirudh Kurapathi](https://github.com/anirudhkurapati), [Alex Kwon](https://github.com/alexkwon), [Lester Hernandez](https://github.com/lhernandez-wfscorp), [Avi Boru](https://github.com/aviboru), [Vardhan Annapureddy](https://github.com/harshaaws) | Internal Developer Portal, service catalog product, API's, Software Templates, tech docs and more. |
| [leboncoin](https://www.leboncoin.fr/) | [Andy Ladjadj](https://github.com/aladjadj) | Centralize our multiple UI in a single portal. Simplify onbording, new features and harmonize how people search information. Core features (catalog,api,docs,scafolder) are good to start the adoption. status: internal beta. |
Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

+1 -1
View File
@@ -74,7 +74,7 @@ export class ProviderAAuthProvider implements OAuthProviderHandlers {
clientID: options.clientId,
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
passReqToCallback: false as true,
passReqToCallback: false,
response_type: 'code',
/// ... etc
}
+7 -5
View File
@@ -76,17 +76,19 @@ TechDocs packages:
TechDocs promoted to v1.0! To understand how this change affects the package, please check out our [versioning policy](https://backstage.io/docs/overview/versioning-policy).
**v1.2** 🚧
With the Backstage 1.2 release, we plan to introduce the [TechDocs Addon Framework](https://github.com/backstage/backstage/issues/9636) for augmenting the TechDocs experience at read-time.
In addition to the framework itself, we'll be open sourcing a `<ReportIssue />` addon, helping you to create a feedback loop that drives up documentation quality and fosters a documentation culture at your organization.
### **Future work 🔮**
Some of the following items are coming soon and some are potential ideas.
- [TechDocs Addon Framework](https://github.com/backstage/backstage/issues/9636)
- Contribute to and deploy from a marketplace of TechDocs Addons
- Addon: Highlight text and raise an Issue to create a feedback loop to drive up documentation quality
- Addon: MDX (allows you to use JSX in your Markdown content)
- Better integration with
[Scaffolder V2](https://github.com/backstage/backstage/issues/2771) (e.g. easy to choose and plug documentation template with Software Templates)
- Static site generator agnostic
- Static site generator agnostic, including possible support for MDX (allowing you to use JSX in your Markdown content)
- Possible to configure several aspects about TechDocs (e.g. URL, homepage,
theme)
+218
View File
@@ -0,0 +1,218 @@
---
id: addons
title: TechDocs Addons
description: How to find, use, or create TechDocs Addons.
---
> Note: This page contains documentation for features that have not yet been
> released on a [main-line version](https://backstage.io/docs/overview/versioning-policy#main-release-line)
> of Backstage and TechDocs. We plan to make Addons generally available in
> Backstage v1.2.
## Concepts
TechDocs is a centralized platform for publishing, viewing, and discovering
technical documentation across an entire organization. It's a solid foundation!
But it doesn't solve higher-order documentation needs on its own: how do you
create and reinforce a culture of documentation? How do you build trust in the
quality of technical documentation?
TechDocs Addons are a mechanism by which you can customize the TechDocs
experience in order to try and address some of these higher-order needs.
### Addons
An Addon is just a react component. Like any react component, it can retrieve
and render data using normal Backstage or native hooks, APIs, and components.
Props can be used to configure its behavior, where appropriate.
### Locations
Addons declare a `location` where they will be rendered. Most locations are
representative of physical spaces in the TechDocs UI:
- `Header`: For Addons which fill up the header from the right, on the same
line as the title.
- `Subheader`: For Addons that sit below the header but above all content.
This is a great location for tooling/configuration of TechDocs display.
- `PrimarySidebar`: Left of the content, above of the navigation.
- `SecondarySidebar`: Right of the content, above the table of contents.
- `Content`: A special location intended for Addons which augment the
statically generated content of the documentation itself.
- `Component`: A [proposed-but-not-yet-implemented](https://github.com/backstage/backstage/issues/11109)
virtual location, aimed at simplifying a common type of Addon.
<img data-zoomable src="../../assets/techdocs/addon-locations.png" alt="TechDocs Addon Location Guide" />
### Addon Registry
The installation and configuration of Addons happens within a Backstage app's
frontend. Addons are imported from plugins and added underneath a registry
component called `<TechDocsAddons>`. This registry can be configured for both
the TechDocs Reader page as well as the Entity docs page.
Addons are rendered in the order in which they are registered.
## Installing and using Addons
Addons can be installed and configured in much the same way as extensions for
other Backstage plugins: by adding them underneath an extension registry
component (`<TechDocsAddons>`) under the route representing the TechDocs Reader
page in your `App.tsx`:
```tsx
// packages/app/src/App.tsx
import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
// ...
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
<TechDocsAddons>
<ReportIssue />
{/* Other addons can be added here. */}
</TechDocsAddons>
</Route>;
```
The process for configuring Addons on the documentation tab on the entity page
is very similar; instead of adding the `<TechDocsAddons>` registry under a
`<Route>`, you'd add it as a child of `<EntityTechdocsContent />`:
```tsx
// packages/app/src/components/catalog/EntityPage.tsx
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha';
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
// ...
<EntityLayout.Route path="/docs" title="Docs">
<EntityTechdocsContent>
<TechDocsAddons>
<ReportIssue />
{/* Other addons can be added here. */}
</TechDocsAddons>
</EntityTechdocsContent>
</EntityLayout.Route>;
```
Note that on the entity page, because the Catalog plugin is responsible for the
page header, TechDocs Addons whose location is `Header` will not be rendered.
## Available Addons
Addons can, in principle, be provided by any plugin! To make it easier to
discover available Addons, we've compiled a list of them here:
| Addon | Package/Plugin | Description |
| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`<ReportIssue />`](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
Got an Addon to contribute? Feel free to add a row above!
## Creating an Addon
The simplest Addons are plain old react components that get rendered in
specific locations within a TechDocs site. To package such a react component as
an Addon, follow these steps:
1. Write the component in your plugin like any other component
2. Create, provide, and export the component from your plugin
```ts
// plugins/your-plugin/src/plugin.ts
import {
createTechDocsAddonExtension,
TechDocsAddonLocations,
} from '@backstage/plugin-techdocs-react/alpha';
import { CatGifComponent, CatGifComponentProps } from './addons';
// ...
// You must "provide" your Addon, just like any extension, via your plugin.
export const CatGif = yourPlugin.provide(
// This function "creates" the Addon given a component and location. If your
// component can be configured via props, pass the prop type here too.
createTechDocsAddonExtension<CatGifComponentProps>({
name: 'CatGif',
location: TechDocsAddonLocations.Header,
component: CatGifComponent,
}),
);
```
### Addons in the Content location
Beyond the "render a component in a region" use-case, it's also possible for
Addons to access and manipulate a TechDocs site's DOM; this could be used to,
for example, load and instantiate client-side diagramming libraries, replace
elements with dynamically loaded content, etc.
This type of Addon is still expressed as a react component, but instead of
returning a react element to be rendered, it updates the DOM via side-effects
(e.g. with `useEffect`). Access to the DOM is made available via utility hooks
provided by the Addon framework.
```tsx
// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.tsx
import React, { useEffect } from 'react';
import { useShadowRootElements } from '@backstage/plugin-techdocs-react/alpha';
// This is a normal react component; in order to make it an Addon, you would
// still create and provide it via your plugin as described above. The only
// difference is that you'd set `location` to `TechDocsAddonLocations.Content`.
export const MakeAllImagesCatGifsAddon = () => {
// This hook can be used to get references to specific elements. If you need
// access to the whole shadow DOM, use the the underlying useShadowRoot()
// hook instead.
const images = useShadowRootElements<HTMLImageElement>(['img']);
useEffect(() => {
images.forEach(img => {
if (img.src !== 'https://example.com/cat.gif') {
img.src = 'https://example.com/cat.gif';
}
});
}, [images]);
// Nothing to render directly, so we can just return null.
return null;
};
```
### Testing Addons
Install `@backstage/plugin-techdocs-addons-test-utils` as a `devDependency` in
your plugin for access to utilities that make testing such Addons easier.
A test for the above Addon might look something like this:
```tsx
// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.test.tsx
import { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils';
// Note: import your actual addon (the one provided by your plugin).
import { MakeAllImagesCatGifs } from '../plugin.ts';
describe('MakeAllImagesCatGifs', () => {
it('replaces img srcs with cat gif', async () => {
const { getByTestId } = await TechDocsAddonTester.buildAddonsInTechDocs([
<MakeAllImagesCatGifs />,
])
.withDom(<img data-testid="fixture" src="http://example.com/dog.jpg" />)
.renderWithEffects();
expect(getByTestId('fixture')).toHaveAttribute(
'src',
'https://example.com/cat.gif',
);
});
});
```
+16 -4
View File
@@ -96,10 +96,6 @@ Documentation generated by TechDocs is generated as static HTML sites. The
TechDocs Reader was therefore created to be able to integrate pre-generated HTML
sites with the Backstage UI.
The TechDocs Reader purpose is also to open up the opportunity to integrate
TechDocs widgets for a customized full-featured TechDocs experience.
([coming soon V.3](./README.md#project-roadmap))
[TechDocs Reader](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md)
## Transformers
@@ -110,3 +106,19 @@ transform the HTML content on pre and post render (e.g. rewrite docs links or
modify css).
[Transformers API docs](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/reader/README.md)
## TechDocs Addons
Addons (introduced in Backstage v1.2) are client-side, React-based extensions
that can be used to augment the TechDocs experience at read-time. They offer a
mechanism for configuring the TechDocs Reader to better suit your
organization's needs.
Addons can dynamically load and display information anywhere in the TechDocs
Reader, including within the statically generated content itself.
Addons should not be confused with `mkdocs` plugins, which may be used to
customize a TechDocs site's content at build-time. While it's possible to take
advantage of some `mkdocs` plugins, not all such plugins play well with
TechDocs (primarily, but not exclusively, for security reasons). Addons offer
an alternative.
+1
View File
@@ -109,6 +109,7 @@
"features/techdocs/techdocs-overview",
"features/techdocs/getting-started",
"features/techdocs/concepts",
"features/techdocs/addons",
"features/techdocs/architecture",
"features/techdocs/creating-and-publishing",
"features/techdocs/configuration",
@@ -38,6 +38,7 @@ export default async function createPlugin(
database: env.database,
scheduler: env.scheduler,
discovery: env.discovery,
tokenManager: env.tokenManager,
factRetrievers: [
createFactRetrieverRegistration({
cadence: '1 1 1 * *', // Example cron, At 01:01 on day-of-month 1.
@@ -71,6 +71,8 @@ export class Auth0AuthProvider implements OAuthHandlers {
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
domain: options.domain,
// We need passReqToCallback set to false to get params, but there's
// no matching type signature for that, so instead behold this beauty
passReqToCallback: false as true,
},
(
@@ -94,9 +94,7 @@ export class BitbucketAuthProvider implements OAuthHandlers {
clientID: options.clientId,
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
// We need passReqToCallback set to false to get params, but there's
// no matching type signature for that, so instead behold this beauty
passReqToCallback: false as true,
passReqToCallback: false,
},
(
accessToken: any,
@@ -73,9 +73,7 @@ export class GoogleAuthProvider implements OAuthHandlers {
clientID: options.clientId,
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
// We need passReqToCallback set to false to get params, but there's
// no matching type signature for that, so instead behold this beauty
passReqToCallback: false as true,
passReqToCallback: false,
},
(
accessToken: any,
@@ -83,7 +83,7 @@ export class MicrosoftAuthProvider implements OAuthHandlers {
callbackURL: options.callbackUrl,
authorizationURL: options.authorizationUrl,
tokenURL: options.tokenUrl,
passReqToCallback: false as true,
passReqToCallback: false,
},
(
accessToken: any,
@@ -76,7 +76,7 @@ export class OAuth2AuthProvider implements OAuthHandlers {
callbackURL: options.callbackUrl,
authorizationURL: options.authorizationUrl,
tokenURL: options.tokenUrl,
passReqToCallback: false as true,
passReqToCallback: false,
scope: options.scope,
customHeaders: options.includeBasicAuth
? {
@@ -146,7 +146,7 @@ export class OidcAuthProvider implements OAuthHandlers {
const strategy = new OidcStrategy(
{
client,
passReqToCallback: false as true,
passReqToCallback: false,
},
(
tokenset: TokenSet,
@@ -94,7 +94,7 @@ export class OktaAuthProvider implements OAuthHandlers {
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
audience: options.audience,
passReqToCallback: false as true,
passReqToCallback: false,
store: this.store,
response_type: 'code',
},
@@ -71,7 +71,7 @@ export class OneLoginProvider implements OAuthHandlers {
clientID: options.clientId,
clientSecret: options.clientSecret,
callbackURL: options.callbackUrl,
passReqToCallback: false as true,
passReqToCallback: false,
},
(
accessToken: any,
+52
View File
@@ -4,6 +4,58 @@ Simple plugin that proxies requests to the [Rollbar](https://rollbar.com) API.
## Setup
1. Install the plugin using:
```bash
# From your Backstage root directory
yarn add --cwd packages/backend @backstage/plugin-rollbar-backend
```
2. Create a `rollbar.ts` file inside `packages/backend/src/plugins/`:
```typescript
import { createRouter } from '@backstage/plugin-rollbar-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
});
}
```
3. Modify your `packages/backend/src/index.ts` to include:
```diff
...
import { Config } from '@backstage/config';
import app from './plugins/app';
+import rollbar from './plugins/rollbar';
import scaffolder from './plugins/scaffolder';
...
async function main() {
...
const authEnv = useHotMemoize(module, () => createEnv('auth'));
+ const rollbarEnv = useHotMemoize(module, () => createEnv('rollbar'));
const proxyEnv = useHotMemoize(module, () => createEnv('proxy'));
...
const apiRouter = Router();
apiRouter.use('/catalog', await catalog(catalogEnv));
+ apiRouter.use('/rollbar', await rollbar(rollbarEnv));
apiRouter.use('/scaffolder', await scaffolder(scaffolderEnv));
```
The following values are read from the configuration file.
```yaml
@@ -28,6 +28,7 @@ and modify the `techInsights.ts` file to contain a reference to the FactCheckers
config: env.config,
database: env.database,
discovery: env.discovery,
tokenManager: env.tokenManager,
factRetrievers: [myFactRetrieverRegistration],
+ factCheckerFactory: myFactCheckerFactory
});
+11 -3
View File
@@ -35,6 +35,7 @@ export default async function createPlugin(
database: env.database,
discovery: env.discovery,
scheduler: env.scheduler,
tokenManager: env.tokenManager,
factRetrievers: [], // Fact retrievers registrations you want tech insights to use
});
@@ -104,6 +105,7 @@ const builder = buildTechInsightsContext({
config: env.config,
database: env.database,
discovery: env.discovery,
tokenManager: env.tokenManager,
- factRetrievers: [],
+ factRetrievers: [myFactRetrieverRegistration],
});
@@ -119,6 +121,7 @@ const builder = buildTechInsightsContext({
config: env.config,
database: env.database,
discovery: env.discovery,
tokenManager: env.tokenManager,
- factRetrievers: [],
+ factRetrievers: process.env.MAIN_FACT_RETRIEVER_INSTANCE ? [myFactRetrieverRegistration] : [],
});
@@ -158,9 +161,12 @@ const myFactRetriever: FactRetriever = {
const catalogClient = new CatalogClient({
discoveryApi: discovery,
});
const entities = await catalogClient.getEntities({
filter: [{ kind: 'component' }],
});
const entities = await catalogClient.getEntities(
{
filter: [{ kind: 'component' }],
},
{ token },
);
/**
* snip: Do complex logic to retrieve facts from external system or calculate fact values
*/
@@ -214,6 +220,7 @@ and modify the `techInsights.ts` file to contain a reference to the FactChecker
config: env.config,
database: env.database,
discovery: env.discovery,
tokenManager: env.tokenManager,
factRetrievers: [myFactRetrieverRegistration],
+ factCheckerFactory: myFactCheckerFactory
});
@@ -273,6 +280,7 @@ export default async function createPlugin(
config: env.config,
database: env.database,
discovery: env.discovery,
tokenManager: env.tokenManager,
factRetrievers: [
createFactRetrieverRegistration({
cadence: '0 */6 * * *', // Run every 6 hours - https://crontab.guru/#0_*/6_*_*_*
@@ -17,6 +17,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { PluginTaskScheduler } from '@backstage/backend-tasks';
import { TechInsightCheck } from '@backstage/plugin-tech-insights-node';
import { TechInsightsStore } from '@backstage/plugin-tech-insights-node';
import { TokenManager } from '@backstage/backend-common';
// @public
export const buildTechInsightsContext: <
@@ -95,6 +96,8 @@ export interface TechInsightsOptions<
logger: Logger;
// (undocumented)
scheduler: PluginTaskScheduler;
// (undocumented)
tokenManager: TokenManager;
}
// (No @packageDocumentation comment for this package)
@@ -22,7 +22,11 @@ import {
} from '@backstage/plugin-tech-insights-node';
import { FactRetrieverRegistry } from './FactRetrieverRegistry';
import { FactRetrieverEngine } from './FactRetrieverEngine';
import { DatabaseManager, getVoidLogger } from '@backstage/backend-common';
import {
DatabaseManager,
getVoidLogger,
ServerTokenManager,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils';
import { TaskScheduler } from '@backstage/backend-tasks';
@@ -129,6 +133,7 @@ describe('FactRetrieverEngine', () => {
factRetrieverContext: {
logger: getVoidLogger(),
config: ConfigReader.fromConfigs([]),
tokenManager: ServerTokenManager.noop(),
discovery: {
getBaseUrl: (_: string) => Promise.resolve('http://mock.url'),
getExternalBaseUrl: (_: string) => Promise.resolve('http://mock.url'),
@@ -18,6 +18,7 @@ import { RELATION_OWNED_BY } from '@backstage/catalog-model';
import {
PluginEndpointDiscovery,
getVoidLogger,
ServerTokenManager,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { GetEntitiesResponse } from '@backstage/catalog-client';
@@ -104,6 +105,7 @@ const handlerContext = {
discovery,
logger: getVoidLogger(),
config: ConfigReader.fromConfigs([]),
tokenManager: ServerTokenManager.noop(),
};
const entityFactRetriever = entityMetadataFactRetriever;
@@ -44,11 +44,19 @@ export const entityMetadataFactRetriever: FactRetriever = {
description: 'The entity has tags in metadata',
},
},
handler: async ({ discovery, entityFilter }: FactRetrieverContext) => {
handler: async ({
discovery,
entityFilter,
tokenManager,
}: FactRetrieverContext) => {
const { token } = await tokenManager.getToken();
const catalogClient = new CatalogClient({
discoveryApi: discovery,
});
const entities = await catalogClient.getEntities({ filter: entityFilter });
const entities = await catalogClient.getEntities(
{ filter: entityFilter },
{ token },
);
return entities.items.map((entity: Entity) => {
return {
@@ -19,6 +19,7 @@ import { RELATION_OWNED_BY } from '@backstage/catalog-model';
import {
PluginEndpointDiscovery,
getVoidLogger,
ServerTokenManager,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { GetEntitiesResponse } from '@backstage/catalog-client';
@@ -104,6 +105,7 @@ const handlerContext = {
discovery,
logger: getVoidLogger(),
config: ConfigReader.fromConfigs([]),
tokenManager: ServerTokenManager.noop(),
};
const entityFactRetriever = entityOwnershipFactRetriever;
@@ -42,11 +42,19 @@ export const entityOwnershipFactRetriever: FactRetriever = {
description: 'The spec.owner field is set and refers to a group',
},
},
handler: async ({ discovery, entityFilter }: FactRetrieverContext) => {
handler: async ({
discovery,
entityFilter,
tokenManager,
}: FactRetrieverContext) => {
const { token } = await tokenManager.getToken();
const catalogClient = new CatalogClient({
discoveryApi: discovery,
});
const entities = await catalogClient.getEntities({ filter: entityFilter });
const entities = await catalogClient.getEntities(
{ filter: entityFilter },
{ token },
);
return entities.items.map((entity: Entity) => {
return {
@@ -19,6 +19,7 @@ import { RELATION_OWNED_BY } from '@backstage/catalog-model';
import {
PluginEndpointDiscovery,
getVoidLogger,
ServerTokenManager,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { GetEntitiesResponse } from '@backstage/catalog-client';
@@ -104,6 +105,7 @@ const handlerContext = {
discovery,
logger: getVoidLogger(),
config: ConfigReader.fromConfigs([]),
tokenManager: ServerTokenManager.noop(),
};
const entityFactRetriever = techdocsFactRetriever;
@@ -40,11 +40,19 @@ export const techdocsFactRetriever: FactRetriever = {
description: 'The entity has a title in metadata',
},
},
handler: async ({ discovery, entityFilter }: FactRetrieverContext) => {
handler: async ({
discovery,
entityFilter,
tokenManager,
}: FactRetrieverContext) => {
const { token } = await tokenManager.getToken();
const catalogClient = new CatalogClient({
discoveryApi: discovery,
});
const entities = await catalogClient.getEntities({ filter: entityFilter });
const entities = await catalogClient.getEntities(
{ filter: entityFilter },
{ token },
);
return entities.items.map((entity: Entity) => {
return {
@@ -19,6 +19,7 @@ import {
DatabaseManager,
getVoidLogger,
PluginDatabaseManager,
ServerTokenManager,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import request from 'supertest';
@@ -74,6 +75,7 @@ describe('Tech Insights router tests', () => {
getBaseUrl: (_: string) => Promise.resolve('http://mock.url'),
getExternalBaseUrl: (_: string) => Promise.resolve('http://mock.url'),
},
tokenManager: ServerTokenManager.noop(),
});
const router = await createRouter({
@@ -21,6 +21,7 @@ import { Config } from '@backstage/config';
import {
PluginDatabaseManager,
PluginEndpointDiscovery,
TokenManager,
} from '@backstage/backend-common';
import {
FactChecker,
@@ -63,6 +64,7 @@ export interface TechInsightsOptions<
discovery: PluginEndpointDiscovery;
database: PluginDatabaseManager;
scheduler: PluginTaskScheduler;
tokenManager: TokenManager;
}
/**
@@ -104,6 +106,7 @@ export const buildTechInsightsContext = async <
database,
logger,
scheduler,
tokenManager,
} = options;
const factRetrieverRegistry = new FactRetrieverRegistry(factRetrievers);
@@ -121,6 +124,7 @@ export const buildTechInsightsContext = async <
config,
discovery,
logger,
tokenManager,
},
});
+2
View File
@@ -10,6 +10,7 @@ import { Duration } from 'luxon';
import { DurationLike } from 'luxon';
import { Logger } from 'winston';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { TokenManager } from '@backstage/backend-common';
// @public
export type CheckValidationResponse = {
@@ -58,6 +59,7 @@ export type FactRetrieverContext = {
config: Config;
discovery: PluginEndpointDiscovery;
logger: Logger;
tokenManager: TokenManager;
entityFilter?:
| Record<string, string | symbol | (string | symbol)[]>[]
| Record<string, string | symbol | (string | symbol)[]>;
+5 -1
View File
@@ -15,7 +15,10 @@
*/
import { DateTime, Duration, DurationLike } from 'luxon';
import { Config } from '@backstage/config';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
import {
PluginEndpointDiscovery,
TokenManager,
} from '@backstage/backend-common';
import { Logger } from 'winston';
/**
@@ -135,6 +138,7 @@ export type FactRetrieverContext = {
config: Config;
discovery: PluginEndpointDiscovery;
logger: Logger;
tokenManager: TokenManager;
entityFilter?:
| Record<string, string | symbol | (string | symbol)[]>[]
| Record<string, string | symbol | (string | symbol)[]>;
+13 -12
View File
@@ -5041,9 +5041,9 @@
integrity sha512-6k/pU2jNlgYvKOy84vpCAZ8MGVwybvAdjzrh4UicCVOCPxz0LSBws1OE6O5TO4sPHaSw+yLfNzNK8RicGFc1Kw==
"@react-hookz/web@^13.0.0":
version "13.2.1"
resolved "https://registry.npmjs.org/@react-hookz/web/-/web-13.2.1.tgz#12b3bc30d2cced8b75690c6c3708f96cfdf58172"
integrity sha512-ckHdvZ5rgblBscvHdPWAASH46FvfOGjnC+TG3ZtzkOEaYxFtXAzxgQyjjPS+veLuVEGLZ/9HdU6A2l24QBp+9w==
version "13.3.0"
resolved "https://registry.npmjs.org/@react-hookz/web/-/web-13.3.0.tgz#257e31049e92a121912fe1e67bdd01dbec5a203b"
integrity sha512-KswgkmqBVVDo6UnBFfssrojmDisogxC4jGZmd976R8YHoS3zdQJxjqICpOBSRohbRyYhYS9Cprw7BuV/CZcMaw==
dependencies:
"@react-hookz/deep-equal" "^1.0.1"
@@ -10337,9 +10337,9 @@ cypress-plugin-snapshots@^1.4.4:
unidiff "1.0.2"
cypress@^9.5.0:
version "9.5.4"
resolved "https://registry.npmjs.org/cypress/-/cypress-9.5.4.tgz#49d9272f62eba12f2314faf29c2a865610e87550"
integrity sha512-6AyJAD8phe7IMvOL4oBsI9puRNOWxZjl8z1lgixJMcgJ85JJmyKeP6uqNA0dI1z14lmJ7Qklf2MOgP/xdAqJ/Q==
version "9.6.0"
resolved "https://registry.npmjs.org/cypress/-/cypress-9.6.0.tgz#84473b3362255fa8f5e627a596e58575c9e5320f"
integrity sha512-nNwt9eBQmSENamwa8LxvggXksfyzpyYaQ7lNBLgks3XZ6dPE/6BCQFBzeAyAPt/bNXfH3tKPkAyhiAZPYkWoEg==
dependencies:
"@cypress/request" "^2.88.10"
"@cypress/xvfb" "^1.2.4"
@@ -14421,9 +14421,9 @@ inquirer@^7.3.3:
through "^2.3.6"
inquirer@^8.0.0, inquirer@^8.1.1, inquirer@^8.2.0:
version "8.2.2"
resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.2.tgz#1310517a87a0814d25336c78a20b44c3d9b7629d"
integrity sha512-pG7I/si6K/0X7p1qU+rfWnpTE1UIkTONN1wxtzh0d+dHXtT/JG6qBgLxoyHVsQa8cFABxAPh0pD6uUUHiAoaow==
version "8.2.3"
resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.3.tgz#9c0b8a3fda91fdb00590557ec8530160e908c6e7"
integrity sha512-jmoBlmWUChXgVi1wGDZsD7pWCaibJKmL+8+E2jaiWiRj8OlJLwQdQQS2CIjgvdg8UUHX+oyagQKicVVcqwxi9Q==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
@@ -14439,6 +14439,7 @@ inquirer@^8.0.0, inquirer@^8.1.1, inquirer@^8.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
wrap-ansi "^7.0.0"
internal-slot@^1.0.3:
version "1.0.3"
@@ -21288,9 +21289,9 @@ react-virtualized-auto-sizer@^1.0.6:
integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ==
react-window@^1.8.6:
version "1.8.6"
resolved "https://registry.npmjs.org/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112"
integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==
version "1.8.7"
resolved "https://registry.npmjs.org/react-window/-/react-window-1.8.7.tgz#5e9fd0d23f48f432d7022cdb327219353a15f0d4"
integrity sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==
dependencies:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"