Merge remote-tracking branch 'upstream/master' into airbrake-no-projectid-no-error
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
Move `@types/json-schema` to be a dev dependency
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/catalog-client': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the old deprecated request/response types:
|
||||
|
||||
- `CatalogEntitiesRequest` - please use `GetEntitiesRequest` instead
|
||||
- `CatalogEntityAncestorsRequest` - please use `GetEntityAncestorsRequest` instead
|
||||
- `CatalogEntityAncestorsResponse` - please use `GetEntityAncestorsResponse` instead
|
||||
- `CatalogListResponse` - please use `GetEntitiesResponse` instead
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
**Breaking**: Mark permission-related exports as alpha. This means that the exports below should now be imported from `@backstage/plugin-catalog-backend/alpha` instead of `@backstage/plugin-catalog-backend`.
|
||||
|
||||
- `catalogConditions`
|
||||
- `createCatalogPolicyDecision`
|
||||
- `permissionRules`
|
||||
- `createCatalogPermissionRule`
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
'@backstage/backend-common': minor
|
||||
---
|
||||
|
||||
**BREAKING**: The connection string for `redis` cache store now requires a protocol prefix.
|
||||
|
||||
```diff
|
||||
backend:
|
||||
cache:
|
||||
store: redis
|
||||
- connection: user:pass@cache.example.com:6379
|
||||
+ connection: redis://user:pass@cache.example.com:6379
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-backend': patch
|
||||
---
|
||||
|
||||
Added a new interface that allows for customization of when to build techdocs
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-msgraph': patch
|
||||
---
|
||||
|
||||
add config option `groupExpand` to allow expanding a single relationship
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
'@backstage/plugin-api-docs': patch
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
'@backstage/plugin-badges-backend': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-code-coverage-backend': patch
|
||||
'@backstage/plugin-explore': patch
|
||||
'@backstage/plugin-fossa': patch
|
||||
'@backstage/plugin-jenkins-backend': patch
|
||||
'@backstage/plugin-rollbar': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
'@backstage/plugin-techdocs-backend': patch
|
||||
'@backstage/plugin-todo-backend': patch
|
||||
---
|
||||
|
||||
Use `getEntityByRef` instead of `getEntityByName` in the catalog client
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-common': minor
|
||||
---
|
||||
|
||||
Remove resourceType property from catalogEntityCreatePermission. Resource type refers to the type of resources whose resourceRefs should be passed along with authorize requests, to allow conditional responses for that resource type. Since creation does not correspond to an entity (as the entity does not exist at the time of authorization), the resourceRef should not be included on the permission.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Update import location of catalogEntityCreatePermission.
|
||||
|
||||
To apply this change to an existing app, make the following change to `packages/app/src/App.tsx`:
|
||||
|
||||
```diff
|
||||
-import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common';
|
||||
+import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha';
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-explore': patch
|
||||
'@backstage/plugin-fossa': patch
|
||||
'@backstage/plugin-org': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
- **DEPRECATION**: Deprecated `formatEntityRefTitle` in favor of the new `humanizeEntityRef` method instead. Please migrate to using the new method instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
DockerContainerRunner.runContainer now automatically removes the container when its execution terminates
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/integration': minor
|
||||
'@backstage/backend-common': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
ensure `apiBaseUrl` being set for Bitbucket integrations, replace hardcoded defaults
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': minor
|
||||
---
|
||||
|
||||
- **BREAKING**: Removed the `FavouriteTemplate` export in favor of the `FavoriteEntity` from `@backstage/plugin-catalog-react`. Please migrate any usages to that component instead if you are creating your own `TemplateCard` page.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
**DEPRECATED**: The `results` export, and instead adding `processingResult` with the same shape and purpose.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Internal restructuring to collect the various provider files in a `modules` folder while waiting to be externalized
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
Deprecated `favoriteEntityTooltip` and `favoriteEntityIcon` since the utility value is very low.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
---
|
||||
|
||||
**DEPRECATION**: Deprecated the `EntityName` type, and added the better-named `CompoundEntityRef` to replace it.
|
||||
|
||||
**DEPRECATION**: Deprecated the `getEntityName` function, and added the better-named `getCompoundEntityRef` to replace it.
|
||||
|
||||
Please switch over to using the new symbols, as the old ones may be removed in a future release.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
'@backstage/core-plugin-api': minor
|
||||
'@backstage/test-utils': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the deprecated `get` method from `StorageAPI` and its implementations, this method has been replaced by the `snapshot` method. The return value from snapshot no longer includes `newValue` which has been replaced by `value`. For getting notified when a value changes, use `observe$`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-permission-common': patch
|
||||
---
|
||||
|
||||
Add api doc comments to `Permission` type properties.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-common': minor
|
||||
---
|
||||
|
||||
**Breaking**: Mark permission-related exports as alpha. This means that the exports below should now be imported from `@backstage/plugin-catalog-common/alpha` instead of `@backstage/plugin-catalog-common`.
|
||||
|
||||
- `RESOURCE_TYPE_CATALOG_ENTITY`
|
||||
- `catalogEntityReadPermission`
|
||||
- `catalogEntityCreatePermission`
|
||||
- `catalogEntityDeletePermission`
|
||||
- `catalogEntityRefreshPermission`
|
||||
- `catalogLocationReadPermission`
|
||||
- `catalogLocationCreatePermission`
|
||||
- `catalogLocationDeletePermission`
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': minor
|
||||
---
|
||||
|
||||
Removed some previously deprecated `routeRefs` as follows:
|
||||
|
||||
- **BREAKING**: Removed `entityRoute` in favor of `entityRouteRef`.
|
||||
- **BREAKING**: Removed the previously deprecated `rootRoute` and `catalogRouteRef`. If you want to refer to the catalog index page from a public plugin you now need to use an `ExternalRouteRef` instead. For private plugins it is possible to take the shortcut of referring directly to `catalogPlugin.routes.indexPage` instead.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-aws': patch
|
||||
'@backstage/plugin-catalog-backend-module-ldap': patch
|
||||
'@backstage/plugin-catalog-backend-module-msgraph': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Use the new `processingResult` export from the catalog backend
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Export FetchUrlReader to facilitate more flexible configuration of the backend.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed export of `GithubSession` and `SamlSession` which are only used internally.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the deprecated `app.<key>` template variables from the `index.html` templating. These should be replaced by using `config.getString("app.<key>")` instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Deprecated the `BitbucketRepositoryParser` type.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
- **BREAKING**: The `isOwnerOf` function has been marked as `@alpha` and is now only available via the `@backstage/plugin-catalog-react/alpha` import. The limitations of this function with regards to only supporting direct relations have also been documented.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': minor
|
||||
---
|
||||
|
||||
Marked `useEntityPermission` as alpha since the underlying permission framework is under active development.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
The CLI now bundles both version 16 and 17 of the patched `@hot-loader/react-dom` dependency, and selects the appropriate one based on what version of `react-dom` is installed within the app.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-permission-node': patch
|
||||
---
|
||||
|
||||
Export some utility functions for parsing PermissionCriteria
|
||||
|
||||
`isAndCriteria`, `isOrCriteria`, `isNotCriteria` are now exported.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-msgraph': patch
|
||||
---
|
||||
|
||||
add documentation for config options `userGroupMemberSearch` and `groupSearch`
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/app-defaults': minor
|
||||
'@backstage/core-app-api': minor
|
||||
'@backstage/core-components': minor
|
||||
'@backstage/core-plugin-api': minor
|
||||
'@backstage/test-utils': minor
|
||||
'@backstage/plugin-user-settings': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed deprecated `auth0AuthApiRef`, `oauth2ApiRef`, `samlAuthApiRef` and `oidcAuthApiRef` as these APIs are too generic to be useful. Instructions for how to migrate can be found at [https://backstage.io/docs/api/deprecations#generic-auth-api-refs](https://backstage.io/docs/api/deprecations#generic-auth-api-refs).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
**Breaking**: Removed `entityRef` from `CatalogProcessorRelationResult`. The field is not used by the catalog and relation information is already available inside the `reation` property.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-airbrake': patch
|
||||
'@backstage/plugin-airbrake-backend': patch
|
||||
---
|
||||
|
||||
The Airbrake plugin installation instructions have been updated to work better and conform to how the frontend and backend plugins are supposed to be integrated into a Backstage instance.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/catalog-client': patch
|
||||
---
|
||||
|
||||
**DEPRECATION**: Deprecated `getEntityByName` from `CatalogApi` and added `getEntityByRef` instead, which accepts both string and compound ref forms.
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-node': minor
|
||||
'@backstage/search-common': minor
|
||||
---
|
||||
|
||||
**BREAKING**
|
||||
|
||||
The Backstage Search Platform's indexing process has been rewritten as a stream
|
||||
pipeline in order to improve efficiency and performance on large document sets.
|
||||
|
||||
The concepts of `Collator` and `Decorator` have been replaced with readable and
|
||||
transform object streams (respectively), as well as factory classes to
|
||||
instantiate them. Accordingly, the `SearchEngine.index()` method has also been
|
||||
replaced with a `getIndexer()` factory method that resolves to a writable
|
||||
object stream.
|
||||
|
||||
Check [this upgrade guide](https://backstage.io/docs/features/search/how-to-guides#how-to-migrate-from-search-alpha-to-beta)
|
||||
for further details.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-module-pg': minor
|
||||
---
|
||||
|
||||
**BREAKING**
|
||||
|
||||
The `PgSearchEngine` implements the new stream-based indexing process expected
|
||||
by the latest `@backstage/search-backend-node`.
|
||||
|
||||
When updating to this version, you must also update to the latest version of
|
||||
`@backstage/search-backend-node`. Check [this upgrade guide](https://backstage.io/docs/features/search/how-to-guides#how-to-migrate-from-search-alpha-to-beta)
|
||||
for further details.
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-backend': patch
|
||||
---
|
||||
|
||||
A `DefaultTechDocsCollatorFactory`, which works with the new stream-based
|
||||
search indexing subsystem, is now available. The `DefaultTechDocsCollator` will
|
||||
continue to be available for those unable to upgrade to the stream-based
|
||||
`@backstage/search-backend-node` (and related packages), however it is now
|
||||
marked as deprecated and will be removed in a future version.
|
||||
|
||||
To upgrade this plugin and the search indexing subsystem in one go, check
|
||||
[this upgrade guide](https://backstage.io/docs/features/search/how-to-guides#how-to-migrate-from-search-alpha-to-beta)
|
||||
for necessary changes to your search backend plugin configuration.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
The Backstage Search Platform's indexing process has been rewritten as a stream
|
||||
pipeline in order to improve efficiency and performance on large document sets.
|
||||
|
||||
To take advantage of this, upgrade to the latest version of
|
||||
`@backstage/plugin-search-backend-node`, as well as any backend plugins whose
|
||||
collators you are using. Then, make the following changes to your
|
||||
`/packages/backend/src/plugins/search.ts` file:
|
||||
|
||||
```diff
|
||||
-import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend';
|
||||
-import { DefaultTechDocsCollator } from '@backstage/plugin-techdocs-backend';
|
||||
+import { DefaultCatalogCollatorFactory } from '@backstage/plugin-catalog-backend';
|
||||
+import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
|
||||
|
||||
// ...
|
||||
|
||||
const indexBuilder = new IndexBuilder({ logger, searchEngine });
|
||||
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
- collator: DefaultCatalogCollator.fromConfig(config, { discovery }),
|
||||
+ factory: DefaultCatalogCollatorFactory.fromConfig(config, { discovery }),
|
||||
});
|
||||
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
- collator: DefaultTechDocsCollator.fromConfig(config, {
|
||||
+ factory: DefaultTechDocsCollatorFactory.fromConfig(config, {
|
||||
discovery,
|
||||
logger,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
If you've written custom collators, decorators, or search engines in your
|
||||
Backstage backend instance, you will need to re-implement them as readable,
|
||||
transform, and writable streams respectively (including factory classes for
|
||||
instantiating them). [A how-to guide for refactoring](https://backstage.io/docs/features/search/how-to-guides#rewriting-alpha-style-collators-for-beta)
|
||||
existing implementations is available.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend-module-elasticsearch': minor
|
||||
---
|
||||
|
||||
**BREAKING**
|
||||
|
||||
The `ElasticSearchSearchEngine` implements the new stream-based indexing
|
||||
process expected by the latest `@backstage/search-backend-node`.
|
||||
|
||||
When updating to this version, you must also update to the latest version of
|
||||
`@backstage/search-backend-node`. Check [this upgrade guide](https://backstage.io/docs/features/search/how-to-guides#how-to-migrate-from-search-alpha-to-beta)
|
||||
for further details.
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
A `DefaultCatalogCollatorFactory`, which works with the new stream-based
|
||||
search indexing subsystem, is now available. The `DefaultCatalogCollator` will
|
||||
continue to be available for those unable to upgrade to the stream-based
|
||||
`@backstage/search-backend-node` (and related packages), however it is now
|
||||
marked as deprecated and will be removed in a future version.
|
||||
|
||||
To upgrade this plugin and the search indexing subsystem in one go, check
|
||||
[this upgrade guide](https://backstage.io/docs/features/search/how-to-guides#how-to-migrate-from-search-alpha-to-beta)
|
||||
for necessary changes to your search backend plugin configuration.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
**Breaking**: Removed optional `handleError()` from `CatalogProcessor`. This optional method is never called by the catalog processing engine and can therefore be removed.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
**BREAKING**: Moved **DefaultStarredEntitiesApi** to `@backstage/plugin-catalog`. If you were using this in tests, you can use the new `MockStarredEntitiesApi` from `@backstage/plugin-catalog-react` instead.
|
||||
|
||||
Fixed a risky behavior where `DefaultStarredEntitiesApi` forwarded values to observers that were later mutated.
|
||||
|
||||
Removed the `isStarred` method from `DefaultStarredEntitiesApi`, as it is not part of the `StarredEntitiesApi`.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Removed usage of deprecated favorite utility methods.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
'@backstage/plugin-catalog-common': patch
|
||||
---
|
||||
|
||||
**DEPRECATION**: Moved the `CatalogEntityDocument` to `@backstage/plugin-catalog-common` and deprecated the export from `@backstage/plugin-catalog-backend`.
|
||||
|
||||
A new `type` field has also been added to `CatalogEntityDocument` as a replacement for `componentType`, which is now deprecated. Both fields are still present and should be set to the same value in order to avoid issues with indexing.
|
||||
|
||||
Any search customizations need to be updated to use this new `type` field instead, including any custom frontend filters, custom frontend result components, custom search decorators, or non-default Catalog collator implementations.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
Added the following deprecations to the `catalog-react` package:
|
||||
|
||||
- **DEPRECATION**: `useEntity` will now warn if the entity has not yet been loaded, and will soon throw errors instead. If you're using the default implementation of `EntityLayout` and `EntitySwitch` then these components will ensure that there is an entity loaded before rendering children. If you're implementing your own `EntityLayout` or `EntitySwitch` or something that operates outside or adjacent to them, then use `useAsyncEntity`.
|
||||
|
||||
- **DEPRECATION**: the `loading`, `error` and `refresh` properties that are returned from `useEntity` have been deprecated, and are available on `useAsyncEntity` instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
- Replaced usage of the deprecated and now removed `rootRoute` and `catalogRouteRef`s from the `catalog-react` package
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': minor
|
||||
---
|
||||
|
||||
Removing the `EntityName` path for the `useEntityOwnership` as it has never worked correctly. Please pass in an entire `Entity` instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removing the exports of the raw components that back the `CustomFieldExtensions`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the deprecated `GithubAuth.normalizeScopes` method.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': minor
|
||||
---
|
||||
|
||||
**BREAKING**: The `TokenFactory.issueToken` used by custom sign-in resolvers now ensures that the sub claim given is a full entity reference of the format `<kind>:<namespace>/<name>`. Any existing custom sign-in resolver functions that do not supply a full entity reference must be updated.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
|
||||
---
|
||||
|
||||
Fixed bug where existing cookiecutter.json file is not used.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-msgraph': patch
|
||||
---
|
||||
|
||||
add `userExpand` config option to allow expanding a single relationship
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/techdocs-common': patch
|
||||
---
|
||||
|
||||
Modify techdocs builder to automatically append techdocs-core plugin to mkdocs.yaml file if it is missing. Adds an optional configuration item if this plugin needs to be omitted.
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
'@backstage/catalog-client': patch
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
'@backstage/plugin-catalog-graph': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-code-coverage': patch
|
||||
'@backstage/plugin-code-coverage-backend': patch
|
||||
'@backstage/plugin-fossa': patch
|
||||
'@backstage/plugin-jenkins': patch
|
||||
'@backstage/plugin-jenkins-backend': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-tech-insights': patch
|
||||
'@backstage/plugin-tech-insights-backend': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
'@backstage/plugin-techdocs-backend': patch
|
||||
'@backstage/plugin-todo-backend': patch
|
||||
---
|
||||
|
||||
Use `CompoundEntityRef` instead of `EntityName`, and `getCompoundEntityRef` instead of `getEntityName`, from `@backstage/catalog-model`.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
Updated usage of `StorageApi` to use `snapshot` method instead of `get`
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
'@backstage/catalog-model': minor
|
||||
---
|
||||
|
||||
**BREAKING**: The following changes are all breaking changes.
|
||||
|
||||
Removed `EDIT_URL_ANNOTATION` and `VIEW_URL_ANNOTATION`, `LOCATION_ANNOTATION`, `ORIGIN_LOCATION_ANNOTATION`, `LOCATION_ANNOTATION`, `SOURCE_LOCATION_ANNOTATION`. All of these constants have been prefixed with ANNOTATION to be easier to find meaning `SOURCE_LOCATION_ANNOTATION` is available as `ANNOTATION_SOURCE_LOCATION`.
|
||||
|
||||
Removed `parseLocationReference`, replaced by `parseLocationRef`.
|
||||
|
||||
Removed `stringifyLocationReference`, replaced by `stringifyLocationRef`.
|
||||
|
||||
Removed `Location` type which has been moved to `catalog-client`.
|
||||
|
||||
Removed `ENTITY_DEFAULT_NAMESPACE`, replaced by `DEFAULT_NAMESPACE`.
|
||||
|
||||
Removed `compareEntityToRef` compare using `stringifyEntityRef` instead.
|
||||
|
||||
Removed `JSONSchema` type which should be imported from `json-schema` package instead.
|
||||
|
||||
Removed utility methods: `entityHasChanges`, `generateEntityEtag`, `generateEntityUid`, `generateUpdatedEntity`.
|
||||
|
||||
Removed `ENTITY_META_GENERATED_FIELDS` and `EntityRefContext`.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
**DEPRECATION**: Deprecated the `RefreshIntervalFunction` and `createRandomRefreshInterval` in favour of the `ProcessingIntervalFunction` and `createRandomProcessingInterval` type and method respectively. Please migrate to use the new names.
|
||||
|
||||
**DEPRECATION**: Deprecated the `setRefreshInterval` and `setRefreshIntervalSeconds` methods on the `CatalogBuilder` for the new `setProcessingInterval` and `setProcessingIntervalSeconds` methods. Please migrate to use the new names.
|
||||
@@ -20,7 +20,6 @@ Autoscaling
|
||||
autoselect
|
||||
Avro
|
||||
aws
|
||||
backrub
|
||||
backported
|
||||
backporting
|
||||
Bigtable
|
||||
@@ -39,8 +38,6 @@ Changesets
|
||||
chanwit
|
||||
Chanwit
|
||||
ci
|
||||
cisphobia
|
||||
cissexist
|
||||
classname
|
||||
cli
|
||||
cloudbuild
|
||||
@@ -68,7 +65,6 @@ css
|
||||
Datadog
|
||||
dataflow
|
||||
dayjs
|
||||
deadnaming
|
||||
debounce
|
||||
Debounce
|
||||
declaratively
|
||||
@@ -171,7 +167,6 @@ Minikube
|
||||
Minio
|
||||
misconfiguration
|
||||
misconfigured
|
||||
misgendering
|
||||
mkdocs
|
||||
Mkdocs
|
||||
monorepo
|
||||
@@ -213,6 +208,7 @@ parallelization
|
||||
Patrik
|
||||
Peloton
|
||||
performant
|
||||
Performant
|
||||
plantuml
|
||||
Platformize
|
||||
Podman
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
# [Backstage](https://backstage.io)
|
||||
|
||||
_During March 7 to March 11 the maintainers will be taking part in Spotify's annual hack week. Development will continue as usual, but expect a slower pace for discussions and PR reviews. Why not take this opportunity to [build a plugin](https://backstage.io/docs/plugins/)?_
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://www.cncf.io/projects)
|
||||
[](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Search
|
||||
|
||||
Contributions/extensions to the Search plugin
|
||||
@@ -0,0 +1,95 @@
|
||||
ConfluenceCollator.ts reference
|
||||
|
||||
```ts
|
||||
import { DocumentCollator } from '@backstage/search-common';
|
||||
import fetch from 'cross-fetch';
|
||||
|
||||
export class ConfluenceCollator implements DocumentCollator {
|
||||
public readonly type: string = 'confluence';
|
||||
|
||||
async execute() {
|
||||
const ConfluenceUrlBase =
|
||||
'https://{CONFLUENCE-ORG-NAME}.atlassian.net/wiki/rest/api';
|
||||
|
||||
async function getConfluenceData(requestUrl: string) {
|
||||
var emptyJson = {};
|
||||
try {
|
||||
const res = await fetch(requestUrl, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
Authorization: `Basic ${process.env.CONFLUENCE_TOKEN}`,
|
||||
},
|
||||
});
|
||||
if (res.ok) {
|
||||
return await res.json();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
return emptyJson;
|
||||
}
|
||||
|
||||
async function getSpaces(): Promise<string[]> {
|
||||
const data = await getConfluenceData(
|
||||
`${ConfluenceUrlBase}/space?&limit=1000&type=global&status=current`,
|
||||
);
|
||||
let spacesList = [];
|
||||
if (data['results']) {
|
||||
const results = data['results'];
|
||||
for (const result of results) {
|
||||
spacesList.push(result['key']);
|
||||
}
|
||||
}
|
||||
return spacesList;
|
||||
}
|
||||
|
||||
async function getDocumentsFromSpaces(spaces: string[]): Promise<string[]> {
|
||||
let documentsList = [];
|
||||
for (var space of spaces) {
|
||||
let next = true;
|
||||
let requestUrl = `${ConfluenceUrlBase}/content?limit=1000&status=current&spaceKey=${space}`;
|
||||
while (next) {
|
||||
const data = await getConfluenceData(requestUrl);
|
||||
if (data['results']) {
|
||||
const results = data['results'];
|
||||
for (const result of results) {
|
||||
documentsList.push(result['_links']['self']);
|
||||
}
|
||||
if (data['_links']['next']) {
|
||||
requestUrl = data['_links']['base'] + data['_links']['next'];
|
||||
} else {
|
||||
next = false;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return documentsList;
|
||||
}
|
||||
|
||||
async function getDocumentInfo(documents: string[]) {
|
||||
let documentInfo = [];
|
||||
for (var documentUrl of documents) {
|
||||
const data = await getConfluenceData(
|
||||
documentUrl + '?expand=body.storage',
|
||||
);
|
||||
if (data['status'] && data['status'] == 'current') {
|
||||
const documentMetaData = {
|
||||
title: data['title'],
|
||||
text: data['body']['storage']['value'],
|
||||
location: data['_links']['base'] + data['_links']['webui'],
|
||||
};
|
||||
documentInfo.push(documentMetaData);
|
||||
}
|
||||
}
|
||||
return documentInfo;
|
||||
}
|
||||
|
||||
const spacesList = await getSpaces();
|
||||
const documentsList = await getDocumentsFromSpaces(spacesList);
|
||||
const documentMetaDataList = await getDocumentInfo(documentsList);
|
||||
return documentMetaDataList;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
ConfluenceResultListItem.tsx reference
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { Link } from '@backstage/core-components';
|
||||
import { IndexableDocument } from '@backstage/search-common';
|
||||
import {
|
||||
Divider,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
} from '@material-ui/core';
|
||||
|
||||
type Props = {
|
||||
result: IndexableDocument;
|
||||
};
|
||||
|
||||
export const ConfluenceResultListItem = ({ result }: Props) => {
|
||||
// Remove html tags from document text before displaying
|
||||
const chars = [];
|
||||
let isTag = false;
|
||||
for (const c of result.text.substring(0, 500)) {
|
||||
if (c === '<') {
|
||||
isTag = true;
|
||||
continue;
|
||||
}
|
||||
if (c === '>') {
|
||||
isTag = false;
|
||||
chars.push(' ');
|
||||
continue;
|
||||
}
|
||||
if (!isTag) {
|
||||
chars.push(c);
|
||||
}
|
||||
}
|
||||
const excerpt =
|
||||
chars.join('').substring(0, 80) + (result.text.length > 80 ? '...' : '');
|
||||
|
||||
return (
|
||||
<Link to={result.location}>
|
||||
<ListItem alignItems="center">
|
||||
<ListItemIcon>
|
||||
<img
|
||||
width="20"
|
||||
height="20"
|
||||
src="https://cdn.worldvectorlogo.com/logos/confluence-1.svg"
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primaryTypographyProps={{ variant: 'h6' }}
|
||||
primary={result.title}
|
||||
secondary={excerpt}
|
||||
/>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
# Confluence
|
||||
|
||||
These files help you add Confluence as a source to the Backstage Search plugin.
|
||||
To do so, add both files in this directory under the packages/backend/src/plugins/search/ pathway in your Backstage app.
|
||||
Then, add the following code to your packages/app/src/components/search/SearchPage.tsx:
|
||||
|
||||
```tsx
|
||||
import { ConfluenceResultListItem } from './ConfluenceResultListItem';
|
||||
```
|
||||
|
||||
```tsx
|
||||
case 'confluence':
|
||||
return (
|
||||
<ConfluenceResultListItem
|
||||
key={document.location}
|
||||
result={document}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
and the following to packages/backend/src/plugins/search.ts:
|
||||
|
||||
```ts
|
||||
import { ConfluenceCollator } from './search/ConfluenceCollator';
|
||||
```
|
||||
|
||||
```ts
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: new ConfluenceCollator(),
|
||||
});
|
||||
```
|
||||
@@ -27,6 +27,8 @@ sign-in resolvers and set them for any of the Authentication providers inside
|
||||
`@backstage/plugin-auth-backend` plugin.
|
||||
|
||||
```ts
|
||||
import { DEFAULT_NAMESPACE, stringifyEntityRef } from '@backstage/catalog-model';
|
||||
|
||||
export default async function createPlugin({
|
||||
...
|
||||
}: PluginEnvironment): Promise<Router> {
|
||||
@@ -38,22 +40,31 @@ export default async function createPlugin({
|
||||
resolver: async ({ profile: { email } }, ctx) => {
|
||||
// Call a custom validator function that checks that the email is
|
||||
// valid and on our own company's domain, and throws an Error if it
|
||||
// isn't
|
||||
// isn't.
|
||||
// TODO: Implement this function
|
||||
validateEmail(email);
|
||||
|
||||
// List of entity references that denote the identity and
|
||||
// membership of the user
|
||||
const ent = [];
|
||||
const ent: string[] = [];
|
||||
|
||||
// Let's use the username in the email ID as the user's default
|
||||
// unique identifier inside Backstage.
|
||||
const [id] = email.split('@');
|
||||
ent.push(`User:default/${id}`)
|
||||
ent.push(stringifyEntityRef({
|
||||
kind: 'User',
|
||||
namespace: DEFAULT_NAMESPACE,
|
||||
name: id,
|
||||
}));
|
||||
|
||||
// Let's call the internal LDAP provider to get a list of groups
|
||||
// that the user belongs to, and add those to the list as well
|
||||
const ldapGroups = await getLdapGroups(email);
|
||||
ldapGroups.forEach(group => ent.push(`Group:default/${group}`))
|
||||
ldapGroups.forEach(group => ent.push(stringifyEntityRef({
|
||||
kind: 'Group',
|
||||
namespace: DEFAULT_NAMESPACE,
|
||||
name: group,
|
||||
})));
|
||||
|
||||
// Issue the token containing the entity claims
|
||||
const token = await ctx.tokenIssuer.issueToken({
|
||||
|
||||
@@ -54,13 +54,14 @@ An index is a collection of such documents of a given type.
|
||||
### Collators
|
||||
|
||||
You need to be able to search something! Collators are the way to define what
|
||||
can be searched. Specifically, they're classes which return documents conforming
|
||||
to a minimum set of fields (including a document title, location, and text), but
|
||||
which can contain any other fields as defined by the collator itself. One
|
||||
collator is responsible for defining and collecting documents of a type.
|
||||
can be searched. Specifically, they're readable object streams of documents that
|
||||
conform to a minimum set of fields (including a document title, location, and
|
||||
text), but which can contain any other fields as defined by the collator itself.
|
||||
One collator is responsible for defining and collecting documents of a type.
|
||||
|
||||
Some plugins, like the Catalog Backend, provide so-called "default" collators
|
||||
which you can use out-of-the-box to start searching across Backstage quickly.
|
||||
Some plugins, like the Catalog Backend, provide so-called "default" collator
|
||||
factories which you can use out-of-the-box to start searching across Backstage
|
||||
quickly.
|
||||
|
||||
### Decorators
|
||||
|
||||
@@ -68,9 +69,15 @@ Sometimes you want to add extra information to a set of documents in your search
|
||||
index that the collator may not be aware of. For example, the Software Catalog
|
||||
knows about software entities, but it may not know about their usage or quality.
|
||||
|
||||
Decorators are classes which can add extra fields to pre-collated documents.
|
||||
This extra metadata could then be used to bias search results or otherwise
|
||||
improve the search experience in your Backstage instance.
|
||||
Decorators are transform streams which sit between a collator (read stream) and
|
||||
an indexer (write stream) during the indexing process. It can be used to add
|
||||
extra fields to documents as they are being collated and indexed. This extra
|
||||
metadata could then be used to bias search results or otherwise improve the
|
||||
search experience in your Backstage instance.
|
||||
|
||||
In addition to adding extra metadata, decorators (like any transform stream) can
|
||||
also be used to remove metadata, filter out, or even add extra documents at
|
||||
index-time.
|
||||
|
||||
### The Scheduler
|
||||
|
||||
|
||||
@@ -48,10 +48,10 @@ const app = createApp({
|
||||
## How to index TechDocs documents
|
||||
|
||||
The TechDocs plugin has supported integrations to Search, meaning that it
|
||||
provides a default collator ready to be used.
|
||||
provides a default collator factory ready to be used.
|
||||
|
||||
The purpose of this guide is to walk you through how to register the
|
||||
[DefaultTechDocsCollator](https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts)
|
||||
[DefaultTechDocsCollatorFactory](https://github.com/backstage/backstage/blob/master/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts)
|
||||
in your App, so that you can get TechDocs documents indexed.
|
||||
|
||||
If you have been through the
|
||||
@@ -60,18 +60,19 @@ you should have the `packages/backend/src/plugins/search.ts` file available. If
|
||||
so, you can go ahead and follow this guide - if not, start by going through the
|
||||
getting started guide.
|
||||
|
||||
1. Import the DefaultTechDocsCollator from `@backstage/plugin-techdocs-backend`.
|
||||
1. Import the `DefaultTechDocsCollatorFactory` from
|
||||
`@backstage/plugin-techdocs-backend`.
|
||||
|
||||
```typescript
|
||||
import { DefaultTechDocsCollator } from '@backstage/plugin-techdocs-backend';
|
||||
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
|
||||
```
|
||||
|
||||
2. Register the DefaultTechDocsCollator with the IndexBuilder.
|
||||
2. Register the `DefaultTechDocsCollatorFactory` with the IndexBuilder.
|
||||
|
||||
```typescript
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: DefaultTechDocsCollator.fromConfig(config, {
|
||||
factory: DefaultTechDocsCollatorFactory.fromConfig(config, {
|
||||
discovery,
|
||||
logger,
|
||||
tokenManager,
|
||||
@@ -131,3 +132,264 @@ indexBuilder.addCollator({
|
||||
|
||||
As shown above, you can add a catalog entity filter to narrow down what catalog
|
||||
entities are indexed by the search engine.
|
||||
|
||||
## How to migrate from Search Alpha to Beta
|
||||
|
||||
For the purposes of this guide, Search Beta version is defined as:
|
||||
|
||||
- **Search Plugin**: At least `v0.x.y`
|
||||
- **Search Backend Plugin**: At least `v0.x.y`
|
||||
- **Search Backend Node**: At least `v0.x.y`
|
||||
|
||||
In the Beta version, the Search Platform's indexing process has been rewritten
|
||||
as a stream pipeline in order to improve efficiency and performance on large
|
||||
sets of documents.
|
||||
|
||||
If you've not yet extended the Search Platform with custom code, and have
|
||||
instead taken advantage of default collators, decorators, and search engines
|
||||
provided by existing plugins, the migration process is fairly straightforward:
|
||||
|
||||
1. Upgrade to at least version `0.x.y` of
|
||||
`@backstage/plugin-search-backend-node`, as well as any backend plugins whose
|
||||
collators you are using (e.g. at least version `0.x.y` of
|
||||
`@backstage/plugin-catalog-backend` and/or version `0.x.y` of
|
||||
`@backstage/plugin-techdocs-backend`).
|
||||
2. Then, make the following changes to your
|
||||
`/packages/backend/src/plugins/search.ts` file:
|
||||
|
||||
```diff
|
||||
-import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend';
|
||||
-import { DefaultTechDocsCollator } from '@backstage/plugin-techdocs-backend';
|
||||
+import { DefaultCatalogCollatorFactory } from '@backstage/plugin-catalog-backend';
|
||||
+import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
|
||||
// ...
|
||||
const indexBuilder = new IndexBuilder({ logger, searchEngine });
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
- collator: DefaultCatalogCollator.fromConfig(config, { discovery }),
|
||||
+ factory: DefaultCatalogCollatorFactory.fromConfig(config, { discovery }),
|
||||
});
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
- collator: DefaultTechDocsCollator.fromConfig(config, {
|
||||
+ factory: DefaultTechDocsCollatorFactory.fromConfig(config, {
|
||||
discovery,
|
||||
logger,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
Any custom collators, decorators, or search engine implementations will require
|
||||
minor refactoring. Continue on for details.
|
||||
|
||||
### Rewriting alpha-style collators for beta
|
||||
|
||||
In alpha versions of the Backstage Search Platform, collators were classes that
|
||||
implemented an `execute` method which resolved an `IndexableDocument` array.
|
||||
|
||||
In beta versions, the logic encapsulated by the aforementioned `execute` method
|
||||
is contained within an [object-mode][obj-mode] `Readable` stream where each
|
||||
object pushed onto the stream is of type `IndexableDocument`. Instances of this
|
||||
stream are instantiated by a factory class conforming to the
|
||||
`DocumentCollatorFactory` interface.
|
||||
|
||||
The optimal conversion strategy will vary depending on the collator's logic, but
|
||||
the simplest conversion can follow a process like this:
|
||||
|
||||
1. Rename your collator class to something like `YourCollatorFactory` and update
|
||||
it to implement `DocumentCollatorFactory` instead of `DocumentCollator`.
|
||||
2. Update its `execute` method so that it resolves
|
||||
`AsyncGenerator<YourIndexableDocument>` instead of `YourIndexableDocument[]`.
|
||||
3. Implement `DocumentCollatorFactory`'s `getCollator` method which resolves to
|
||||
`Readable.from(this.execute())` (which is a utility for creating [readable
|
||||
streams][read-stream] from [async generators][async-gen]).
|
||||
|
||||
```ts
|
||||
import { DocumentCollatorFactory } from '@backstage/plugin-search-backend-node';
|
||||
import { Readable } from 'stream';
|
||||
export class YourCollatorFactory implements DocumentCollatorFactory {
|
||||
public readonly type: string = 'your-type';
|
||||
async *execute(): AsyncGenerator<YourIndexableDocument> {
|
||||
const widgets = await this.client.getWidgets();
|
||||
for (const widget of widgets) {
|
||||
yield {
|
||||
title: widget.name,
|
||||
location: widget.url,
|
||||
text: widget.description,
|
||||
};
|
||||
}
|
||||
}
|
||||
getCollator() {
|
||||
return Readable.from(this.execute());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: it may be possible to simplify your collator dramatically! If your custom
|
||||
collator was previously using streams under the hood (for example, by reading
|
||||
newline delimited JSON from a local or remote file), you could just expose the
|
||||
stream directly via a simple factory class:
|
||||
|
||||
```ts
|
||||
import { DocumentCollatorFactory } from '@backstage/plugin-search-backend-node';
|
||||
import { createReadStream } from 'fs';
|
||||
import { parse } from '@jsonlines/core';
|
||||
export class YourCollatorFactory implements DocumentCollatorFactory {
|
||||
public readonly type: string = 'your-type';
|
||||
async getCollator() {
|
||||
const parseStream = parse();
|
||||
return createReadStream('./documents.ndjson').pipe(parseStream);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Rewriting alpha-style decorators for beta
|
||||
|
||||
In alpha versions of the Backstage Search Platform, decorators were classes that
|
||||
implemented an `execute` method which took an `IndexableDocument` array as an
|
||||
argument, and resolved a modified array of the same type.
|
||||
|
||||
In beta versions, the logic encapsulated by the aforementioned `execute` method
|
||||
is contained within an object-mode `Transform` stream which reads objects of
|
||||
type `IndexableDocument`, and writes objects of a conforming type. Similar to
|
||||
collators, instances of this stream are instantiated by a factory class
|
||||
conforming to the `DocumentDecoratorFactory` interface.
|
||||
|
||||
Although you can choose to implement a `Transform` stream from scratch, the
|
||||
`@backstage/plugin-search-backend-node` package provides a `DecoratorBase` class
|
||||
in order to simplify the developer experience. With this base class, all that's
|
||||
needed is to transfer your old decorator class logic into the base class' three
|
||||
methods (`initialize`, `decorate`, and `finalize`), and implement the factory
|
||||
class that instantiates the stream:
|
||||
|
||||
```ts
|
||||
import { DecoratorBase } from '@backstage/plugin-search-backend-node';
|
||||
export class YourDecorator extends DecoratorBase {
|
||||
async initialize() {
|
||||
// Setup logic. Performed once before any documents are consumed.
|
||||
}
|
||||
async decorate(
|
||||
document: YourIndexableDocument,
|
||||
): Promise<YourIndexableDocument | YourIndexableDocument[] | undefined> {
|
||||
// Perform transformation logic here.
|
||||
return document;
|
||||
}
|
||||
async finalize() {
|
||||
// Teardown logic. Performed once after all documents have been consumed.
|
||||
}
|
||||
}
|
||||
export class YourDecoratorFactory implements DocumentDecoratorFactory {
|
||||
async getDecorator() {
|
||||
return new YourDecorator();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note the return type of the `decorate` method and how each can be used to
|
||||
different effect.
|
||||
|
||||
- By resolving a single `YourIndexableDocument` object, your decorator can be
|
||||
used to make simple transformations:
|
||||
|
||||
```ts
|
||||
class BooleanWidgetCoolnessDecorator extends DecoratorBase {
|
||||
async decorator(widget) {
|
||||
// Perform a simple, 1:1 transformation.
|
||||
widget.isCool = widget.isCool === 'true' ? true : false;
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- By resolving `undefined`, your decorator can filter out documents which
|
||||
shouldn't be in the index:
|
||||
|
||||
```ts
|
||||
class OnlyCoolWidgetsDecorator extends DecoratorBase {
|
||||
async decorator(widget) {
|
||||
// Perform a simple filter operation.
|
||||
return widget.isCool ? widget : undefined;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- By resolving an array of `YourIndexableDocument` objects, you can generate
|
||||
multiple documents based on the content of one:
|
||||
|
||||
```ts
|
||||
class WidgetByVariantDecorator extends DecoratorBase {
|
||||
async decorator(widget) {
|
||||
// Generate one widget doc per widget variant.
|
||||
return widget.variants.map(variant => {
|
||||
// Each widget doc is the given widget plus a "variant" property
|
||||
// pulled from a widget.variants string array.
|
||||
return {
|
||||
...widget,
|
||||
variant,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In alpha versions, a decorator had access to every `IndexableDocument`
|
||||
simultaneously. This is no longer possible in beta versions (precisely to make
|
||||
the indexing process more efficient and performant). You will need to modify
|
||||
your decorator's logic so that it does not need access to every document at
|
||||
once.
|
||||
|
||||
### Rewriting alpha-style search engines for beta
|
||||
|
||||
Search Engines are responsible for both querying and indexing documents to an
|
||||
underlying search engine technology. While the search engine query interface
|
||||
didn't change between alpha and beta versions, the indexing half of the
|
||||
interface _did_ change.
|
||||
|
||||
In alpha versions of the Backstage Search Platform, a search engine implemented
|
||||
an `index` method which took a `type` and an `IndexableDocument` array and was
|
||||
responsible for writing these documents to the underlying search engine.
|
||||
|
||||
In beta versions, the logic encapsulated by the aforementioned `index` method is
|
||||
contained within an object-mode `Writable` stream which expects objects of type
|
||||
`IndexableDocument`. On the search engine class itself, the `index` method is
|
||||
replaced with a `getIndexer` factory method which still takes the `type`, but
|
||||
resolves an instance of the aforementioned `Writable` stream.
|
||||
|
||||
Although you can choose to implement a `Writable` stream from scratch, the
|
||||
`@backstage/plugin-search-backend-node` package provides a
|
||||
`BatchSearchEngineIndexer` class in order to simplify the developer experience.
|
||||
With this base class, which collects documents in batches of a configurable size
|
||||
on your behalf, all that's needed is to transfer your old `index` method logic
|
||||
into the base class' three methods (`initialize`, `index`, and `finalize`), and
|
||||
implement the factory method that instantiates the stream:
|
||||
|
||||
```ts
|
||||
import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node';
|
||||
import { SearchEngine } from '@backstage/search-common';
|
||||
export class YourSearchEngineIndexer extends BatchSearchEngineIndexer {
|
||||
constructor({ type }: { type: string }) {
|
||||
// Customize the number of documents passed to the index method per batch.
|
||||
super({ batchSize: 500 });
|
||||
// An imaginary search engine indexing client.
|
||||
this.index = new SomeSearchEngineIndex({ indexName: type });
|
||||
}
|
||||
async initialize() {
|
||||
// Setup logic. Performed once before any documents are consumed.
|
||||
}
|
||||
async index(documents: IndexableDocument[]) {
|
||||
await this.index.batchOf(documents);
|
||||
}
|
||||
async finalize() {
|
||||
// Teardown logic. Performed once after all documents have been consumed.
|
||||
}
|
||||
}
|
||||
export class YourSearchEngine implements SearchEngine {
|
||||
async getIndexer(type: string) {
|
||||
return new YourSearchEngineIndexer({ type });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[obj-mode]: https://nodejs.org/docs/latest-v14.x/api/stream.html#stream_object_mode
|
||||
[read-stream]: https://nodejs.org/docs/latest-v14.x/api/stream.html#stream_readable_streams
|
||||
[async-gen]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of#iterating_over_async_generators
|
||||
|
||||
@@ -57,7 +57,7 @@ The recommended way of instantiating the catalog backend classes is to use the
|
||||
`CatalogBuilder`, as illustrated in the
|
||||
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts).
|
||||
We will create a new
|
||||
[`EntityProvider`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/providers/types.ts)
|
||||
[`EntityProvider`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/api/provider.ts)
|
||||
subclass that can be added to this catalog builder.
|
||||
|
||||
Let's make a simple provider that can refresh a set of entities based on a
|
||||
@@ -355,7 +355,7 @@ The recommended way of instantiating the catalog backend classes is to use the
|
||||
`CatalogBuilder`, as illustrated in the
|
||||
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts).
|
||||
We will create a new
|
||||
[`CatalogProcessor`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/ingestion/processors/types.ts)
|
||||
[`CatalogProcessor`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/api/processor.ts)
|
||||
subclass that can be added to this catalog builder.
|
||||
|
||||
It is up to you where you put the code for this new processor class. For quick
|
||||
|
||||
@@ -130,6 +130,8 @@ Options:
|
||||
if not found.
|
||||
--etag <ETAG> A unique identifier for the prepared tree e.g. commit SHA. If provided it will be stored
|
||||
in techdocs_metadata.json.
|
||||
--omitTechdocsCoreMkdocsPlugin An option to disable automatic addition of techdocs-core plugin to the mkdocs.yaml files.
|
||||
Defaults to false, which means that the techdocs-core plugin is always added to the mkdocs file.
|
||||
-v --verbose Enable verbose output. (default: false)
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
@@ -46,6 +46,24 @@ between `techdocs-backend` and the storage)
|
||||
|
||||
[TechDocs Backend](https://github.com/backstage/backstage/tree/master/plugins/techdocs-backend)
|
||||
|
||||
## TechDocs Build Strategy
|
||||
|
||||
To accommodate more complex logic surrounding whether or not to build TechDocs, the TechDocs backend
|
||||
supports selecting a Build Strategy.
|
||||
The Build Strategy is responsible for deciding whether the documentation requested should be built locally
|
||||
by the TechDocs backend or not.
|
||||
Customization of the Build Strategy allows for more complex behaviour regarding whether the TechDocs backend
|
||||
is responsible for building TechDocs, whether an external process is responsible, or whether a combination
|
||||
of local builds and an external process is responsible, on an entity-by-entity basis.
|
||||
|
||||
The default Build Strategy results in the TechDocs backend building documentation locally if the
|
||||
`techdocs.builder` configuration option is set to `'local'`, and skipping any building otherwise.
|
||||
However any logic that satisfies the Build Strategy interface can be implemented, using the Backstage
|
||||
config as well as the entity being processed to make a decision.
|
||||
|
||||
For an example of how the Build Strategy can be used to implement a 'hybrid' build model, refer to
|
||||
the [How to implement a hybrid build strategy](./how-to-guides.md#how-to-implement-a-hybrid-build-strategy) guide.
|
||||
|
||||
## TechDocs Container
|
||||
|
||||
The TechDocs container is a Docker container available at
|
||||
|
||||
@@ -37,12 +37,22 @@ techdocs:
|
||||
|
||||
pullImage: true
|
||||
|
||||
mkdocs:
|
||||
# (Optional) techdocs.generator.omitTechdocsCoreMkdocsPlugin can be used to disable automatic addition of techdocs-core plugin to the mkdocs.yaml files.
|
||||
# Defaults to false, which means that the techdocs-core plugin is always added to the mkdocs file.
|
||||
omitTechdocsCorePlugin: false
|
||||
|
||||
# techdocs.builder can be either 'local' or 'external.
|
||||
# If builder is set to 'local' and you open a TechDocs page, techdocs-backend will try to generate the docs, publish to storage
|
||||
# and show the generated docs afterwords. This is the "Basic" setup of the TechDocs Architecture.
|
||||
# If builder is set to 'external', techdocs-backend will only fetch the docs and will NOT try to generate and publish. In this case of 'external',
|
||||
# we assume that docs are being built by an external process (e.g. in the CI/CD pipeline of the repository). This is the "Recommended" setup of
|
||||
# the architecture. Read more here https://backstage.io/docs/features/techdocs/architecture
|
||||
# Using the default build strategy, if builder is set to 'local' and you open a TechDocs page,
|
||||
# techdocs-backend will try to generate the docs, publish to storage and show the generated docs afterwords.
|
||||
# This is the "Basic" setup of the TechDocs Architecture.
|
||||
# Using the default build strategy, if builder is set to 'external' (or anything other than 'local'), techdocs-backend
|
||||
# will only fetch the docs and will NOT try to generate and publish.
|
||||
# In this case, we assume that docs are being built by an external process (e.g. in the CI/CD pipeline of the repository).
|
||||
# This is the "Recommended" setup of the architecture.
|
||||
# Note that custom build strategies may alter this behaviour.
|
||||
# Read more about the "Basic" and "Recommended" setups here https://backstage.io/docs/features/techdocs/architecture
|
||||
# Read more about build strategies here: https://backstage.io/docs/features/techdocs/concepts#techdocs-build-strategy
|
||||
|
||||
builder: 'local'
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ plugins:
|
||||
- techdocs-core
|
||||
```
|
||||
|
||||
> Note - The plugins section above is optional. Backstage automatically adds the `techdocs-core` plugin to the
|
||||
> mkdocs file if it is missing. This functionality can be turned off with a [configuration option](./configuration.md) in Backstage.
|
||||
|
||||
Update your component's entity description by adding the following lines to its
|
||||
`catalog-info.yaml` in the root of its repository:
|
||||
|
||||
|
||||
@@ -538,3 +538,58 @@ Done! Now you have a support of the following diagrams along with mermaid:
|
||||
- `Vega`
|
||||
- `Vega-Lite`
|
||||
- `WaveDrom`
|
||||
|
||||
## How to implement a hybrid build strategy
|
||||
|
||||
One limitation of the [Recommended deployment](./architecture.md#recommended-deployment) is that
|
||||
the experience for users requires modifying their CI/CD process to publish
|
||||
their TechDocs. For some users, this may be unnecessary, and provides a barrier
|
||||
to entry for onboarding users to Backstage. However, a purely local TechDocs
|
||||
build restricts TechDocs creators to using the tooling provided in Backstage,
|
||||
as well as the plugins and features provided in the Backstage-included `mkdocs`
|
||||
installation.
|
||||
|
||||
To accommodate both of these use-cases, users can implement a custom [Build Strategy](./concepts.md#techdocs-build-strategy)
|
||||
with logic to encode which TechDocs should be built locally, and which will be
|
||||
built externally.
|
||||
|
||||
To achieve this hybrid build model:
|
||||
|
||||
1. In your Backstage instance's `app-config.yaml`, set `techdocs.builder` to
|
||||
`'local'`. This ensures that Backstage will build docs for users who want the
|
||||
'out-of-the-box' experience.
|
||||
2. Configure external storage of TechDocs as normal for a production deployment.
|
||||
This allows Backstage to publish documentation to your storage, as well as
|
||||
allowing other users to publish documentation from their CI/CD pipelines.
|
||||
3. Create a custom build strategy, that implements the `DocsBuildStrategy` interface,
|
||||
and which implements your custom logic for determining whether to build docs for
|
||||
a given entity.
|
||||
For example, to only build docs when an entity has the `company.com/techdocs-builder`
|
||||
annotation set to `'local'`:
|
||||
|
||||
```typescript
|
||||
export class AnnotationBasedBuildStrategy {
|
||||
private readonly config: Config;
|
||||
|
||||
constructor(config: Config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
async shouldBuild(_: Entity): Promise<boolean> {
|
||||
return (
|
||||
this.entity.metadata?.annotations?.['company.com/techdocs-builder'] ===
|
||||
'local'
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. Pass an instance of this Build Strategy as the `docsBuildStrategy` parameter of the
|
||||
TechDocs backend `createRouter` method.
|
||||
|
||||
Users should now be able to choose to have their documentation built and published by
|
||||
the TechDocs backend by adding the `company.com/techdocs-builder` annotation to their
|
||||
entity. If the value of this annotation is `'local'`, the TechDocs backend will build
|
||||
and publish the documentation for them. If the value of the `company.com/techdocs-builder`
|
||||
annotation is anything other than `'local'`, the user is responsible for publishing
|
||||
documentation to the appropriate location in the TechDocs external storage.
|
||||
|
||||
@@ -552,3 +552,36 @@ The following is an excerpt of a typical setup of an isomorphic library package:
|
||||
},
|
||||
"files": ["dist"],
|
||||
```
|
||||
|
||||
## Experimental Type Build
|
||||
|
||||
The Backstage CLI has an experimental feature where multiple different type definition files can be generated for different release stages. The release stages are marked in the [TSDoc](https://tsdoc.org/) for each individual export, using either `@public`, `@alpha`, or `@beta`. Rather than just building a single `index.d.ts` file, the build process will instead output `index.d.ts`, `index.beta.d.ts`, and `index.alpha.d.ts`. Each of these files will have exports from more unstable release stages stripped, meaning that `index.d.ts` will omit all exports marked with `@alpha` or `@beta`, while `index.beta.d.ts` will omit all exports marked with `@alpha`.
|
||||
|
||||
This feature is aimed at projects that publish to package registries and wish to maintain different levels of API stability within each package. There is no need to use this within a single monorepo, as it has no effect due to only applying to built and published packages.
|
||||
|
||||
In order for the experimental type build to work, `@microsoft/api-extractor` must be installed in your project, as it is an optional peer dependency of the Backstage CLI. There are then three steps that need to be taken for each package where you want to enable this feature:
|
||||
|
||||
- Add the `--experimental-type-build` flag to the `"build"` script of the package.
|
||||
- Add either one or both of `"alphaTypes"` and `"betaTypes"` to the `"publishConfig"` of the package:
|
||||
```json
|
||||
"publishConfig": {
|
||||
...
|
||||
"types": "dist/index.d.ts",
|
||||
"alphaTypes": "dist/index.alpha.d.ts",
|
||||
"betaTypes": "dist/index.beta.d.ts"
|
||||
},
|
||||
```
|
||||
- Add either one or both of `"alpha"` and `"beta"` to the `"files"` of the package:
|
||||
```json
|
||||
"files": [
|
||||
"dist",
|
||||
"alpha",
|
||||
"beta"
|
||||
]
|
||||
```
|
||||
|
||||
Once this setup is complete, users of the published packages will only be able to access the stable API via the main package entry point, for example `@acme/my-plugin`. Exports marked with `@alpha` or `@beta` will only be available via the `/alpha` entry point, for example `@acme/my-plugin/alpha`, and exports marked with `@beta` will only be available via `/beta`. This does not apply within the monorepo that contains the package. There all exports still have to be imported via the main entry point.
|
||||
|
||||
Note that these different entry points are only separated during type checking. At runtime they all share the same code which contains the exports from all releases stages.
|
||||
|
||||
An example of this setup can be seen in the [`@backstage/catalog-model`](https://github.com/backstage/backstage/blob/da0675bf9f28ed1460f03635a22d3c26abd14707/packages/catalog-model/package.json#L14) package, which has enabled `alpha` type exports. With this setup, exports marked as `@alpha` are only available for import via `@backstage/catalog-model/alpha`. The `@backstage/catalog-model` package currently does not have any exports marked as `@beta`, or a `/beta` entry point.
|
||||
|
||||
@@ -310,7 +310,7 @@ backend:
|
||||
backend:
|
||||
cache:
|
||||
store: redis
|
||||
connection: user:pass@cache.example.com:6379
|
||||
connection: redis://user:pass@cache.example.com:6379
|
||||
```
|
||||
|
||||
Contributions supporting other cache stores are welcome!
|
||||
|
||||
@@ -43,9 +43,11 @@ backend:
|
||||
+ user: ${POSTGRES_USER}
|
||||
+ password: ${POSTGRES_PASSWORD}
|
||||
+ # https://node-postgres.com/features/ssl
|
||||
+ #ssl: require # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
|
||||
+ #ca: # if you have a CA file and want to verify it you can uncomment this section
|
||||
+ #$file: <file-path>/ca/server.crt
|
||||
+ # you can set the sslmode configuration option via the `PGSSLMODE` environment variable
|
||||
+ # see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
|
||||
+ # ssl:
|
||||
+ # ca: # if you have a CA file and want to verify it you can uncomment this section
|
||||
+ # $file: <file-path>/ca/server.crt
|
||||
```
|
||||
|
||||
If you have an `app-config.local.yaml` for local development, a similar update
|
||||
|
||||
+1
-3
@@ -45,9 +45,7 @@
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"**/@graphql-codegen/cli/**/ws": "^7.4.6",
|
||||
"**/@roadiehq/**/@backstage/plugin-catalog": "*",
|
||||
"**/@roadiehq/**/@backstage/catalog-model": "*"
|
||||
"**/@graphql-codegen/cli/**/ws": "^7.4.6"
|
||||
},
|
||||
"version": "0.69.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -21,16 +21,13 @@ import {
|
||||
ErrorAlerter,
|
||||
GoogleAuth,
|
||||
GithubAuth,
|
||||
OAuth2,
|
||||
OktaAuth,
|
||||
GitlabAuth,
|
||||
Auth0Auth,
|
||||
MicrosoftAuth,
|
||||
BitbucketAuth,
|
||||
OAuthRequestManager,
|
||||
WebStorage,
|
||||
UrlPatternDiscovery,
|
||||
SamlAuth,
|
||||
OneLoginAuth,
|
||||
UnhandledErrorForwarder,
|
||||
AtlassianAuth,
|
||||
@@ -49,16 +46,12 @@ import {
|
||||
oauthRequestApiRef,
|
||||
googleAuthApiRef,
|
||||
githubAuthApiRef,
|
||||
oauth2ApiRef,
|
||||
oktaAuthApiRef,
|
||||
gitlabAuthApiRef,
|
||||
auth0AuthApiRef,
|
||||
microsoftAuthApiRef,
|
||||
storageApiRef,
|
||||
configApiRef,
|
||||
samlAuthApiRef,
|
||||
oneloginAuthApiRef,
|
||||
oidcAuthApiRef,
|
||||
bitbucketAuthApiRef,
|
||||
atlassianAuthApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
@@ -197,46 +190,6 @@ export const apis = [
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: auth0AuthApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
oauthRequestApi: oauthRequestApiRef,
|
||||
configApi: configApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
|
||||
Auth0Auth.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: oauth2ApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
oauthRequestApi: oauthRequestApiRef,
|
||||
configApi: configApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
|
||||
OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: samlAuthApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
configApi: configApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, configApi }) =>
|
||||
SamlAuth.create({
|
||||
discoveryApi,
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: oneloginAuthApiRef,
|
||||
deps: {
|
||||
@@ -251,25 +204,6 @@ export const apis = [
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: oidcAuthApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
oauthRequestApi: oauthRequestApiRef,
|
||||
configApi: configApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
|
||||
OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
provider: {
|
||||
id: 'oidc',
|
||||
title: 'Your Identity Provider',
|
||||
icon: () => null,
|
||||
},
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: bitbucketAuthApiRef,
|
||||
deps: {
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
import { EntityLayout } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
DefaultStarredEntitiesApi,
|
||||
EntityProvider,
|
||||
starredEntitiesApiRef,
|
||||
MockStarredEntitiesApi,
|
||||
} from '@backstage/plugin-catalog-react';
|
||||
import { githubActionsApiRef } from '@backstage/plugin-github-actions';
|
||||
import { permissionApiRef } from '@backstage/plugin-permission-react';
|
||||
import {
|
||||
MockPermissionApi,
|
||||
MockStorageApi,
|
||||
renderInTestApp,
|
||||
TestApiProvider,
|
||||
} from '@backstage/test-utils';
|
||||
@@ -59,12 +58,7 @@ describe('EntityPage Test', () => {
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[githubActionsApiRef, mockedApi],
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new DefaultStarredEntitiesApi({
|
||||
storageApi: MockStorageApi.create(),
|
||||
}),
|
||||
],
|
||||
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
|
||||
[permissionApiRef, mockPermissionApi],
|
||||
]}
|
||||
>
|
||||
|
||||
@@ -19,27 +19,12 @@ import {
|
||||
gitlabAuthApiRef,
|
||||
oktaAuthApiRef,
|
||||
githubAuthApiRef,
|
||||
samlAuthApiRef,
|
||||
microsoftAuthApiRef,
|
||||
oneloginAuthApiRef,
|
||||
oauth2ApiRef,
|
||||
oidcAuthApiRef,
|
||||
bitbucketAuthApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
export const providers = [
|
||||
{
|
||||
id: 'oidc-auth-provider',
|
||||
title: 'Oidc',
|
||||
message: 'Sign In using OpenId Connect',
|
||||
apiRef: oidcAuthApiRef,
|
||||
},
|
||||
{
|
||||
id: 'oauth2-auth-provider',
|
||||
title: 'OAuth 2.0',
|
||||
message: 'Sign In using OAuth 2.0',
|
||||
apiRef: oauth2ApiRef,
|
||||
},
|
||||
{
|
||||
id: 'google-auth-provider',
|
||||
title: 'Google',
|
||||
@@ -70,12 +55,6 @@ export const providers = [
|
||||
message: 'Sign In using Okta',
|
||||
apiRef: oktaAuthApiRef,
|
||||
},
|
||||
{
|
||||
id: 'saml-auth-provider',
|
||||
title: 'SAML',
|
||||
message: 'Sign In using SAML',
|
||||
apiRef: samlAuthApiRef,
|
||||
},
|
||||
{
|
||||
id: 'onelogin-auth-provider',
|
||||
title: 'OneLogin',
|
||||
|
||||
@@ -234,6 +234,21 @@ export type ErrorHandlerOptions = {
|
||||
logClientErrors?: boolean;
|
||||
};
|
||||
|
||||
// @public
|
||||
export class FetchUrlReader implements UrlReader {
|
||||
static factory: ReaderFactory;
|
||||
// (undocumented)
|
||||
read(url: string): Promise<Buffer>;
|
||||
// (undocumented)
|
||||
readTree(): Promise<ReadTreeResponse>;
|
||||
// (undocumented)
|
||||
readUrl(url: string, options?: ReadUrlOptions): Promise<ReadUrlResponse>;
|
||||
// (undocumented)
|
||||
search(): Promise<SearchResponse>;
|
||||
// (undocumented)
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type FromReadableArrayOptions = Array<{
|
||||
data: Readable;
|
||||
|
||||
Vendored
+1
-1
@@ -137,7 +137,7 @@ export interface Config {
|
||||
| {
|
||||
store: 'redis';
|
||||
/**
|
||||
* A redis connection string in the form `user:pass@host:port`.
|
||||
* A redis connection string in the form `redis://user:pass@host:port`.
|
||||
* @secret
|
||||
*/
|
||||
connection: string;
|
||||
|
||||
+3
-4
@@ -195,14 +195,13 @@ describe('CacheManager', () => {
|
||||
});
|
||||
|
||||
it('returns a Redis client when configured', () => {
|
||||
const redisHostAndPort = '127.0.0.1:6379';
|
||||
const expectedHost = `redis://${redisHostAndPort}`;
|
||||
const redisConnection = 'redis://127.0.0.1:6379';
|
||||
const manager = CacheManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
cache: {
|
||||
store: 'redis',
|
||||
connection: redisHostAndPort,
|
||||
connection: redisConnection,
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -218,7 +217,7 @@ describe('CacheManager', () => {
|
||||
expect(mockCacheCalls[0][0].store).toBeInstanceOf(KeyvRedis);
|
||||
const redis = KeyvRedis as jest.Mock;
|
||||
const mockRedisCalls = redis.mock.calls.splice(-1);
|
||||
expect(mockRedisCalls[0][0]).toEqual(expectedHost);
|
||||
expect(mockRedisCalls[0][0]).toEqual(redisConnection);
|
||||
});
|
||||
|
||||
describe('connection errors', () => {
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ export class CacheManager {
|
||||
return new Keyv({
|
||||
namespace: pluginId,
|
||||
ttl: defaultTtl,
|
||||
store: new KeyvRedis(`redis://${this.connection}`),
|
||||
store: new KeyvRedis(this.connection),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -270,22 +270,6 @@ describe('BitbucketUrlReader', () => {
|
||||
|
||||
expect(response.etag).toBe('12ab34cd56ef');
|
||||
});
|
||||
|
||||
it('should throw error when apiBaseUrl is missing', () => {
|
||||
expect(() => {
|
||||
/* eslint-disable no-new */
|
||||
new BitbucketUrlReader(
|
||||
new BitbucketIntegration(
|
||||
readBitbucketIntegrationConfig(
|
||||
new ConfigReader({
|
||||
host: 'bitbucket.mycompany.net',
|
||||
}),
|
||||
),
|
||||
),
|
||||
{ treeResponseFactory },
|
||||
);
|
||||
}).toThrowError('must configure an explicit apiBaseUrl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search hosted', () => {
|
||||
|
||||
@@ -62,14 +62,9 @@ export class BitbucketUrlReader implements UrlReader {
|
||||
private readonly integration: BitbucketIntegration,
|
||||
private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },
|
||||
) {
|
||||
const { host, apiBaseUrl, token, username, appPassword } =
|
||||
integration.config;
|
||||
const { host, token, username, appPassword } = integration.config;
|
||||
|
||||
if (!apiBaseUrl) {
|
||||
throw new Error(
|
||||
`Bitbucket integration for '${host}' must configure an explicit apiBaseUrl`,
|
||||
);
|
||||
} else if (!token && username && !appPassword) {
|
||||
if (!token && username && !appPassword) {
|
||||
throw new Error(
|
||||
`Bitbucket integration for '${host}' has configured a username but is missing a required appPassword.`,
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@ export { BitbucketUrlReader } from './BitbucketUrlReader';
|
||||
export { GithubUrlReader } from './GithubUrlReader';
|
||||
export { GitlabUrlReader } from './GitlabUrlReader';
|
||||
export { AwsS3UrlReader } from './AwsS3UrlReader';
|
||||
export { FetchUrlReader } from './FetchUrlReader';
|
||||
export type {
|
||||
FromReadableArrayOptions,
|
||||
ReaderFactory,
|
||||
|
||||
@@ -115,6 +115,7 @@ describe('DockerContainerRunner', () => {
|
||||
Env: envVarsArray,
|
||||
WorkingDir: workingDir,
|
||||
HostConfig: {
|
||||
AutoRemove: true,
|
||||
Binds: expect.arrayContaining([
|
||||
`${path.join(rootDir, 'input')}:/input`,
|
||||
`${path.join(rootDir, 'output')}:/output`,
|
||||
@@ -207,6 +208,7 @@ describe('DockerContainerRunner', () => {
|
||||
logStream,
|
||||
expect.objectContaining({
|
||||
HostConfig: {
|
||||
AutoRemove: true,
|
||||
Binds: [],
|
||||
},
|
||||
Volumes: {},
|
||||
|
||||
@@ -105,6 +105,7 @@ export class DockerContainerRunner implements ContainerRunner {
|
||||
await this.dockerClient.run(imageName, args, logStream, {
|
||||
Volumes,
|
||||
HostConfig: {
|
||||
AutoRemove: true,
|
||||
Binds,
|
||||
},
|
||||
...(workingDir ? { WorkingDir: workingDir } : {}),
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
useHotCleanup,
|
||||
} from '@backstage/backend-common';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend';
|
||||
import { DefaultCatalogCollatorFactory } from '@backstage/plugin-catalog-backend';
|
||||
import { createRouter } from '@backstage/plugin-search-backend';
|
||||
import { ElasticSearchSearchEngine } from '@backstage/plugin-search-backend-module-elasticsearch';
|
||||
import { PgSearchEngine } from '@backstage/plugin-search-backend-module-pg';
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
LunrSearchEngine,
|
||||
SearchEngine,
|
||||
} from '@backstage/plugin-search-backend-node';
|
||||
import { DefaultTechDocsCollator } from '@backstage/plugin-techdocs-backend';
|
||||
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
|
||||
import { Logger } from 'winston';
|
||||
import { PluginEnvironment } from '../types';
|
||||
|
||||
@@ -70,7 +70,7 @@ export default async function createPlugin({
|
||||
// particular collator gathers entities from the software catalog.
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: DefaultCatalogCollator.fromConfig(config, {
|
||||
factory: DefaultCatalogCollatorFactory.fromConfig(config, {
|
||||
discovery,
|
||||
tokenManager,
|
||||
}),
|
||||
@@ -78,7 +78,7 @@ export default async function createPlugin({
|
||||
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: DefaultTechDocsCollator.fromConfig(config, {
|
||||
factory: DefaultTechDocsCollatorFactory.fromConfig(config, {
|
||||
discovery,
|
||||
logger,
|
||||
tokenManager,
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
|
||||
// @public
|
||||
export type AddLocationRequest = {
|
||||
@@ -38,8 +38,13 @@ export interface CatalogApi {
|
||||
request: GetEntityAncestorsRequest,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<GetEntityAncestorsResponse>;
|
||||
// @deprecated
|
||||
getEntityByName(
|
||||
name: EntityName,
|
||||
name: CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined>;
|
||||
getEntityByRef(
|
||||
entityRef: string | CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined>;
|
||||
getEntityFacets(
|
||||
@@ -91,7 +96,11 @@ export class CatalogClient implements CatalogApi {
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<GetEntityAncestorsResponse>;
|
||||
getEntityByName(
|
||||
compoundName: EntityName,
|
||||
compoundName: CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined>;
|
||||
getEntityByRef(
|
||||
entityRef: string | CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined>;
|
||||
getEntityFacets(
|
||||
@@ -130,18 +139,6 @@ export class CatalogClient implements CatalogApi {
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type CatalogEntitiesRequest = GetEntitiesRequest;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type CatalogEntityAncestorsRequest = GetEntityAncestorsRequest;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type CatalogEntityAncestorsResponse = GetEntityAncestorsResponse;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type CatalogListResponse<_Entity> = GetEntitiesResponse;
|
||||
|
||||
// @public
|
||||
export interface CatalogRequestOptions {
|
||||
// (undocumented)
|
||||
|
||||
@@ -195,6 +195,60 @@ describe('CatalogClient', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEntityByRef', () => {
|
||||
const existingEntity: Entity = {
|
||||
apiVersion: 'v1',
|
||||
kind: 'CustomKind',
|
||||
metadata: {
|
||||
namespace: 'default',
|
||||
name: 'exists',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
rest.get(
|
||||
`${mockBaseUrl}/entities/by-name/customkind/default/exists`,
|
||||
(_, res, ctx) => {
|
||||
return res(ctx.json(existingEntity));
|
||||
},
|
||||
),
|
||||
rest.get(
|
||||
`${mockBaseUrl}/entities/by-name/customkind/default/missing`,
|
||||
(_, res, ctx) => {
|
||||
return res(ctx.status(404));
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('finds by string and compound', async () => {
|
||||
await expect(
|
||||
client.getEntityByRef('customkind:default/exists'),
|
||||
).resolves.toEqual(existingEntity);
|
||||
await expect(
|
||||
client.getEntityByRef({
|
||||
kind: 'CustomKind',
|
||||
namespace: 'default',
|
||||
name: 'exists',
|
||||
}),
|
||||
).resolves.toEqual(existingEntity);
|
||||
});
|
||||
|
||||
it('returns undefined for 404s', async () => {
|
||||
await expect(
|
||||
client.getEntityByRef('customkind:default/missing'),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(
|
||||
client.getEntityByRef({
|
||||
kind: 'CustomKind',
|
||||
namespace: 'default',
|
||||
name: 'missing',
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLocationById', () => {
|
||||
const defaultResponse = {
|
||||
data: {
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
ANNOTATION_LOCATION,
|
||||
ANNOTATION_ORIGIN_LOCATION,
|
||||
Entity,
|
||||
EntityName,
|
||||
CompoundEntityRef,
|
||||
parseEntityRef,
|
||||
stringifyEntityRef,
|
||||
stringifyLocationRef,
|
||||
@@ -170,11 +170,32 @@ export class CatalogClient implements CatalogApi {
|
||||
return { items: entities.sort(refCompare) };
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc CatalogApi.getEntityByRef}
|
||||
*/
|
||||
async getEntityByRef(
|
||||
entityRef: string | CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined> {
|
||||
const { kind, namespace, name } = parseEntityRef(entityRef);
|
||||
return this.requestOptional(
|
||||
'GET',
|
||||
`/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent(
|
||||
namespace,
|
||||
)}/${encodeURIComponent(name)}`,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
// NOTE(freben): When we deprecate getEntityByName from the interface, we may
|
||||
// still want to leave this implementation in place for quite some time
|
||||
// longer, to minimize the risk for breakages. Suggested date for removal:
|
||||
// August 2022
|
||||
/**
|
||||
* {@inheritdoc CatalogApi.getEntityByName}
|
||||
*/
|
||||
async getEntityByName(
|
||||
compoundName: EntityName,
|
||||
compoundName: CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined> {
|
||||
const { kind, namespace = 'default', name } = compoundName;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity, EntityName } from '@backstage/catalog-model';
|
||||
import { CompoundEntityRef, Entity } from '@backstage/catalog-model';
|
||||
|
||||
/**
|
||||
* This symbol can be used in place of a value when passed to filters in e.g.
|
||||
@@ -306,11 +306,25 @@ export interface CatalogApi {
|
||||
* Gets a single entity from the catalog by its ref (kind, namespace, name)
|
||||
* triplet.
|
||||
*
|
||||
* @param entityRef - A complete entity ref, either on string or compound form
|
||||
* @param options - Additional options
|
||||
* @returns The matching entity, or undefined if there was no entity with that ref
|
||||
*/
|
||||
getEntityByRef(
|
||||
entityRef: string | CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined>;
|
||||
|
||||
/**
|
||||
* Gets a single entity from the catalog by its ref (kind, namespace, name)
|
||||
* triplet.
|
||||
*
|
||||
* @deprecated Use getEntityRef instead
|
||||
* @param name - A complete entity ref
|
||||
* @param options - Additional options
|
||||
*/
|
||||
getEntityByName(
|
||||
name: EntityName,
|
||||
name: CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Entity | undefined>;
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
GetEntitiesRequest,
|
||||
GetEntitiesResponse,
|
||||
GetEntityAncestorsRequest,
|
||||
GetEntityAncestorsResponse,
|
||||
} from './api';
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use GetEntitiesRequest instead
|
||||
*/
|
||||
export type CatalogEntitiesRequest = GetEntitiesRequest;
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use GetEntitiesResponse instead
|
||||
*/
|
||||
export type CatalogListResponse<_Entity> = GetEntitiesResponse;
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use GetEntityAncestorsRequest instead
|
||||
*/
|
||||
export type CatalogEntityAncestorsRequest = GetEntityAncestorsRequest;
|
||||
/**
|
||||
* @public
|
||||
* @deprecated use GetEntityAncestorsResponse instead
|
||||
*/
|
||||
export type CatalogEntityAncestorsResponse = GetEntityAncestorsResponse;
|
||||
@@ -28,5 +28,4 @@ export type {
|
||||
GetEntityFacetsRequest,
|
||||
GetEntityFacetsResponse,
|
||||
} from './api';
|
||||
export * from './deprecated';
|
||||
export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status';
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
```ts
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { JSONSchema7 } from 'json-schema';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { SerializedError } from '@backstage/errors';
|
||||
|
||||
// @alpha
|
||||
@@ -66,23 +64,6 @@ export class CommonValidatorFunctions {
|
||||
static isValidUrl(value: unknown): boolean;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
export function compareEntityToRef(
|
||||
entity: Entity,
|
||||
ref:
|
||||
| string
|
||||
| {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name: string;
|
||||
}
|
||||
| EntityName,
|
||||
context?: {
|
||||
defaultKind?: string;
|
||||
defaultNamespace?: string;
|
||||
},
|
||||
): boolean;
|
||||
|
||||
// @public
|
||||
interface ComponentEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
@@ -107,6 +88,13 @@ export { ComponentEntityV1alpha1 };
|
||||
// @public
|
||||
export const componentEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public
|
||||
export type CompoundEntityRef = {
|
||||
kind: string;
|
||||
namespace: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const DEFAULT_NAMESPACE = 'default';
|
||||
|
||||
@@ -134,9 +122,6 @@ export { DomainEntityV1alpha1 };
|
||||
// @public
|
||||
export const domainEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public @deprecated
|
||||
export const EDIT_URL_ANNOTATION = 'backstage.io/edit-url';
|
||||
|
||||
// @public
|
||||
export type Entity = {
|
||||
apiVersion: string;
|
||||
@@ -146,16 +131,6 @@ export type Entity = {
|
||||
relations?: EntityRelation[];
|
||||
};
|
||||
|
||||
// @public @deprecated
|
||||
export const ENTITY_DEFAULT_NAMESPACE = 'default';
|
||||
|
||||
// @public @deprecated
|
||||
export const ENTITY_META_GENERATED_FIELDS: readonly [
|
||||
'uid',
|
||||
'etag',
|
||||
'generation',
|
||||
];
|
||||
|
||||
// @public
|
||||
export type EntityEnvelope = {
|
||||
apiVersion: string;
|
||||
@@ -171,9 +146,6 @@ export function entityEnvelopeSchemaValidator<
|
||||
T extends EntityEnvelope = EntityEnvelope,
|
||||
>(schema?: unknown): (data: unknown) => T;
|
||||
|
||||
// @public @deprecated
|
||||
export function entityHasChanges(previous: Entity, next: Entity): boolean;
|
||||
|
||||
// @public
|
||||
export function entityKindSchemaValidator<T extends Entity>(
|
||||
schema: unknown,
|
||||
@@ -201,12 +173,8 @@ export type EntityMeta = JsonObject & {
|
||||
links?: EntityLink[];
|
||||
};
|
||||
|
||||
// @public
|
||||
export type EntityName = {
|
||||
kind: string;
|
||||
namespace: string;
|
||||
name: string;
|
||||
};
|
||||
// @public @deprecated
|
||||
export type EntityName = CompoundEntityRef;
|
||||
|
||||
// @public
|
||||
export const EntityPolicies: {
|
||||
@@ -228,16 +196,10 @@ export type EntityRef =
|
||||
name: string;
|
||||
};
|
||||
|
||||
// @public @deprecated
|
||||
export type EntityRefContext = {
|
||||
defaultKind?: string;
|
||||
defaultNamespace?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type EntityRelation = {
|
||||
type: string;
|
||||
target: EntityName;
|
||||
target: CompoundEntityRef;
|
||||
targetRef: string;
|
||||
};
|
||||
|
||||
@@ -269,17 +231,11 @@ export class FieldFormatEntityPolicy implements EntityPolicy {
|
||||
enforce(entity: Entity): Promise<Entity>;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
export function generateEntityEtag(): string;
|
||||
|
||||
// @public @deprecated
|
||||
export function generateEntityUid(): string;
|
||||
|
||||
// @public @deprecated
|
||||
export function generateUpdatedEntity(previous: Entity, next: Entity): Entity;
|
||||
|
||||
// @public
|
||||
export function getEntityName(entity: Entity): EntityName;
|
||||
export function getCompoundEntityRef(entity: Entity): CompoundEntityRef;
|
||||
|
||||
// @public @deprecated
|
||||
export const getEntityName: typeof getCompoundEntityRef;
|
||||
|
||||
// @public
|
||||
export function getEntitySourceLocation(entity: Entity): {
|
||||
@@ -312,11 +268,6 @@ export { GroupEntityV1alpha1 };
|
||||
// @public
|
||||
export const groupEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public @deprecated
|
||||
export type JSONSchema = JSONSchema7 & {
|
||||
[key in string]?: JsonValue;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type KindValidator = {
|
||||
check(entity: Entity): Promise<boolean>;
|
||||
@@ -342,15 +293,6 @@ export class KubernetesValidatorFunctions {
|
||||
static isValidObjectName(value: unknown): boolean;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
type Location_2 = {
|
||||
id: string;
|
||||
} & LocationSpec;
|
||||
export { Location_2 as Location };
|
||||
|
||||
// @public @deprecated
|
||||
export const LOCATION_ANNOTATION = 'backstage.io/managed-by-location';
|
||||
|
||||
// @public
|
||||
interface LocationEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
@@ -388,10 +330,6 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy {
|
||||
enforce(entity: Entity): Promise<Entity>;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
export const ORIGIN_LOCATION_ANNOTATION =
|
||||
'backstage.io/managed-by-origin-location';
|
||||
|
||||
// @public @deprecated
|
||||
export function parseEntityName(
|
||||
ref:
|
||||
@@ -405,7 +343,7 @@ export function parseEntityName(
|
||||
defaultKind?: string;
|
||||
defaultNamespace?: string;
|
||||
},
|
||||
): EntityName;
|
||||
): CompoundEntityRef;
|
||||
|
||||
// @public
|
||||
export function parseEntityRef(
|
||||
@@ -420,7 +358,7 @@ export function parseEntityRef(
|
||||
defaultKind?: string;
|
||||
defaultNamespace?: string;
|
||||
},
|
||||
): EntityName;
|
||||
): CompoundEntityRef;
|
||||
|
||||
// @public
|
||||
export function parseLocationRef(ref: string): {
|
||||
@@ -428,12 +366,6 @@ export function parseLocationRef(ref: string): {
|
||||
target: string;
|
||||
};
|
||||
|
||||
// @public @deprecated
|
||||
export function parseLocationReference(ref: string): {
|
||||
type: string;
|
||||
target: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export const RELATION_API_CONSUMED_BY = 'apiConsumedBy';
|
||||
|
||||
@@ -503,9 +435,6 @@ export class SchemaValidEntityPolicy implements EntityPolicy {
|
||||
enforce(entity: Entity): Promise<Entity>;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
export const SOURCE_LOCATION_ANNOTATION = 'backstage.io/source-location';
|
||||
|
||||
// @public
|
||||
export function stringifyEntityRef(
|
||||
ref:
|
||||
@@ -523,12 +452,6 @@ export function stringifyLocationRef(ref: {
|
||||
target: string;
|
||||
}): string;
|
||||
|
||||
// @public @deprecated
|
||||
export function stringifyLocationReference(ref: {
|
||||
type: string;
|
||||
target: string;
|
||||
}): string;
|
||||
|
||||
// @public
|
||||
interface SystemEntityV1alpha1 extends Entity {
|
||||
// (undocumented)
|
||||
@@ -581,7 +504,4 @@ export type Validators = {
|
||||
isValidAnnotationValue(value: unknown): boolean;
|
||||
isValidTag(value: unknown): boolean;
|
||||
};
|
||||
|
||||
// @public @deprecated
|
||||
export const VIEW_URL_ANNOTATION = 'backstage.io/view-url';
|
||||
```
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
"@backstage/config": "^0.1.15",
|
||||
"@backstage/errors": "^0.2.2",
|
||||
"@backstage/types": "^0.1.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"ajv": "^7.0.3",
|
||||
"json-schema": "^0.4.0",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -46,6 +45,7 @@
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.14.1",
|
||||
"@types/jest": "^26.0.7",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"@types/lodash": "^4.14.151",
|
||||
"yaml": "^1.9.2"
|
||||
},
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { EntityName } from '../types';
|
||||
import { CompoundEntityRef } from '../types';
|
||||
import { EntityStatus } from './EntityStatus';
|
||||
|
||||
/**
|
||||
@@ -201,7 +201,7 @@ export type EntityRelation = {
|
||||
*
|
||||
* @deprecated use targetRef instead
|
||||
*/
|
||||
target: EntityName;
|
||||
target: CompoundEntityRef;
|
||||
|
||||
/**
|
||||
* The entity ref of the target of this relation.
|
||||
|
||||
@@ -14,14 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The namespace that entities without an explicit namespace fall into.
|
||||
*
|
||||
* @public
|
||||
* @deprecated use {@link DEFAULT_NAMESPACE} instead.
|
||||
*/
|
||||
export const ENTITY_DEFAULT_NAMESPACE = 'default';
|
||||
|
||||
/**
|
||||
* The namespace that entities without an explicit namespace fall into.
|
||||
*
|
||||
@@ -29,34 +21,6 @@ export const ENTITY_DEFAULT_NAMESPACE = 'default';
|
||||
*/
|
||||
export const DEFAULT_NAMESPACE = 'default';
|
||||
|
||||
/**
|
||||
* The keys of EntityMeta that are auto-generated.
|
||||
*
|
||||
* @public
|
||||
* @deprecated will be removed in a future release.
|
||||
*/
|
||||
export const ENTITY_META_GENERATED_FIELDS = [
|
||||
'uid',
|
||||
'etag',
|
||||
'generation',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Annotation for linking to entity page from catalog pages.
|
||||
*
|
||||
* @public
|
||||
* @deprecated use {@link ANNOTATION_VIEW_URL} instead.
|
||||
*/
|
||||
export const VIEW_URL_ANNOTATION = 'backstage.io/view-url';
|
||||
|
||||
/**
|
||||
* Annotation for linking to entity edit page from catalog pages.
|
||||
*
|
||||
* @public
|
||||
* @deprecated use {@link ANNOTATION_EDIT_URL} instead.
|
||||
*/
|
||||
export const EDIT_URL_ANNOTATION = 'backstage.io/edit-url';
|
||||
|
||||
/**
|
||||
* Annotation for linking to entity page from catalog pages.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user