removed unused dependency react-router-dom

This commit is contained in:
mufaddal motiwala
2021-11-29 13:48:13 +05:30
304 changed files with 17419 additions and 1031 deletions
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/errors': patch
---
Deprecate `parseErrorResponse` in favour of `parseErrorResponseBody`. Deprecate `data` field inside `ErrorResponse` in favour of `body`.
Rename the error name for unknown errors from `unknown` to `error`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/integration': patch
---
Narrow the types returned by the request option functions, to only the specifics that they actually do return. The reason for this change is that a full `RequestInit` is unfortunate to return because it's different between `cross-fetch` and `node-fetch`.
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/plugin-tech-insights-backend': patch
'@backstage/plugin-tech-insights-backend-module-jsonfc': patch
---
Update README docs to use correct function/parameter names
+51
View File
@@ -0,0 +1,51 @@
---
'@backstage/create-app': patch
---
Incorporate usage of the tokenManager into the backend created using `create-app`.
In existing backends, update the `PluginEnvironment` to include a `tokenManager`:
```diff
// packages/backend/src/types.ts
...
import {
...
+ TokenManager,
} from '@backstage/backend-common';
export type PluginEnvironment = {
...
+ tokenManager: TokenManager;
};
```
Then, create a `ServerTokenManager`. This can either be a `noop` that requires no secret and validates all requests by default, or one that uses a secret from your `app-config.yaml` to generate and validate tokens.
```diff
// packages/backend/src/index.ts
...
import {
...
+ ServerTokenManager,
} from '@backstage/backend-common';
...
function makeCreateEnv(config: Config) {
...
// CHOOSE ONE
// TokenManager not requiring a secret
+ const tokenManager = ServerTokenManager.noop();
// OR TokenManager requiring a secret
+ const tokenManager = ServerTokenManager.fromConfig(config);
...
return (plugin: string): PluginEnvironment => {
...
- return { logger, cache, database, config, reader, discovery };
+ return { logger, cache, database, config, reader, discovery, tokenManager };
};
}
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder': patch
---
Bump `react-jsonschema-form`
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-auth-backend': patch
---
Switched to using the standardized JSON error responses for all provider endpoints.
+19
View File
@@ -0,0 +1,19 @@
---
'@backstage/config-loader': patch
'@backstage/plugin-auth-backend': patch
'@backstage/plugin-badges-backend': patch
'@backstage/plugin-bitrise': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-catalog-backend-module-msgraph': patch
'@backstage/plugin-code-coverage-backend': patch
'@backstage/plugin-fossa': patch
'@backstage/plugin-jenkins-backend': patch
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
'@backstage/plugin-sonarqube': patch
'@backstage/plugin-tech-insights-backend': patch
'@backstage/plugin-techdocs-backend': patch
'@backstage/plugin-todo-backend': patch
---
Align on usage of `cross-fetch` vs `node-fetch` in frontend vs backend packages, and remove some unnecessary imports of either one of them
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Switch the default test coverage provider from the jest default one to `'v8'`, which provides much better coverage information when using the default Backstage test setup. This is considered a bug fix as the current coverage information is often very inaccurate.
+28
View File
@@ -0,0 +1,28 @@
---
'@backstage/plugin-techdocs-backend': minor
---
**BREAKING** `DefaultTechDocsCollator` has a new required option `tokenManager`. See the create-app changelog for how to create a `tokenManager` and add it to the `PluginEnvironment`. It can then be passed to the collator in `createPlugin`:
```diff
// packages/backend/src/plugins/search.ts
...
export default async function createPlugin({
...
+ tokenManager,
}: PluginEnvironment) {
...
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: DefaultTechDocsCollator.fromConfig(config, {
discovery,
logger,
+ tokenManager,
}),
});
...
}
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Disable ES transforms in tests transformed by the `jestSucraseTransform.js`. This is not considered a breaking change since all code is already transpiled this way in the development setup.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/create-app': patch
---
DefaultTechDocsCollator is now included in the search backend, and the Search Page updated with the SearchType component that includes the techdocs type
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Create a `TokenManager` interface and `ServerTokenManager` implementation to generate and validate server tokens for authenticated backend-to-backend API requests.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/cli': patch
'@techdocs/cli': patch
---
Bump react-dev-utils to v12
-34
View File
@@ -1,34 +0,0 @@
---
'@backstage/backend-common': patch
'@backstage/cli': patch
'@backstage/core-app-api': patch
'@backstage/create-app': patch
'@backstage/techdocs-common': patch
'@backstage/plugin-auth-backend': patch
'@backstage/plugin-azure-devops-backend': patch
'@backstage/plugin-badges-backend': patch
'@backstage/plugin-bazaar-backend': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-code-coverage-backend': patch
'@backstage/plugin-github-actions': patch
'@backstage/plugin-jenkins-backend': patch
'@backstage/plugin-proxy-backend': patch
'@backstage/plugin-rollbar-backend': patch
'@backstage/plugin-search-backend': patch
'@backstage/plugin-techdocs': patch
'@backstage/plugin-techdocs-backend': patch
---
Change default port of backend from 7000 to 7007.
This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start.
You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values:
```
backend:
listen: 0.0.0.0:7123
baseUrl: http://localhost:7123
```
More information can be found here: https://backstage.io/docs/conf/writing
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-permission-common': minor
---
Accept configApi rather than enabled flag in PermissionClient constructor.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-plugin-api': patch
---
Tweaked the logged deprecation warning for `createRouteRef` to hopefully make it more clear.
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/plugin-config-schema': patch
'@backstage/plugin-scaffolder': patch
---
Fixed a missing `await` when throwing server side errors
-42
View File
@@ -1,42 +0,0 @@
---
'@backstage/plugin-catalog-backend': minor
---
**BREAKING** EntitiesSearchFilter fields have changed.
EntitiesSearchFilter now has only two fields: `key` and `value`. The `matchValueIn` and `matchValueExists` fields are no longer are supported. Previous filters written using the `matchValueIn` and `matchValueExists` fields can be rewritten as follows:
Filtering by existence of key only:
```diff
filter: {
{
key: 'abc',
- matchValueExists: true,
},
}
```
Filtering by key and values:
```diff
filter: {
{
key: 'abc',
- matchValueExists: true,
- matchValueIn: ['xyz'],
+ values: ['xyz'],
},
}
```
Negation of filters can now be achieved through a `not` object:
```
filter: {
not: {
key: 'abc',
values: ['xyz'],
},
}
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-backend': patch
---
Index User entities by displayName to be able to search by full name. Added displayName (if present) to the 'text' field in the indexed document.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-auth-backend': patch
---
Expose catalog lib in plugin-auth-backend, i.e `CatalogIdentityClient` class is exposed now.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Update the default routes to use id instead of title
-63
View File
@@ -1,63 +0,0 @@
---
'@backstage/core-app-api': patch
'@backstage/test-utils': patch
---
The `ApiRegistry` from `@backstage/core-app-api` class has been deprecated and will be removed in a future release. To replace it, we have introduced two new helpers that are exported from `@backstage/test-utils`, namely `TestApiProvider` and `TestApiRegistry`.
These two new helpers are more tailored for writing tests and development setups, as they allow for partial implementations of each of the APIs.
When migrating existing code it is typically best to prefer usage of `TestApiProvider` when possible, so for example the following code:
```tsx
render(
<ApiProvider
apis={ApiRegistry.from([
[identityApiRef, mockIdentityApi as unknown as IdentityApi]
])}
>
{...}
</ApiProvider>
)
```
Would be migrated to this:
```tsx
render(
<TestApiProvider apis={[[identityApiRef, mockIdentityApi]]}>
{...}
</TestApiProvider>
)
```
In cases where the `ApiProvider` is used in a more standalone way, for example to reuse a set of APIs across multiple tests, the `TestApiRegistry` can be used instead. Note that the `TestApiRegistry` only has a single static factory method, `.from()`, and it is slightly different from the existing `.from()` method on `ApiRegistry` in that it doesn't require the API pairs to be wrapped in an outer array.
Usage that looks like this:
```ts
const apis = ApiRegistry.with(
identityApiRef,
mockIdentityApi as unknown as IdentityApi,
).with(configApiRef, new ConfigReader({}));
```
OR like this:
```ts
const apis = ApiRegistry.from([
[identityApiRef, mockIdentityApi as unknown as IdentityApi],
[configApiRef, new ConfigReader({})],
]);
```
Would be migrated to this:
```ts
const apis = TestApiRegistry.from(
[identityApiRef, mockIdentityApi],
[configApiRef, new ConfigReader({})],
);
```
If your app is still using the `ApiRegistry` to construct the `apis` for `createApp`, we recommend that you move over to use the new method of supplying API factories instead, using `createApiFactory`.
+17
View File
@@ -0,0 +1,17 @@
---
'@backstage/plugin-scaffolder': patch
---
Add group filtering to the scaffolder page so that individuals can surface specific templates to end users ahead of others, or group templates together. This can be accomplished by passing in a `groups` prop to the `ScaffolderPage`
```
<ScaffolderPage
groups={[
{
title: "Recommended",
filter: entity =>
entity?.metadata?.tags?.includes('recommended') ?? false,
},
]}
/>
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core-components': patch
---
Pin sidebar by default for easier navigation
+27
View File
@@ -0,0 +1,27 @@
---
'@backstage/plugin-catalog-backend': minor
---
**BREAKING** `DefaultCatalogCollator` has a new required option `tokenManager`. See the create-app changelog for how to create a `tokenManager` and add it to the `PluginEnvironment`. It can then be passed to the collator in `createPlugin`:
```diff
// packages/backend/src/plugins/search.ts
...
export default async function createPlugin({
...
+ tokenManager,
}: PluginEnvironment) {
...
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: DefaultCatalogCollator.fromConfig(config, {
discovery,
+ tokenManager,
}),
});
...
}
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-graphiql': patch
---
Letting GraphiQL use headers
+7
View File
@@ -18,6 +18,13 @@
/plugins/techdocs-backend @backstage/techdocs-core
/plugins/ilert @backstage/reviewers @yacut
/plugins/home @backstage/techdocs-core
/plugins/azure-devops @backstage/reviewers @marleypowell @awanlin
/plugins/azure-devops-backend @backstage/reviewers @marleypowell @awanlin
/plugins/azure-devops-common @backstage/reviewers @marleypowell @awanlin
/tech-insights-backend @backstage/reviewers @xantier @iain-b
/tech-insights-backend-module-jsonfc @backstage/reviewers @xantier @iain-b
/tech-insights-tech-insights-common @backstage/reviewers @xantier @iain-b
/tech-insights-tech-insights-node @backstage/reviewers @xantier @iain-b
/packages/embedded-techdocs-app @backstage/techdocs-core
/packages/search-common @backstage/techdocs-core
/packages/techdocs-cli @backstage/techdocs-core
-21
View File
@@ -1,21 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- plugin
- help wanted
- good first issue
- rfc
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
+1
View File
@@ -189,6 +189,7 @@ oidc
Okta
onboarding
Onboarding
OpenShift
orgs
pagerduty
pageview
+30
View File
@@ -0,0 +1,30 @@
name: 'Stale workflow'
on:
workflow_dispatch:
schedule:
- cron: '*/10 * * * *' # run every 10 minutes as it also removes labels.
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@main
id: stale
with:
stale-issue-message: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
days-before-issue-stale: 60
days-before-issue-close: 7
exempt-issue-labels: 'pinned,security,plugin,help wanted,good first issue,rfc'
stale-issue-label: stale
stale-pr-message: >
This PR has been automatically marked as stale because it has not had
recent activity from the author. It will be closed if no further activity occurs.
If you are the author and the PR has been closed, feel free to re-open the PR and continue the contribution!
days-before-pr-stale: 7
days-before-pr-close: 3
exempt-pr-labels: reviewer-approved,awaiting-review
stale-pr-label: stale
operations-per-run: 100
+1
View File
@@ -71,3 +71,4 @@
| [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! |
| [Globo](https://globo.com) | [Carlos Gusmão](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. |
| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly 🚀 |
| [LogMeIn](https://www.logmein.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. |
+5
View File
@@ -23,6 +23,11 @@ app:
title: '#backstage'
backend:
# Used for enabling authentication, secret is shared by all backend plugins
# See backend-to-backend-auth.md in the docs for information on the format
# auth:
# keys:
# - secret: ${BACKEND_SECRET}
baseUrl: http://localhost:7007
listen:
port: 7007
@@ -1,7 +1,13 @@
{{- $frontendUrl := urlParse .Values.appConfig.app.baseUrl}}
{{- $backendUrl := urlParse .Values.appConfig.backend.baseUrl}}
{{- $lighthouseUrl := urlParse .Values.appConfig.lighthouse.baseUrl}}
{{/* Determine the api type for the ingress */}}
{{- if lt .Capabilities.KubeVersion.Minor "19" }}
apiVersion: networking.k8s.io/v1beta1
{{- else if ge .Capabilities.KubeVersion.Minor "19" }}
apiVersion: networking.k8s.io/v1
{{- end }}
kind: Ingress
metadata:
name: {{ include "backstage.fullname" . }}-ingress
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

+13 -3
View File
@@ -154,13 +154,17 @@ import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend';
export default async function createPlugin({
logger,
discovery,
tokenManager,
}: PluginEnvironment) {
const searchEngine = new LunrSearchEngine({ logger });
const indexBuilder = new IndexBuilder({ logger, searchEngine });
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: new DefaultCatalogCollator({ discovery }),
collator: new DefaultCatalogCollator({
discovery,
tokenManager,
}),
});
const { scheduler } = await indexBuilder.build();
@@ -285,7 +289,10 @@ const indexBuilder = new IndexBuilder({ logger, searchEngine });
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: new DefaultCatalogCollator({ discovery }),
collator: new DefaultCatalogCollator({
discovery,
tokenManager,
}),
});
indexBuilder.addCollator({
@@ -303,6 +310,9 @@ its `defaultRefreshIntervalSeconds` value, like this:
```typescript {3}
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: new DefaultCatalogCollator({ discovery }),
collator: new DefaultCatalogCollator({
discovery,
tokenManager,
}),
});
```
+2 -1
View File
@@ -2,7 +2,7 @@
id: how-to-guides
title: Search "HOW TO" guides
sidebar_label: "HOW TO" guides
description: Search "HOW TO" guides
description: Search "HOW TO" guides
---
## How to implement your own Search API
@@ -74,6 +74,7 @@ indexBuilder.addCollator({
collator: DefaultTechDocsCollator.fromConfig(config, {
discovery,
logger,
tokenManager,
}),
});
```
@@ -53,3 +53,30 @@ You can do so by including the following lines in the last step of your
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install cookiecutter
```
### Customizing the ScaffolderPage with Grouping and Filtering
Once you have more than a few software templates you may want to customize your
`ScaffolderPage` by grouping and surfacing certain templates together. You can
accomplish this by creating `groups` and passing them to your `ScaffolderPage`
like below
```
<ScaffolderPage
groups={[
{
title: "Recommended",
filter: entity =>
entity?.metadata?.tags?.includes('recommended') ?? false,
},
]}
/>
```
This code will group all templates with the 'recommended' tag together at the
top of the page above any other templates not filtered by this group or others.
You can also further customize groups by passing in a `titleComponent` instead
of a `title` which will be a component to use as the header instead of just the
default `ContentHeader` with the `title` set as it's value.
![Grouped Templates](../../assets/software-templates/grouped-templates.png)
+49
View File
@@ -0,0 +1,49 @@
---
id: discovery
title: Azure DevOps Discovery
sidebar_label: Discovery
# prettier-ignore
description: Automatically discovering catalog entities from repositories in an Azure DevOps organization
---
The Azure DevOps integration has a special discovery processor for discovering
catalog entities within an Azure DevOps. The processor will crawl the Azure
DevOps organization and register entities matching the configured path. This can
be useful as an alternative to static locations or manually adding things to the
catalog.
To use the discovery processor, you'll need a GitHub integration
[set up](locations.md) with a `AZURE_TOKEN`. Then you can add a location target
to the catalog configuration:
```yaml
catalog:
locations:
# Scan all repositories for a catalog-info.yaml in the root of the default branch
- type: azure-discovery
target: https://dev.azure.com/myorg/myproject
# Or use a custom pattern for a subset of all repositories with default repository
- type: azure-discovery
target: https://dev.azure.com/myorg/myproject/_git/service-*
# Or use a custom file format and location
- type: azure-discovery
target: https://dev.azure.com/myorg/myproject/_git/*?path=/src/*/catalog-info.yaml
```
Note the `azure-discovery` type, as this is not a regular `url` processor.
When using a custom pattern, the target is composed of five parts:
- The base instance URL, `https://dev.azure.com` in this case
- The organization name which is required, `myorg` in this case
- The project name which is required, `myproject` in this case
- The repository blob to scan, which accepts \* wildcard tokens and must be
added after `_git/`. This can simply be `*` to scan all repositories in the
project.
- The path within each repository to find the catalog YAML file. This will
usually be `/catalog-info.yaml`, `/src/*/catalog-info.yaml` or a similar
variation for catalog files stored in the root directory of each repository.
_Note:_ the path parameter follows the same rules as the search on Azure DevOps
web interface. For more details visit the
[official search documentation](https://docs.microsoft.com/en-us/azure/devops/project/search/get-started-search?view=azure-devops)
+1 -1
View File
@@ -27,7 +27,7 @@ point building on top of the previous one:
and the new APIs can be used in parallel. This deprecation must have been
released for at least two weeks before the deprecated API is removed in a
minor version bump.
- **3** - The time limit for the deprecation is 3 months instead of two days.
- **3** - The time limit for the deprecation is 3 months instead of two weeks.
TL;DR:
+68
View File
@@ -0,0 +1,68 @@
---
id: backend-to-backend-auth
title: Backend-to-Backend Authentication
description:
Guide for authenticating API requests between Backstage plugin backends
---
This tutorial describes the steps needed to handle _backend-to-backend
authentication_, which allows plugin backends to determine whether a given
request originates from a legitimate Backstage backend by verifying a token
signed with a shared secret. This system has limited use for now, but will be
needed to support the upcoming framework for permissions and authorization (see
[the PRFC on the topic](https://github.com/backstage/backstage/pull/7761) for
more details).
Backends have no concept of a Backstage identity, so instead they use a token
generated using a shared key stored in config. You can generate a unique key for
your app in a terminal, and set the `BACKEND_SECRET` environment variable to the
resulting value.
```bash
node -p 'require("crypto").randomBytes(24).toString("base64")'
```
Requests originating from a backend plugin can be authenticated by decorating
them with a backend token. Backend tokens can be generated using a
`TokenManager`, which can be passed to plugin backends via the
`PluginEnvironment`. The `TokenManager` provided in new Backstage instances
generated by `create-app` is a stub, which returns empty tokens and accepts any
input string as valid. To enable backend-to-backend authentication, you'll need
to instantiate a new one using the secret from your config instead:
```diff
// packages/backend/src/index.ts
function makeCreateEnv(config: Config) {
const root = getRootLogger();
const reader = UrlReaders.default({ logger: root, config });
const discovery = SingleHostDiscovery.fromConfig(config);
root.info(`Created UrlReader ${reader}`);
const cacheManager = CacheManager.fromConfig(config);
const databaseManager = DatabaseManager.fromConfig(config);
- const tokenManager = ServerTokenManager.noop();
+ const tokenManager = ServerTokenManager.fromConfig(config);
```
With this `tokenManager`, you can then generate a server token for requests:
```typescript
const { token } = await this.tokenManager.getToken();
const response = await fetch(pluginBackendApiUrl, {
method: 'GET',
headers: {
...headers,
Authorization: `Bearer ${token}`,
},
});
```
You can use the same `tokenManager` to authenticate tokens supplied on incoming
requests:
```typescript
await tokenManager.authenticate(token); // throws if token is invalid
```
+1 -1
View File
@@ -19,7 +19,7 @@
"@spotify/prettier-config": "^12.0.0",
"docusaurus": "^2.0.0-alpha.70",
"js-yaml": "^4.1.0",
"prettier": "^2.4.1",
"prettier": "^2.5.0",
"yarn-lock-check": "^1.0.5"
},
"prettier": "@spotify/prettier-config"
+5 -1
View File
@@ -125,7 +125,11 @@
{
"type": "subcategory",
"label": "Azure",
"ids": ["integrations/azure/locations", "integrations/azure/org"]
"ids": [
"integrations/azure/locations",
"integrations/azure/discovery",
"integrations/azure/org"
]
},
{
"type": "subcategory",
+4 -4
View File
@@ -5190,10 +5190,10 @@ prepend-http@^2.0.0:
resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
prettier@^2.4.1:
version "2.4.1"
resolved "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c"
integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==
prettier@^2.5.0:
version "2.5.0"
resolved "https://registry.npmjs.org/prettier/-/prettier-2.5.0.tgz#a6370e2d4594e093270419d9cc47f7670488f893"
integrity sha512-FM/zAKgWTxj40rH03VxzIPdXmj39SwSjwG0heUcNFwI+EMZJnY93yAiKXM3dObIKAM5TA88werc8T/EwhB45eg==
prismjs@^1.22.0:
version "1.25.0"
+1
View File
@@ -88,6 +88,7 @@ nav:
- Discovery: 'integrations/aws-s3/discovery.md'
- Azure:
- Locations: 'integrations/azure/locations.md'
- Discovery: 'integrations/azure/discovery.md'
- Org Data: 'integrations/azure/org.md'
- Bitbucket:
- Locations: 'integrations/bitbucket/locations.md'
+2
View File
@@ -30,6 +30,8 @@
"prettier:check": "prettier --check .",
"lerna": "lerna",
"storybook": "yarn workspace storybook start",
"snyk:test": "npx snyk test --yarn-workspaces --strict-out-of-sync=false",
"snyk:test:package": "yarn snyk:test --include",
"build-storybook": "yarn workspace storybook build-storybook",
"techdocs-cli": "node scripts/techdocs-cli.js",
"techdocs-cli:dev": "cross-env TECHDOCS_CLI_DEV_MODE=true node scripts/techdocs-cli.js",
+1 -1
View File
@@ -67,7 +67,7 @@
"devDependencies": {
"@backstage/test-utils": "^0.1.22",
"@rjsf/core": "^3.2.1",
"@testing-library/cypress": "^7.0.1",
"@testing-library/cypress": "^8.0.2",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.8",
+14 -1
View File
@@ -175,7 +175,20 @@ const routes = (
>
{techDocsPage}
</Route>
<Route path="/create" element={<ScaffolderPage />}>
<Route
path="/create"
element={
<ScaffolderPage
groups={[
{
title: 'Recommended',
filter: entity =>
entity?.metadata?.tags?.includes('recommended') ?? false,
},
]}
/>
}
>
<ScaffolderFieldExtensions>
<LowerCaseValuePickerFieldExtension />
</ScaffolderFieldExtensions>
+21
View File
@@ -1,5 +1,26 @@
# @backstage/backend-common
## 0.9.11
### Patch Changes
- bab752e2b3: Change default port of backend from 7000 to 7007.
This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start.
You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values:
```
backend:
listen: 0.0.0.0:7123
baseUrl: http://localhost:7123
```
More information can be found here: https://backstage.io/docs/conf/writing
- Updated dependencies
- @backstage/errors@0.1.5
## 0.9.10
### Patch Changes
+24
View File
@@ -526,6 +526,20 @@ export type SearchResponseFile = {
content(): Promise<Buffer>;
};
// @public
export class ServerTokenManager implements TokenManager {
// (undocumented)
authenticate(token: string): Promise<void>;
// (undocumented)
static fromConfig(config: Config): ServerTokenManager;
// (undocumented)
getToken(): Promise<{
token: string;
}>;
// (undocumented)
static noop(): TokenManager;
}
// @public (undocumented)
export type ServiceBuilder = {
loadConfig(config: Config): ServiceBuilder;
@@ -583,6 +597,16 @@ export interface StatusCheckHandlerOptions {
statusCheck?: StatusCheck;
}
// @public
export interface TokenManager {
// (undocumented)
authenticate: (token: string) => Promise<void>;
// (undocumented)
getToken: () => Promise<{
token: string;
}>;
}
// @public
export type UrlReader = {
read(url: string): Promise<Buffer>;
+14
View File
@@ -20,6 +20,20 @@ export interface Config {
};
backend: {
/** Backend configuration for when request authentication is enabled */
auth?: {
/** Keys shared by all backends for signing and validating backend tokens. */
keys: {
/**
* Secret for generating tokens. Should be a base64 string, recommended
* length is 24 bytes.
*
* @visibility secret
*/
secret: string;
}[];
};
baseUrl: string; // defined in core, but repeated here without doc
/** Address that the backend should listen to. */
+5 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-common",
"description": "Common functionality library for Backstage backends",
"version": "0.9.10",
"version": "0.9.11",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -32,7 +32,7 @@
"@backstage/cli-common": "^0.1.6",
"@backstage/config": "^0.1.11",
"@backstage/config-loader": "^0.8.0",
"@backstage/errors": "^0.1.4",
"@backstage/errors": "^0.1.5",
"@backstage/integration": "^0.6.9",
"@backstage/types": "^0.1.1",
"@google-cloud/storage": "^5.8.0",
@@ -54,6 +54,7 @@
"git-url-parse": "^11.6.0",
"helmet": "^4.0.0",
"isomorphic-git": "^1.8.0",
"jose": "^1.27.1",
"keyv": "^4.0.3",
"keyv-memcache": "^1.2.5",
"knex": "^0.95.1",
@@ -80,8 +81,8 @@
}
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
"@backstage/test-utils": "^0.1.22",
"@backstage/cli": "^0.9.1",
"@backstage/test-utils": "^0.1.23",
"@types/archiver": "^5.1.0",
"@types/compression": "^1.7.0",
"@types/concat-stream": "^1.6.0",
+1
View File
@@ -31,4 +31,5 @@ export * from './paths';
export * from './reading';
export * from './scm';
export * from './service';
export * from './tokens';
export * from './util';
@@ -0,0 +1,189 @@
/*
* Copyright 2021 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 { ConfigReader } from '@backstage/config';
import { TokenManager } from './types';
import { ServerTokenManager } from './ServerTokenManager';
const emptyConfig = new ConfigReader({});
const configWithSecret = new ConfigReader({
backend: { auth: { keys: [{ secret: 'a-secret-key' }] } },
});
describe('ServerTokenManager', () => {
it('should throw if secret in config does not exist', () => {
expect(() => ServerTokenManager.fromConfig(emptyConfig)).toThrowError();
});
describe('getToken', () => {
it('should return a token if secret in config exists', async () => {
const tokenManager = ServerTokenManager.fromConfig(configWithSecret);
expect((await tokenManager.getToken()).token).toBeDefined();
});
it('should return a token string if using a noop TokenManager', async () => {
const tokenManager = ServerTokenManager.noop();
expect((await tokenManager.getToken()).token).toBeDefined();
});
});
describe('authenticate', () => {
it('should not throw if token is valid', async () => {
const tokenManager = ServerTokenManager.fromConfig(configWithSecret);
const { token } = await tokenManager.getToken();
await expect(tokenManager.authenticate(token)).resolves.not.toThrow();
});
it('should throw if token is invalid', async () => {
const tokenManager = ServerTokenManager.fromConfig(configWithSecret);
await expect(
tokenManager.authenticate('random-string'),
).rejects.toThrowError(/invalid server token/i);
});
it('should validate server tokens created by a different instance using the same secret', async () => {
const tokenManager1 = ServerTokenManager.fromConfig(configWithSecret);
const tokenManager2 = ServerTokenManager.fromConfig(configWithSecret);
const { token } = await tokenManager1.getToken();
await expect(tokenManager2.authenticate(token)).resolves.not.toThrow();
});
it('should validate server tokens created using any of the secrets', async () => {
const tokenManager1 = ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [{ secret: 'a1b2c3' }] } },
}),
);
const tokenManager2 = ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [{ secret: 'd4e5f6' }] } },
}),
);
const tokenManager3 = ServerTokenManager.fromConfig(
new ConfigReader({
backend: {
auth: { keys: [{ secret: 'a1b2c3' }, { secret: 'd4e5f6' }] },
},
}),
);
const { token: token1 } = await tokenManager1.getToken();
await expect(tokenManager3.authenticate(token1)).resolves.not.toThrow();
const { token: token2 } = await tokenManager2.getToken();
await expect(tokenManager3.authenticate(token2)).resolves.not.toThrow();
});
it('should throw for server tokens created using a different secret', async () => {
const tokenManager1 = ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [{ secret: 'a1b2c3' }] } },
}),
);
const tokenManager2 = ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [{ secret: 'd4e5f6' }] } },
}),
);
const { token } = await tokenManager1.getToken();
await expect(tokenManager2.authenticate(token)).rejects.toThrowError(
/invalid server token/i,
);
});
it('should throw for server tokens created using a noop TokenManager', async () => {
const noopTokenManager = ServerTokenManager.noop();
const tokenManager = ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [{ secret: 'a1b2c3' }] } },
}),
);
const { token } = await noopTokenManager.getToken();
await expect(tokenManager.authenticate(token)).rejects.toThrowError(
/invalid server token/i,
);
});
});
describe('ServerTokenManager.fromConfig', () => {
it('should throw if backend auth configuration is missing', () => {
expect(() =>
ServerTokenManager.fromConfig(new ConfigReader({})),
).toThrow();
});
it('should throw if no keys are included in the configuration', () => {
expect(() =>
ServerTokenManager.fromConfig(
new ConfigReader({
backend: { auth: { keys: [] } },
}),
),
).toThrow();
});
it('should throw if any key is missing a secret property', () => {
expect(() =>
ServerTokenManager.fromConfig(
new ConfigReader({
backend: {
auth: {
keys: [{ secret: '123' }, {}, { secret: '789' }],
},
},
}),
),
).toThrow();
});
});
describe('ServerTokenManager.noop', () => {
let noopTokenManager: TokenManager;
beforeEach(() => {
noopTokenManager = ServerTokenManager.noop();
});
it('should accept tokens it generates', async () => {
const { token } = await noopTokenManager.getToken();
await expect(noopTokenManager.authenticate(token)).resolves.not.toThrow();
});
it('should accept tokens generated by other noop token managers', async () => {
const noopTokenManager2 = ServerTokenManager.noop();
await expect(
noopTokenManager.authenticate(
(
await noopTokenManager2.getToken()
).token,
),
).resolves.not.toThrow();
});
it('should accept signed tokens', async () => {
const tokenManager = ServerTokenManager.fromConfig(configWithSecret);
await expect(
noopTokenManager.authenticate((await tokenManager.getToken()).token),
).resolves.not.toThrow();
});
});
});
@@ -0,0 +1,80 @@
/*
* Copyright 2021 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 { JWKS, JWK, JWT } from 'jose';
import { Config } from '@backstage/config';
import { AuthenticationError } from '@backstage/errors';
import { TokenManager } from './types';
class NoopTokenManager implements TokenManager {
async getToken() {
return { token: '' };
}
async authenticate() {}
}
/**
* Creates and validates tokens for use during backend-to-backend
* authentication.
*
* @public
*/
export class ServerTokenManager implements TokenManager {
private readonly verificationKeys: JWKS.KeyStore;
private readonly signingKey: JWK.Key;
static noop(): TokenManager {
return new NoopTokenManager();
}
static fromConfig(config: Config) {
return new ServerTokenManager(
config
.getConfigArray('backend.auth.keys')
.map(key => key.getString('secret')),
);
}
private constructor(secrets?: string[]) {
if (!secrets?.length) {
throw new Error(
'No secrets provided when constructing ServerTokenManager',
);
}
this.verificationKeys = new JWKS.KeyStore(
secrets.map(k => JWK.asKey({ kty: 'oct', k })),
);
this.signingKey = this.verificationKeys.all()[0];
}
async getToken(): Promise<{ token: string }> {
const jwt = JWT.sign({ sub: 'backstage-server' }, this.signingKey, {
algorithm: 'HS256',
});
return { token: jwt };
}
async authenticate(token: string): Promise<void> {
try {
JWT.verify(token, this.verificationKeys);
} catch (e) {
throw new AuthenticationError('Invalid server token');
}
}
}
@@ -0,0 +1,18 @@
/*
* Copyright 2021 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.
*/
export { ServerTokenManager } from './ServerTokenManager';
export type { TokenManager } from './types';
@@ -0,0 +1,25 @@
/*
* Copyright 2021 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.
*/
/**
* Interface for creating and validating tokens.
*
* @public
*/
export interface TokenManager {
getToken: () => Promise<{ token: string }>;
authenticate: (token: string) => Promise<void>;
}
+22
View File
@@ -1,5 +1,27 @@
# example-backend
## 0.2.54
### Patch Changes
- Updated dependencies
- @backstage/plugin-kubernetes-backend@0.3.19
- @backstage/plugin-tech-insights-backend@0.1.2
- @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.1
- @backstage/plugin-auth-backend@0.4.9
- @backstage/plugin-scaffolder-backend@0.15.14
- @backstage/plugin-catalog-backend@0.18.0
- @backstage/plugin-kafka-backend@0.2.12
- @backstage/backend-common@0.9.11
- @backstage/plugin-azure-devops-backend@0.2.2
- @backstage/plugin-badges-backend@0.1.12
- @backstage/plugin-code-coverage-backend@0.1.15
- @backstage/plugin-jenkins-backend@0.1.8
- @backstage/plugin-proxy-backend@0.2.14
- @backstage/plugin-rollbar-backend@0.1.16
- @backstage/plugin-search-backend@0.2.7
- @backstage/plugin-techdocs-backend@0.10.9
## 0.2.52
### Patch Changes
+19 -19
View File
@@ -1,6 +1,6 @@
{
"name": "example-backend",
"version": "0.2.52",
"version": "0.2.54",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -24,35 +24,35 @@
"migrate:create": "knex migrate:make -x ts"
},
"dependencies": {
"@backstage/backend-common": "^0.9.10",
"@backstage/backend-common": "^0.9.11",
"@backstage/catalog-client": "^0.5.2",
"@backstage/catalog-model": "^0.9.7",
"@backstage/config": "^0.1.10",
"@backstage/integration": "^0.6.8",
"@backstage/plugin-app-backend": "^0.3.19",
"@backstage/plugin-auth-backend": "^0.4.8",
"@backstage/plugin-azure-devops-backend": "^0.2.1",
"@backstage/plugin-badges-backend": "^0.1.11",
"@backstage/plugin-catalog-backend": "^0.17.4",
"@backstage/plugin-code-coverage-backend": "^0.1.14",
"@backstage/plugin-auth-backend": "^0.4.9",
"@backstage/plugin-azure-devops-backend": "^0.2.2",
"@backstage/plugin-badges-backend": "^0.1.12",
"@backstage/plugin-catalog-backend": "^0.18.0",
"@backstage/plugin-code-coverage-backend": "^0.1.15",
"@backstage/plugin-graphql-backend": "^0.1.9",
"@backstage/plugin-jenkins-backend": "^0.1.7",
"@backstage/plugin-kubernetes-backend": "^0.3.18",
"@backstage/plugin-kafka-backend": "^0.2.11",
"@backstage/plugin-proxy-backend": "^0.2.13",
"@backstage/plugin-rollbar-backend": "^0.1.15",
"@backstage/plugin-scaffolder-backend": "^0.15.13",
"@backstage/plugin-jenkins-backend": "^0.1.8",
"@backstage/plugin-kubernetes-backend": "^0.3.19",
"@backstage/plugin-kafka-backend": "^0.2.12",
"@backstage/plugin-proxy-backend": "^0.2.14",
"@backstage/plugin-rollbar-backend": "^0.1.16",
"@backstage/plugin-scaffolder-backend": "^0.15.14",
"@backstage/plugin-scaffolder-backend-module-rails": "^0.1.7",
"@backstage/plugin-search-backend": "^0.2.6",
"@backstage/plugin-search-backend": "^0.2.7",
"@backstage/plugin-search-backend-node": "^0.4.2",
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.5",
"@backstage/plugin-search-backend-module-pg": "^0.2.1",
"@backstage/plugin-techdocs-backend": "^0.10.8",
"@backstage/plugin-tech-insights-backend": "^0.1.1",
"@backstage/plugin-techdocs-backend": "^0.10.9",
"@backstage/plugin-tech-insights-backend": "^0.1.2",
"@backstage/plugin-tech-insights-node": "^0.1.0",
"@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.0",
"@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.1",
"@backstage/plugin-todo-backend": "^0.1.13",
"@gitbeaker/node": "^30.2.0",
"@gitbeaker/node": "^34.6.0",
"@octokit/rest": "^18.5.3",
"azure-devops-node-api": "^11.0.1",
"dockerode": "^3.3.1",
@@ -68,7 +68,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
"@backstage/cli": "^0.9.1",
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5"
+3 -1
View File
@@ -33,6 +33,7 @@ import {
SingleHostDiscovery,
UrlReaders,
useHotMemoize,
ServerTokenManager,
} from '@backstage/backend-common';
import { Config } from '@backstage/config';
import healthcheck from './plugins/healthcheck';
@@ -60,6 +61,7 @@ function makeCreateEnv(config: Config) {
const root = getRootLogger();
const reader = UrlReaders.default({ logger: root, config });
const discovery = SingleHostDiscovery.fromConfig(config);
const tokenManager = ServerTokenManager.noop();
root.info(`Created UrlReader ${reader}`);
@@ -70,7 +72,7 @@ function makeCreateEnv(config: Config) {
const logger = root.child({ type: 'plugin', plugin });
const database = databaseManager.forPlugin(plugin);
const cache = cacheManager.forPlugin(plugin);
return { logger, cache, database, config, reader, discovery };
return { logger, cache, database, config, reader, discovery, tokenManager };
};
}
+6 -1
View File
@@ -59,6 +59,7 @@ export default async function createPlugin({
discovery,
config,
database,
tokenManager,
}: PluginEnvironment) {
// Initialize a connection to a search engine.
const searchEngine = await createSearchEngine({ config, logger, database });
@@ -68,7 +69,10 @@ export default async function createPlugin({
// particular collator gathers entities from the software catalog.
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: DefaultCatalogCollator.fromConfig(config, { discovery }),
collator: DefaultCatalogCollator.fromConfig(config, {
discovery,
tokenManager,
}),
});
indexBuilder.addCollator({
@@ -76,6 +80,7 @@ export default async function createPlugin({
collator: DefaultTechDocsCollator.fromConfig(config, {
discovery,
logger,
tokenManager,
}),
});
+2
View File
@@ -20,6 +20,7 @@ import {
PluginCacheManager,
PluginDatabaseManager,
PluginEndpointDiscovery,
TokenManager,
UrlReader,
} from '@backstage/backend-common';
@@ -30,4 +31,5 @@ export type PluginEnvironment = {
config: Config;
reader: UrlReader;
discovery: PluginEndpointDiscovery;
tokenManager: TokenManager;
};
+24
View File
@@ -1,5 +1,29 @@
# @backstage/cli
## 0.9.1
### Patch Changes
- dde216acf4: Switch the default test coverage provider from the jest default one to `'v8'`, which provides much better coverage information when using the default Backstage test setup. This is considered a bug fix as the current coverage information is often very inaccurate.
- 719cc87d2f: Disable ES transforms in tests transformed by the `jestSucraseTransform.js`. This is not considered a breaking change since all code is already transpiled this way in the development setup.
- bab752e2b3: Change default port of backend from 7000 to 7007.
This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start.
You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values:
```
backend:
listen: 0.0.0.0:7123
baseUrl: http://localhost:7123
```
More information can be found here: https://backstage.io/docs/conf/writing
- ee055cf6db: Update the default routes to use id instead of title
- Updated dependencies
- @backstage/errors@0.1.5
## 0.9.0
### Minor Changes
+8 -8
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli",
"description": "CLI for developing Backstage plugins and apps",
"version": "0.9.0",
"version": "0.9.1",
"private": false,
"publishConfig": {
"access": "public"
@@ -31,7 +31,7 @@
"@backstage/cli-common": "^0.1.6",
"@backstage/config": "^0.1.11",
"@backstage/config-loader": "^0.8.0",
"@backstage/errors": "^0.1.4",
"@backstage/errors": "^0.1.5",
"@backstage/types": "^0.1.1",
"@hot-loader/react-dom": "^16.13.0",
"@lerna/package-graph": "^4.0.0",
@@ -90,7 +90,7 @@
"postcss": "^8.1.0",
"process": "^0.11.10",
"react": "^16.0.0",
"react-dev-utils": "^11.0.4",
"react-dev-utils": "^12.0.0-next.47",
"react-hot-loader": "^4.12.21",
"recursive-readdir": "^2.2.2",
"replace-in-file": "^6.0.0",
@@ -117,13 +117,13 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-common": "^0.9.10",
"@backstage/backend-common": "^0.9.11",
"@backstage/config": "^0.1.11",
"@backstage/core-components": "^0.7.4",
"@backstage/core-plugin-api": "^0.2.0",
"@backstage/core-app-api": "^0.1.21",
"@backstage/core-components": "^0.7.5",
"@backstage/core-plugin-api": "^0.2.1",
"@backstage/core-app-api": "^0.1.23",
"@backstage/dev-utils": "^0.2.13",
"@backstage/test-utils": "^0.1.22",
"@backstage/test-utils": "^0.1.23",
"@backstage/theme": "^0.2.13",
"@types/diff": "^5.0.0",
"@types/express": "^4.17.6",
+9
View File
@@ -1,5 +1,14 @@
# @backstage/codemods
## 0.1.23
### Patch Changes
- Updated dependencies
- @backstage/core-app-api@0.1.23
- @backstage/core-plugin-api@0.2.1
- @backstage/core-components@0.7.5
## 0.1.22
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/codemods",
"description": "A collection of codemods for Backstage projects",
"version": "0.1.22",
"version": "0.1.23",
"private": false,
"publishConfig": {
"access": "public",
+2 -2
View File
@@ -41,10 +41,10 @@
"json-schema": "^0.4.0",
"json-schema-merge-allof": "^0.8.1",
"json-schema-traverse": "^1.0.0",
"node-fetch": "^2.6.1",
"typescript-json-schema": "^0.51.0",
"yaml": "^1.9.2",
"yup": "^0.32.9",
"node-fetch": "2.6.5"
"yup": "^0.32.9"
},
"devDependencies": {
"@types/jest": "^26.0.7",
+81
View File
@@ -1,5 +1,86 @@
# @backstage/core-app-api
## 0.1.23
### Patch Changes
- bab752e2b3: Change default port of backend from 7000 to 7007.
This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start.
You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values:
```
backend:
listen: 0.0.0.0:7123
baseUrl: http://localhost:7123
```
More information can be found here: https://backstage.io/docs/conf/writing
- 000190de69: The `ApiRegistry` from `@backstage/core-app-api` class has been deprecated and will be removed in a future release. To replace it, we have introduced two new helpers that are exported from `@backstage/test-utils`, namely `TestApiProvider` and `TestApiRegistry`.
These two new helpers are more tailored for writing tests and development setups, as they allow for partial implementations of each of the APIs.
When migrating existing code it is typically best to prefer usage of `TestApiProvider` when possible, so for example the following code:
```tsx
render(
<ApiProvider
apis={ApiRegistry.from([
[identityApiRef, mockIdentityApi as unknown as IdentityApi]
])}
>
{...}
</ApiProvider>
)
```
Would be migrated to this:
```tsx
render(
<TestApiProvider apis={[[identityApiRef, mockIdentityApi]]}>
{...}
</TestApiProvider>
)
```
In cases where the `ApiProvider` is used in a more standalone way, for example to reuse a set of APIs across multiple tests, the `TestApiRegistry` can be used instead. Note that the `TestApiRegistry` only has a single static factory method, `.from()`, and it is slightly different from the existing `.from()` method on `ApiRegistry` in that it doesn't require the API pairs to be wrapped in an outer array.
Usage that looks like this:
```ts
const apis = ApiRegistry.with(
identityApiRef,
mockIdentityApi as unknown as IdentityApi,
).with(configApiRef, new ConfigReader({}));
```
OR like this:
```ts
const apis = ApiRegistry.from([
[identityApiRef, mockIdentityApi as unknown as IdentityApi],
[configApiRef, new ConfigReader({})],
]);
```
Would be migrated to this:
```ts
const apis = TestApiRegistry.from(
[identityApiRef, mockIdentityApi],
[configApiRef, new ConfigReader({})],
);
```
If your app is still using the `ApiRegistry` to construct the `apis` for `createApp`, we recommend that you move over to use the new method of supplying API factories instead, using `createApiFactory`.
- Updated dependencies
- @backstage/core-plugin-api@0.2.1
- @backstage/core-components@0.7.5
## 0.1.22
### Patch Changes
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-app-api",
"description": "Core app API used by Backstage apps",
"version": "0.1.22",
"version": "0.1.23",
"private": false,
"publishConfig": {
"access": "public",
@@ -30,9 +30,9 @@
},
"dependencies": {
"@backstage/app-defaults": "^0.1.1",
"@backstage/core-components": "^0.7.4",
"@backstage/core-components": "^0.7.5",
"@backstage/config": "^0.1.11",
"@backstage/core-plugin-api": "^0.2.0",
"@backstage/core-plugin-api": "^0.2.1",
"@backstage/theme": "^0.2.13",
"@backstage/types": "^0.1.1",
"@backstage/version-bridge": "^0.1.0",
@@ -47,8 +47,8 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
"@backstage/test-utils": "^0.1.22",
"@backstage/cli": "^0.9.1",
"@backstage/test-utils": "^0.1.23",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2",
@@ -349,6 +349,78 @@ describe('Integration Test', () => {
});
});
it('getFeatureFlags should return feature flags', async () => {
const storageFlags = new LocalStorageFeatureFlags();
jest.spyOn(storageFlags, 'registerFlag');
const apis = [
noOpAnalyticsApi,
createApiFactory({
api: featureFlagsApiRef,
deps: { configApi: configApiRef },
factory() {
return storageFlags;
},
}),
];
const app = new AppManager({
apis,
defaultApis: [],
themes: [
{
id: 'light',
title: 'Light Theme',
variant: 'light',
Provider: ({ children }) => <>{children}</>,
},
],
icons,
plugins: [
createPlugin({
id: 'test',
featureFlags: [
{
name: 'foo',
},
],
register: p => p.featureFlags.register('name'),
}),
],
components,
configLoader: async () => [],
bindRoutes: ({ bind }) => {
bind(plugin1.externalRoutes, {
extRouteRef1: plugin1RouteRef,
extRouteRef2: plugin2RouteRef,
});
},
});
const Provider = app.getProvider();
const Router = app.getRouter();
await renderWithEffects(
<Provider>
<Router>
<Routes>
<Route path="/" element={<ExposedComponent />} />
<Route path="/foo" element={<HiddenComponent />} />
</Routes>
</Router>
</Provider>,
);
expect(storageFlags.registerFlag).toHaveBeenCalledWith({
name: 'name',
pluginId: 'test',
});
expect(storageFlags.registerFlag).toHaveBeenCalledWith({
name: 'foo',
pluginId: 'test',
});
});
it('should track route changes via analytics api', async () => {
const mockAnalyticsApi = new MockAnalyticsApi();
const apis = [createApiFactory(analyticsApiRef, mockAnalyticsApi)];
+19 -10
View File
@@ -272,17 +272,26 @@ export class AppManager implements BackstageApp {
const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!;
for (const plugin of this.plugins.values()) {
for (const output of plugin.output()) {
switch (output.type) {
case 'feature-flag': {
featureFlagsApi.registerFlag({
name: output.name,
pluginId: plugin.getId(),
});
break;
if ('getFeatureFlags' in plugin) {
for (const flag of plugin.getFeatureFlags()) {
featureFlagsApi.registerFlag({
name: flag.name,
pluginId: plugin.getId(),
});
}
} else {
for (const output of plugin.output()) {
switch (output.type) {
case 'feature-flag': {
featureFlagsApi.registerFlag({
name: output.name,
pluginId: plugin.getId(),
});
break;
}
default:
break;
}
default:
break;
}
}
}
+9
View File
@@ -1,5 +1,14 @@
# @backstage/core-components
## 0.7.5
### Patch Changes
- 157530187a: Pin sidebar by default for easier navigation
- Updated dependencies
- @backstage/errors@0.1.5
- @backstage/core-plugin-api@0.2.1
## 0.7.4
### Patch Changes
+6 -6
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-components",
"description": "Core components used by Backstage plugins and apps",
"version": "0.7.4",
"version": "0.7.5",
"private": false,
"publishConfig": {
"access": "public",
@@ -30,8 +30,8 @@
},
"dependencies": {
"@backstage/config": "^0.1.11",
"@backstage/core-plugin-api": "^0.2.0",
"@backstage/errors": "^0.1.4",
"@backstage/core-plugin-api": "^0.2.1",
"@backstage/errors": "^0.1.5",
"@backstage/theme": "^0.2.13",
"@material-table/core": "^3.1.0",
"@material-ui/core": "^4.12.2",
@@ -67,9 +67,9 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@backstage/core-app-api": "^0.1.21",
"@backstage/cli": "^0.9.0",
"@backstage/test-utils": "^0.1.22",
"@backstage/core-app-api": "^0.1.23",
"@backstage/cli": "^0.9.1",
"@backstage/test-utils": "^0.1.23",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2",
+8
View File
@@ -1,5 +1,13 @@
# @backstage/core-plugin-api
## 0.2.1
### Patch Changes
- 950b36393c: Deprecated `register` option of `createPlugin` and the `outputs` methods of the plugin instance.
Introduces the `featureFlags` property to define your feature flags instead.
## 0.2.0
### Minor Changes
+9 -2
View File
@@ -258,6 +258,7 @@ export type BackstagePlugin<
getId(): string;
output(): PluginOutput[];
getApis(): Iterable<AnyApiFactory>;
getFeatureFlags(): Iterable<PluginFeatureFlagConfig>;
provide<T>(extension: Extension<T>): T;
routes: Routes;
externalRoutes: ExternalRoutes;
@@ -463,7 +464,7 @@ export type FeatureFlag = {
pluginId: string;
};
// @public
// @public @deprecated
export type FeatureFlagOutput = {
type: 'feature-flag';
name: string;
@@ -682,14 +683,20 @@ export type PluginConfig<
register?(hooks: PluginHooks): void;
routes?: Routes;
externalRoutes?: ExternalRoutes;
featureFlags?: PluginFeatureFlagConfig[];
};
// @public
export type PluginFeatureFlagConfig = {
name: string;
};
// @public @deprecated
export type PluginHooks = {
featureFlags: FeatureFlagsHooks;
};
// @public
// @public @deprecated
export type PluginOutput = FeatureFlagOutput;
// @public
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-plugin-api",
"description": "Core API used by Backstage plugins",
"version": "0.2.0",
"version": "0.2.1",
"private": false,
"publishConfig": {
"access": "public",
@@ -43,9 +43,9 @@
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
"@backstage/core-app-api": "^0.1.21",
"@backstage/test-utils": "^0.1.22",
"@backstage/cli": "^0.9.1",
"@backstage/core-app-api": "^0.1.23",
"@backstage/test-utils": "^0.1.23",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/react-hooks": "^7.0.2",
@@ -0,0 +1,89 @@
/*
* Copyright 2021 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 { createPlugin } from './Plugin';
describe('Plugin Feature Flag', () => {
it('should be able to register and receive feature flags', () => {
expect(
createPlugin({
id: 'test',
featureFlags: [{ name: 'test' }],
}).getFeatureFlags(),
).toEqual([{ name: 'test' }]);
expect(
createPlugin({
id: 'test',
register({ featureFlags }) {
featureFlags.register('blob');
},
}).getFeatureFlags(),
).toEqual([{ name: 'blob' }]);
expect(
createPlugin({
id: 'test',
register({ featureFlags }) {
featureFlags.register('blob');
},
featureFlags: [{ name: 'test' }],
}).getFeatureFlags(),
).toEqual([{ name: 'test' }, { name: 'blob' }]);
expect(
createPlugin({
id: 'test',
}).getFeatureFlags(),
).toEqual([]);
/* deprecated tests */
expect(
createPlugin({
id: 'test',
featureFlags: [{ name: 'test' }],
}).output(),
).toEqual([{ name: 'test', type: 'feature-flag' }]);
expect(
createPlugin({
id: 'test',
register({ featureFlags }) {
featureFlags.register('blob');
},
}).output(),
).toEqual([{ name: 'blob', type: 'feature-flag' }]);
expect(
createPlugin({
id: 'test',
register({ featureFlags }) {
featureFlags.register('blob');
},
featureFlags: [{ name: 'test' }],
}).output(),
).toEqual([
{ name: 'test', type: 'feature-flag' },
{ name: 'blob', type: 'feature-flag' },
]);
expect(
createPlugin({
id: 'test',
}).output(),
).toEqual([]);
});
});
+19 -4
View File
@@ -21,6 +21,7 @@ import {
Extension,
AnyRoutes,
AnyExternalRoutes,
PluginFeatureFlagConfig,
} from './types';
import { AnyApiFactory } from '../apis';
@@ -44,6 +45,14 @@ export class PluginImpl<
return this.config.apis ?? [];
}
getFeatureFlags(): Iterable<PluginFeatureFlagConfig> {
const registeredFlags = this.output()
.filter(({ type }) => type === 'feature-flag')
.map(({ name }) => ({ name }));
return registeredFlags;
}
get routes(): Routes {
return this.config.routes ?? ({} as Routes);
}
@@ -56,11 +65,18 @@ export class PluginImpl<
if (this.storedOutput) {
return this.storedOutput;
}
if (!this.config.register) {
return [];
const outputs = new Array<PluginOutput>();
this.storedOutput = outputs;
if (this.config.featureFlags) {
for (const flag of this.config.featureFlags) {
outputs.push({ type: 'feature-flag', name: flag.name });
}
}
const outputs = new Array<PluginOutput>();
if (!this.config.register) {
return outputs;
}
this.config.register({
featureFlags: {
@@ -70,7 +86,6 @@ export class PluginImpl<
},
});
this.storedOutput = outputs;
return this.storedOutput;
}
@@ -25,4 +25,5 @@ export type {
PluginConfig,
PluginHooks,
PluginOutput,
PluginFeatureFlagConfig,
} from './types';
+22 -1
View File
@@ -19,7 +19,7 @@ import { AnyApiFactory } from '../apis/system';
/**
* Replace with using {@link RouteRef}s.
*
* @deprecated will be removed
* @public
*/
export type FeatureFlagOutput = {
@@ -31,6 +31,7 @@ export type FeatureFlagOutput = {
* {@link FeatureFlagOutput} type.
*
* @public
* @deprecated Use {@link BackstagePlugin.getFeatureFlags} instead.
*/
export type PluginOutput = FeatureFlagOutput;
@@ -71,13 +72,30 @@ export type BackstagePlugin<
ExternalRoutes extends AnyExternalRoutes = {},
> = {
getId(): string;
/**
* @deprecated use getFeatureFlags instead.
* */
output(): PluginOutput[];
getApis(): Iterable<AnyApiFactory>;
/**
* Returns all registered feature flags for this plugin.
*/
getFeatureFlags(): Iterable<PluginFeatureFlagConfig>;
provide<T>(extension: Extension<T>): T;
routes: Routes;
externalRoutes: ExternalRoutes;
};
/**
* Plugin feature flag configuration.
*
* @public
*/
export type PluginFeatureFlagConfig = {
/** Feature flag name */
name: string;
};
/**
* Plugin descriptor type.
*
@@ -89,14 +107,17 @@ export type PluginConfig<
> = {
id: string;
apis?: Iterable<AnyApiFactory>;
/** @deprecated use featureFlags property instead for defining feature flags */
register?(hooks: PluginHooks): void;
routes?: Routes;
externalRoutes?: ExternalRoutes;
featureFlags?: PluginFeatureFlagConfig[];
};
/**
* Holds hooks registered by the plugin.
*
* @deprecated - feature flags are now registered in plugin config under featureFlags
* @public
*/
export type PluginHooks = {
@@ -59,21 +59,21 @@ export class RouteRefImpl<Params extends AnyParams>
if (config.path) {
// eslint-disable-next-line no-console
console.warn(
`[core-plugin-api] - routeRefs no longer decide their own path, please remove the path for ${this.toString()}. This will be removed in upcoming versions.`,
`DEPRECATION WARNING: Passing a path to createRouteRef is deprecated, please remove the path for ${this}.`,
);
}
if (config.icon) {
// eslint-disable-next-line no-console
console.warn(
`[core-plugin-api] - routeRefs no longer decide their own icon, please remove the icon for ${this.toString()}. This will be removed in upcoming versions.`,
`DEPRECATION WARNING: Passing an icon to createRouteRef is deprecated, please remove the icon for ${this}.`,
);
}
if (config.title) {
// eslint-disable-next-line no-console
console.warn(
`[core-plugin-api] - routeRefs no longer decide their own title, please remove the title for ${this.toString()}. This will be removed in upcoming versions.`,
`DEPRECATION WARNING: Passing a title to createRouteRef is deprecated, please remove the title for ${this}.`,
);
}
}
+22
View File
@@ -1,5 +1,27 @@
# @backstage/create-app
## 0.4.5
### Patch Changes
- dcaeaac174: Cleaned out the `peerDependencies` in the published version of the package, making it much quicker to run `npx @backstage/create-app` as it no longer needs to install a long list of unnecessary.
- a5a5d7e1f1: DefaultTechDocsCollator is now included in the search backend, and the Search Page updated with the SearchType component that includes the techdocs type
- bab752e2b3: Change default port of backend from 7000 to 7007.
This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start.
You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values:
```
backend:
listen: 0.0.0.0:7123
baseUrl: http://localhost:7123
```
More information can be found here: https://backstage.io/docs/conf/writing
- 42ebbc18c0: Bump gitbeaker to the latest version
## 0.4.4
### Patch Changes
+3 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/create-app",
"description": "A CLI that helps you create your own Backstage app",
"version": "0.4.4",
"version": "0.4.5",
"private": false,
"publishConfig": {
"access": "public"
@@ -25,6 +25,8 @@
"lint": "backstage-cli lint",
"test": "backstage-cli test",
"clean": "backstage-cli clean",
"prepack": "node scripts/prepack.js",
"postpack": "node scripts/postpack.js",
"start": "nodemon --"
},
"dependencies": {
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env node
/*
* Copyright 2021 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.
*/
/* eslint-disable no-restricted-syntax */
const fs = require('fs-extra');
const path = require('path');
async function main() {
const pkgPath = path.resolve(__dirname, '../package.json');
const pkgBackupPath = path.resolve(__dirname, '../package.json-prepack');
try {
await fs.move(pkgBackupPath, pkgPath, { overwrite: true });
} catch (err) {
console.error(`Failed to restore package.json during postpack, ${err}`);
}
}
main().catch(err => {
console.error(err.stack);
process.exit(1);
});
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env node
/*
* Copyright 2021 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.
*/
/* eslint-disable no-restricted-syntax */
const fs = require('fs-extra');
const path = require('path');
async function main() {
const pkgPath = path.resolve(__dirname, '../package.json');
const pkgBackupPath = path.resolve(__dirname, '../package.json-prepack');
const pkg = await fs.readJson(pkgPath);
await fs.writeJson(pkgBackupPath, pkg, { encoding: 'utf8', spaces: 2 });
delete pkg.peerDependencies;
await fs.writeJson(pkgPath, pkg, { encoding: 'utf8', spaces: 2 });
}
main().catch(err => {
console.error(err.stack);
process.exit(1);
});
@@ -6,6 +6,11 @@ organization:
name: My Company
backend:
# Used for enabling authentication, secret is shared by all backend plugins
# See backend-to-backend-auth.md in the docs for information on the format
# auth:
# keys:
# - secret: ${BACKEND_SECRET}
baseUrl: http://localhost:7007
listen:
port: 7007
@@ -27,7 +27,7 @@
"@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}",
"@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}",
"@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}",
"@gitbeaker/node": "^30.2.0",
"@gitbeaker/node": "^34.6.0",
"@octokit/rest": "^18.5.3",
"dockerode": "^3.3.1",
"express": "^4.17.1",
@@ -17,6 +17,7 @@ import {
DatabaseManager,
SingleHostDiscovery,
UrlReaders,
ServerTokenManager,
} from '@backstage/backend-common';
import { Config } from '@backstage/config';
import app from './plugins/app';
@@ -37,12 +38,13 @@ function makeCreateEnv(config: Config) {
const cacheManager = CacheManager.fromConfig(config);
const databaseManager = DatabaseManager.fromConfig(config);
const tokenManager = ServerTokenManager.noop();
return (plugin: string): PluginEnvironment => {
const logger = root.child({ type: 'plugin', plugin });
const database = databaseManager.forPlugin(plugin);
const cache = cacheManager.forPlugin(plugin);
return { logger, database, cache, config, reader, discovery };
return { logger, database, cache, config, reader, discovery, tokenManager };
};
}
@@ -12,6 +12,7 @@ export default async function createPlugin({
logger,
discovery,
config,
tokenManager,
}: PluginEnvironment) {
// Initialize a connection to a search engine.
const searchEngine = new LunrSearchEngine({ logger });
@@ -21,13 +22,20 @@ export default async function createPlugin({
// collator gathers entities from the software catalog.
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: DefaultCatalogCollator.fromConfig(config, { discovery }),
collator: DefaultCatalogCollator.fromConfig(config, {
discovery,
tokenManager,
}),
});
// collator gathers entities from techdocs.
indexBuilder.addCollator({
defaultRefreshIntervalSeconds: 600,
collator: DefaultTechDocsCollator.fromConfig(config, { discovery, logger }),
collator: DefaultTechDocsCollator.fromConfig(config, {
discovery,
logger,
tokenManager,
}),
});
// The scheduler controls when documents are gathered from collators and sent
@@ -4,6 +4,7 @@ import {
PluginCacheManager,
PluginDatabaseManager,
PluginEndpointDiscovery,
TokenManager,
UrlReader,
} from '@backstage/backend-common';
@@ -14,4 +15,5 @@ export type PluginEnvironment = {
config: Config;
reader: UrlReader;
discovery: PluginEndpointDiscovery;
tokenManager: TokenManager;
};
+7
View File
@@ -1,5 +1,12 @@
# @backstage/errors
## 0.1.5
### Patch Changes
- 4d09c60256: Deprecate `parseErrorResponse` in favour of `parseErrorResponseBody`. Deprecate `data` field inside `ErrorResponse` in favour of `body`.
Rename the error name for unknown errors from `unknown` to `error`.
## 0.1.4
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/errors",
"description": "Common utilities for error handling within Backstage",
"version": "0.1.4",
"version": "0.1.5",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -35,7 +35,7 @@
"serialize-error": "^8.0.1"
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
"@backstage/cli": "^0.9.1",
"@types/jest": "^26.0.7"
},
"files": [
+12 -6
View File
@@ -112,7 +112,9 @@ export function getAzureFileFetchUrl(url: string): string;
export function getAzureRequestOptions(
config: AzureIntegrationConfig,
additionalHeaders?: Record<string, string>,
): RequestInit;
): {
headers: Record<string, string>;
};
// @public
export function getBitbucketDefaultBranch(
@@ -135,7 +137,9 @@ export function getBitbucketFileFetchUrl(
// @public
export function getBitbucketRequestOptions(
config: BitbucketIntegrationConfig,
): RequestInit;
): {
headers: Record<string, string>;
};
// @public
export function getGitHubFileFetchUrl(
@@ -148,7 +152,9 @@ export function getGitHubFileFetchUrl(
export function getGitHubRequestOptions(
config: GitHubIntegrationConfig,
credentials: GithubCredentials,
): RequestInit;
): {
headers: Record<string, string>;
};
// @public
export function getGitLabFileFetchUrl(
@@ -157,9 +163,9 @@ export function getGitLabFileFetchUrl(
): Promise<string>;
// @public
export function getGitLabRequestOptions(
config: GitLabIntegrationConfig,
): RequestInit;
export function getGitLabRequestOptions(config: GitLabIntegrationConfig): {
headers: Record<string, string>;
};
// @public
export type GithubAppConfig = {
+2 -2
View File
@@ -64,8 +64,8 @@ export function getAzureCommitsUrl(url: string): string {
export function getAzureRequestOptions(
config: AzureIntegrationConfig,
additionalHeaders?: Record<string, string>,
): RequestInit {
const headers: HeadersInit = additionalHeaders
): { headers: Record<string, string> } {
const headers: Record<string, string> = additionalHeaders
? { ...additionalHeaders }
: {};
+2 -2
View File
@@ -158,8 +158,8 @@ export function getBitbucketFileFetchUrl(
*/
export function getBitbucketRequestOptions(
config: BitbucketIntegrationConfig,
): RequestInit {
const headers: HeadersInit = {};
): { headers: Record<string, string> } {
const headers: Record<string, string> = {};
if (config.token) {
headers.Authorization = `Bearer ${config.token}`;
+2 -2
View File
@@ -73,8 +73,8 @@ export function getGitHubFileFetchUrl(
export function getGitHubRequestOptions(
config: GitHubIntegrationConfig,
credentials: GithubCredentials,
): RequestInit {
const headers: HeadersInit = {};
): { headers: Record<string, string> } {
const headers: Record<string, string> = {};
if (chooseEndpoint(config, credentials) === 'api') {
headers.Accept = 'application/vnd.github.v3.raw';
+3 -3
View File
@@ -54,9 +54,9 @@ export async function getGitLabFileFetchUrl(
* @param config - The relevant provider config
* @public
*/
export function getGitLabRequestOptions(
config: GitLabIntegrationConfig,
): RequestInit {
export function getGitLabRequestOptions(config: GitLabIntegrationConfig): {
headers: Record<string, string>;
} {
const { token = '' } = config;
return {
headers: {
+1 -1
View File
@@ -65,7 +65,7 @@
"dockerode": "^3.3.1",
"fs-extra": "^9.0.1",
"http-proxy": "^1.18.1",
"react-dev-utils": "^11.0.4",
"react-dev-utils": "^12.0.0-next.47",
"serve-handler": "^6.1.3",
"winston": "^3.2.1"
}
+22
View File
@@ -1,5 +1,27 @@
# @backstage/techdocs-common
## 0.10.8
### Patch Changes
- bab752e2b3: Change default port of backend from 7000 to 7007.
This is due to the AirPlay Receiver process occupying port 7000 and preventing local Backstage instances on MacOS to start.
You can change the port back to 7000 or any other value by providing an `app-config.yaml` with the following values:
```
backend:
listen: 0.0.0.0:7123
baseUrl: http://localhost:7123
```
More information can be found here: https://backstage.io/docs/conf/writing
- Updated dependencies
- @backstage/errors@0.1.5
- @backstage/backend-common@0.9.11
## 0.10.7
### Patch Changes
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/techdocs-common",
"description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli",
"version": "0.10.7",
"version": "0.10.8",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -38,10 +38,10 @@
"dependencies": {
"@azure/identity": "^1.5.0",
"@azure/storage-blob": "^12.5.0",
"@backstage/backend-common": "^0.9.10",
"@backstage/backend-common": "^0.9.11",
"@backstage/catalog-model": "^0.9.7",
"@backstage/config": "^0.1.11",
"@backstage/errors": "^0.1.4",
"@backstage/errors": "^0.1.5",
"@backstage/search-common": "^0.2.1",
"@backstage/integration": "^0.6.9",
"@google-cloud/storage": "^5.6.0",
@@ -60,7 +60,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.9.0",
"@backstage/cli": "^0.9.1",
"@types/fs-extra": "^9.0.5",
"@types/js-yaml": "^4.0.0",
"@types/mime-types": "^2.1.0",
+67
View File
@@ -1,5 +1,72 @@
# @backstage/test-utils
## 0.1.23
### Patch Changes
- 000190de69: The `ApiRegistry` from `@backstage/core-app-api` class has been deprecated and will be removed in a future release. To replace it, we have introduced two new helpers that are exported from `@backstage/test-utils`, namely `TestApiProvider` and `TestApiRegistry`.
These two new helpers are more tailored for writing tests and development setups, as they allow for partial implementations of each of the APIs.
When migrating existing code it is typically best to prefer usage of `TestApiProvider` when possible, so for example the following code:
```tsx
render(
<ApiProvider
apis={ApiRegistry.from([
[identityApiRef, mockIdentityApi as unknown as IdentityApi]
])}
>
{...}
</ApiProvider>
)
```
Would be migrated to this:
```tsx
render(
<TestApiProvider apis={[[identityApiRef, mockIdentityApi]]}>
{...}
</TestApiProvider>
)
```
In cases where the `ApiProvider` is used in a more standalone way, for example to reuse a set of APIs across multiple tests, the `TestApiRegistry` can be used instead. Note that the `TestApiRegistry` only has a single static factory method, `.from()`, and it is slightly different from the existing `.from()` method on `ApiRegistry` in that it doesn't require the API pairs to be wrapped in an outer array.
Usage that looks like this:
```ts
const apis = ApiRegistry.with(
identityApiRef,
mockIdentityApi as unknown as IdentityApi,
).with(configApiRef, new ConfigReader({}));
```
OR like this:
```ts
const apis = ApiRegistry.from([
[identityApiRef, mockIdentityApi as unknown as IdentityApi],
[configApiRef, new ConfigReader({})],
]);
```
Would be migrated to this:
```ts
const apis = TestApiRegistry.from(
[identityApiRef, mockIdentityApi],
[configApiRef, new ConfigReader({})],
);
```
If your app is still using the `ApiRegistry` to construct the `apis` for `createApp`, we recommend that you move over to use the new method of supplying API factories instead, using `createApiFactory`.
- Updated dependencies
- @backstage/core-app-api@0.1.23
- @backstage/core-plugin-api@0.2.1
## 0.1.22
### Patch Changes

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