Merge remote-tracking branch 'upstream/master' into airbrake-no-projectid-no-error

This commit is contained in:
Karan Shah
2022-03-03 14:53:56 +00:00
525 changed files with 7449 additions and 3861 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/catalog-model': patch
---
Move `@types/json-schema` to be a dev dependency
+10
View File
@@ -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
+10
View File
@@ -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`
+13
View File
@@ -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
```
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs-backend': patch
---
Added a new interface that allows for customization of when to build techdocs
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-msgraph': patch
---
add config option `groupExpand` to allow expanding a single relationship
+20
View File
@@ -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
+5
View File
@@ -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.
+12
View File
@@ -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';
```
+13
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
DockerContainerRunner.runContainer now automatically removes the container when its execution terminates
+7
View File
@@ -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
+5
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': patch
---
**DEPRECATED**: The `results` export, and instead adding `processingResult` with the same shape and purpose.
+5
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
Deprecated `favoriteEntityTooltip` and `favoriteEntityIcon` since the utility value is very low.
+9
View File
@@ -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.
+7
View File
@@ -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$`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-permission-common': patch
---
Add api doc comments to `Permission` type properties.
+14
View File
@@ -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`
+8
View File
@@ -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.
+8
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Export FetchUrlReader to facilitate more flexible configuration of the backend.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': minor
---
**BREAKING**: Removed export of `GithubSession` and `SamlSession` which are only used internally.
+5
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': patch
---
Deprecated the `BitbucketRepositoryParser` type.
+5
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': minor
---
Marked `useEntityPermission` as alpha since the underlying permission framework is under active development.
+5
View File
@@ -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.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-permission-node': patch
---
Export some utility functions for parsing PermissionCriteria
`isAndCriteria`, `isOrCriteria`, `isNotCriteria` are now exported.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-msgraph': patch
---
add documentation for config options `userGroupMemberSearch` and `groupSearch`
+10
View File
@@ -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).
+5
View File
@@ -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.
+6
View File
@@ -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.
+5
View File
@@ -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.
+12
View File
@@ -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.
+13
View File
@@ -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.
+43
View File
@@ -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.
+13
View File
@@ -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.
+5
View File
@@ -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.
+9
View File
@@ -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`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-catalog': patch
'@backstage/plugin-techdocs': patch
---
Removed usage of deprecated favorite utility methods.
+10
View File
@@ -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.
+10
View File
@@ -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.
+5
View File
@@ -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
+5
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': minor
---
**BREAKING**: Removing the exports of the raw components that back the `CustomFieldExtensions`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': minor
---
**BREAKING**: Removed the deprecated `GithubAuth.normalizeScopes` method.
+5
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
---
Fixed bug where existing cookiecutter.json file is not used.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-msgraph': patch
---
add `userExpand` config option to allow expanding a single relationship
+5
View File
@@ -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.
+22
View File
@@ -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`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/core-components': patch
'@backstage/plugin-catalog-react': patch
---
Updated usage of `StorageApi` to use `snapshot` method instead of `get`
+23
View File
@@ -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`.
+7
View File
@@ -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.
+1 -5
View File
@@ -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
View File
@@ -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/)?_
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![CNCF Status](https://img.shields.io/badge/cncf%20status-sandbox-blue.svg)](https://www.cncf.io/projects)
[![Main CI Build](https://github.com/backstage/backstage/workflows/Main%20Master%20Build/badge.svg)](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22)
+3
View File
@@ -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>
);
};
```
+32
View File
@@ -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(),
});
```
+15 -4
View File
@@ -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({
+16 -9
View File
@@ -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
+268 -6
View File
@@ -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
+2
View File
@@ -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
```
+18
View File
@@ -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
+15 -5
View File
@@ -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:
+55
View File
@@ -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.
+33
View File
@@ -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.
+1 -1
View File
@@ -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!
+5 -3
View File
@@ -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
View File
@@ -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],
]}
>
-21
View File
@@ -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',
+15
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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 } : {}),
+4 -4
View File
@@ -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,
+12 -15
View File
@@ -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: {
+23 -2
View File
@@ -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;
+16 -2
View File
@@ -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';
+16 -96
View File
@@ -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';
```
+1 -1
View File
@@ -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"
},
+2 -2
View File
@@ -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