Merge branch 'backstage:master' into 7340-remote-config-fix
This commit is contained in:
@@ -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`.
|
||||
@@ -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
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
'@backstage/create-app': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Addressed some peer dependency warnings
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Bump `react-jsonschema-form`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Can specify allowedOwners to the RepoUrlPicker picker in a template definition
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Bump esbuild to ^0.14.1
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
Switched to using the standardized JSON error responses for all provider endpoints.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes': minor
|
||||
'@backstage/plugin-kubernetes-backend': minor
|
||||
'@backstage/plugin-kubernetes-common': minor
|
||||
---
|
||||
|
||||
Add pod metrics lookup and display in pod table.
|
||||
|
||||
## Backwards incompatible changes
|
||||
|
||||
If your Kubernetes distribution does not have the [metrics server](https://github.com/kubernetes-sigs/metrics-server) installed,
|
||||
you will need to set the `skipMetricsLookup` config flag to `false`.
|
||||
|
||||
See the [configuration docs](https://backstage.io/docs/features/kubernetes/configuration) for more details.
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-permission-node': patch
|
||||
---
|
||||
|
||||
New package containing common permission and authorization utilities for backend plugins. For more information, see the [authorization PRFC](https://github.com/backstage/backstage/pull/7761).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Reject catalog entities that have duplicate fields that vary only in casing.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Fix bug with setting owner in RepoUrlPicker causing validation failure
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Providing an empty values array in an EntityFilter will now return no matches.
|
||||
@@ -2,4 +2,4 @@
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Added Azure DevOps discovery processor
|
||||
Honor database migration configuration
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Use ellipsis style for overflowed text in sidebar menu
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Add cli option to minify the generated code of a plugin or backend package
|
||||
|
||||
```
|
||||
backstage-cli plugin:build --minify
|
||||
backstage-cli backend:build --minify
|
||||
```
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-permission-common': minor
|
||||
---
|
||||
|
||||
Accept configApi rather than enabled flag in PermissionClient constructor.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search': patch
|
||||
---
|
||||
|
||||
Export SearchApi interface from plugin
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Add options argument to support additional database migrations configuration
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-config-schema': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Fixed a missing `await` when throwing server side errors
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Fix bug where there was error log lines written when failing to `JSON.parse` things that were not `JSON` values.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-analytics-module-ga': patch
|
||||
---
|
||||
|
||||
Support self hosted analytics.js script via `scriptSrc` config option
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'@backstage/core-plugin-api': patch
|
||||
---
|
||||
|
||||
Deprecated `register` option of `createPlugin` and the `outputs` methods of the plugin instance.
|
||||
|
||||
Introduces the `featureFlags` property to define your feature flags instead.
|
||||
@@ -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'],
|
||||
},
|
||||
}
|
||||
```
|
||||
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Add knexConfig config section
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
The problem of lowercase entity triplets which causes docs to not load on entity page is fixed.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/techdocs-common': minor
|
||||
'@backstage/plugin-techdocs-backend': minor
|
||||
---
|
||||
|
||||
Added the ability for the TechDocs Backend to (optionally) leverage a cache
|
||||
store to improve performance when reading files from a cloud storage provider.
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
TechDocs Backend may now (optionally) leverage a cache store to improve
|
||||
performance when reading content from a cloud storage provider.
|
||||
|
||||
To apply this change to an existing app, pass the cache manager from the plugin
|
||||
environment to the `createRouter` function in your backend:
|
||||
|
||||
```diff
|
||||
// packages/backend/src/plugins/techdocs.ts
|
||||
|
||||
export default async function createPlugin({
|
||||
logger,
|
||||
config,
|
||||
discovery,
|
||||
reader,
|
||||
+ cache,
|
||||
}: PluginEnvironment): Promise<Router> {
|
||||
|
||||
// ...
|
||||
|
||||
return await createRouter({
|
||||
preparers,
|
||||
generators,
|
||||
publisher,
|
||||
logger,
|
||||
config,
|
||||
discovery,
|
||||
+ cache,
|
||||
});
|
||||
```
|
||||
|
||||
If your `PluginEnvironment` does not include a cache manager, be sure you've
|
||||
applied [the cache management change][cm-change] to your backend as well.
|
||||
|
||||
[Additional configuration][td-rec-arch] is required if you wish to enable
|
||||
caching in TechDocs.
|
||||
|
||||
[cm-change]: https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md#patch-changes-6
|
||||
[td-rec-arch]: https://backstage.io/docs/features/techdocs/architecture#recommended-deployment
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Detect a duplicate entities when adding locations through dry run
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bump @spotify/prettier-config
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Bump gitbeaker to the latest version
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-xcmetrics': patch
|
||||
---
|
||||
|
||||
Handle a case where XCode data from backend (before 0.0.8) could be missing
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-bazaar-backend': patch
|
||||
---
|
||||
|
||||
Handle migration error when old data is present in the database
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Removed the `scaffolder.github.visibility` configuration that is no longer used from the default app template.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Update the default routes to use id instead of title
|
||||
@@ -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`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-api-docs': patch
|
||||
---
|
||||
|
||||
Adjusted some styles in the OpenAPI definition, for elements which were barely readable in dark mode.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Pin sidebar by default for easier navigation
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-cost-insights': patch
|
||||
---
|
||||
|
||||
Supply featureFlags using featureFlag config option.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-graphiql': patch
|
||||
---
|
||||
|
||||
Letting GraphiQL use headers
|
||||
@@ -8,6 +8,8 @@
|
||||
/docs/features/techdocs @backstage/techdocs-core
|
||||
/docs/features/search @backstage/techdocs-core
|
||||
/docs/assets/search @backstage/techdocs-core
|
||||
/plugins/allure @backstage/reviewers @deepak-bhardwaj-ps
|
||||
/plugins/circleci @backstage/reviewers @adamdmharvey
|
||||
/plugins/code-coverage @backstage/reviewers @alde @nissayeva
|
||||
/plugins/code-coverage-backend @backstage/reviewers @alde @nissayeva
|
||||
/plugins/cost-insights @backstage/silver-lining
|
||||
@@ -18,6 +20,20 @@
|
||||
/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
|
||||
/plugins/jenkins @backstage/reviewers @timja
|
||||
/plugins/jenkins-backend @backstage/reviewers @timja
|
||||
/plugins/kafka @backstage/reviewers @nirga
|
||||
/plugins/kafka-backend @backstage/reviewers @nirga
|
||||
/plugins/scaffolder-backend-module-yeoman @backstage/reviewers @pawelmitka
|
||||
/plugins/scaffolder-backend-module-rails @backstage/reviewers @angeliski
|
||||
/plugins/git-release-manager @backstage/reviewers @erikengervall
|
||||
/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
|
||||
|
||||
@@ -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
|
||||
@@ -189,6 +189,7 @@ oidc
|
||||
Okta
|
||||
onboarding
|
||||
Onboarding
|
||||
OpenShift
|
||||
orgs
|
||||
pagerduty
|
||||
pageview
|
||||
|
||||
@@ -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
|
||||
@@ -72,3 +72,6 @@
|
||||
| [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. |
|
||||
| [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates<br/> Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc |
|
||||
| [Mosaico](https://www.mosaico.com.br/) | [Wédney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. |
|
||||
| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon), [Gauthier Roebroeck](https://github.com/gauthier-roebroeck-mox) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 |
|
||||
|
||||
+5
-18
@@ -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
|
||||
@@ -272,24 +277,6 @@ scaffolder:
|
||||
# email: scaffolder@backstage.io
|
||||
# Use to customize the default commit message when new components are created
|
||||
# defaultCommitMessage: 'Initial commit'
|
||||
github:
|
||||
token: ${GITHUB_TOKEN}
|
||||
visibility: public # or 'internal' or 'private'
|
||||
gitlab:
|
||||
api:
|
||||
baseUrl: https://gitlab.com
|
||||
token: ${GITLAB_TOKEN}
|
||||
visibility: public # or 'internal' or 'private'
|
||||
azure:
|
||||
baseUrl: https://dev.azure.com/{your-organization}
|
||||
api:
|
||||
token: ${AZURE_TOKEN}
|
||||
bitbucket:
|
||||
api:
|
||||
host: https://bitbucket.org
|
||||
username: ${BITBUCKET_USERNAME}
|
||||
token: ${BITBUCKET_TOKEN}
|
||||
visibility: public # or or 'private'
|
||||
|
||||
auth:
|
||||
### Add auth.keyStore.provider to more granularly control how to store JWK data when running
|
||||
|
||||
+26
-78
@@ -13,9 +13,9 @@
|
||||
figures "^1.7.0"
|
||||
|
||||
"@cypress/request@^2.88.5":
|
||||
version "2.88.5"
|
||||
resolved "https://registry.npmjs.org/@cypress/request/-/request-2.88.5.tgz#8d7ecd17b53a849cfd5ab06d5abe7d84976375d7"
|
||||
integrity sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA==
|
||||
version "2.88.10"
|
||||
resolved "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce"
|
||||
integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==
|
||||
dependencies:
|
||||
aws-sign2 "~0.7.0"
|
||||
aws4 "^1.8.0"
|
||||
@@ -24,19 +24,17 @@
|
||||
extend "~3.0.2"
|
||||
forever-agent "~0.6.1"
|
||||
form-data "~2.3.2"
|
||||
har-validator "~5.1.3"
|
||||
http-signature "~1.2.0"
|
||||
http-signature "~1.3.6"
|
||||
is-typedarray "~1.0.0"
|
||||
isstream "~0.1.2"
|
||||
json-stringify-safe "~5.0.1"
|
||||
mime-types "~2.1.19"
|
||||
oauth-sign "~0.9.0"
|
||||
performance-now "^2.1.0"
|
||||
qs "~6.5.2"
|
||||
safe-buffer "^5.1.2"
|
||||
tough-cookie "~2.5.0"
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.3.2"
|
||||
uuid "^8.3.2"
|
||||
|
||||
"@cypress/xvfb@^1.2.4":
|
||||
version "1.2.4"
|
||||
@@ -68,16 +66,6 @@
|
||||
resolved "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
|
||||
integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==
|
||||
|
||||
ajv@^6.12.3:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-escapes@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
|
||||
@@ -539,16 +527,6 @@ extsprintf@^1.2.0:
|
||||
resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||
|
||||
fast-deep-equal@^3.1.1:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
||||
fd-slicer@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
|
||||
@@ -645,19 +623,6 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.5.tgz#bc18864a6c9fc7b303f2e2abdb9155ad178fbe29"
|
||||
integrity sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw==
|
||||
|
||||
har-schema@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||
|
||||
har-validator@~5.1.3:
|
||||
version "5.1.5"
|
||||
resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
|
||||
integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
|
||||
dependencies:
|
||||
ajv "^6.12.3"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
has-ansi@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
|
||||
@@ -675,14 +640,14 @@ has-flag@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
http-signature@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
|
||||
http-signature@~1.3.6:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9"
|
||||
integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
jsprim "^2.0.2"
|
||||
sshpk "^1.14.1"
|
||||
|
||||
human-signals@^1.1.1:
|
||||
version "1.1.1"
|
||||
@@ -796,15 +761,10 @@ jsbn@~0.1.0:
|
||||
resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||
json-schema@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
|
||||
integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
|
||||
|
||||
json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
@@ -820,14 +780,14 @@ jsonfile@^6.0.1:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
|
||||
jsprim@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d"
|
||||
integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==
|
||||
dependencies:
|
||||
assert-plus "1.0.0"
|
||||
extsprintf "1.3.0"
|
||||
json-schema "0.2.3"
|
||||
json-schema "0.4.0"
|
||||
verror "1.10.0"
|
||||
|
||||
lazy-ass@^1.6.0:
|
||||
@@ -985,11 +945,6 @@ number-is-nan@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||
|
||||
oauth-sign@~0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
object-assign@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
@@ -1084,7 +1039,7 @@ punycode@1.3.2:
|
||||
resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
||||
|
||||
punycode@^2.1.0, punycode@^2.1.1:
|
||||
punycode@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
@@ -1191,7 +1146,7 @@ slice-ansi@0.0.4:
|
||||
resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
|
||||
integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=
|
||||
|
||||
sshpk@^1.7.0:
|
||||
sshpk@^1.14.1:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
|
||||
@@ -1353,13 +1308,6 @@ untildify@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
|
||||
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
url@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
|
||||
@@ -1373,10 +1321,10 @@ util-deprecate@~1.0.1:
|
||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
uuid@^8.3.2:
|
||||
version "8.3.2"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
verror@1.10.0:
|
||||
version "1.10.0"
|
||||
|
||||
@@ -291,7 +291,7 @@ The figure below shows the relationship between
|
||||
<span style="color: #b85450">fooApiRef</span>.
|
||||
|
||||
<div style="text-align:center">
|
||||
<img src="../assets/utility-apis-fig1.svg" alt="Figure showing the relationship between utility APIs, the apps that provide them, and the plugins that consume them">
|
||||
<img src="../assets/utility-apis-fig1.svg" alt="Figure showing the relationship between utility APIs, the apps that provide them, and the plugins that consume them" />
|
||||
</div>
|
||||
|
||||
The current method for connecting Utility API providers and consumers is via the
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 64 KiB |
@@ -16,8 +16,10 @@ Backstage identity information in your app or plugins.
|
||||
|
||||
Backstage comes with many common authentication providers in the core library:
|
||||
|
||||
- [Atlassian](atlassian/provider.md)
|
||||
- [Auth0](auth0/provider.md)
|
||||
- [Azure](microsoft/provider.md)
|
||||
- [Bitbucket](bitbucket/provider.md)
|
||||
- [GitHub](github/provider.md)
|
||||
- [GitLab](gitlab/provider.md)
|
||||
- [Google](google/provider.md)
|
||||
|
||||
@@ -7,9 +7,9 @@ description: How to build a Backstage Docker image for deployment
|
||||
|
||||
This section describes how to build a Backstage App into a deployable Docker
|
||||
image. It is split into three sections, first covering the host build approach,
|
||||
which is recommended due its speed and more efficient and often simpler caching.
|
||||
The second section covers a full multi-stage Docker build, and the last section
|
||||
covers how to deploy the frontend and backend as separate images.
|
||||
which is recommended due to its speed and more efficient and often simpler
|
||||
caching. The second section covers a full multi-stage Docker build, and the last
|
||||
section covers how to deploy the frontend and backend as separate images.
|
||||
|
||||
Something that goes for all of these docker deployment strategies is that they
|
||||
are stateless, so for a production deployment you will want to set up and
|
||||
|
||||
@@ -26,6 +26,7 @@ kubernetes:
|
||||
name: minikube
|
||||
authProvider: 'serviceAccount'
|
||||
skipTLSVerify: false
|
||||
skipMetricsLookup: true
|
||||
serviceAccountToken: ${K8S_MINIKUBE_TOKEN}
|
||||
dashboardUrl: http://127.0.0.1:64713 # url copied from running the command: minikube service kubernetes-dashboard -n kubernetes-dashboard
|
||||
dashboardApp: standard
|
||||
@@ -37,6 +38,7 @@ kubernetes:
|
||||
projectId: 'gke-clusters'
|
||||
region: 'europe-west1'
|
||||
skipTLSVerify: true
|
||||
skipMetricsLookup: true
|
||||
```
|
||||
|
||||
### `serviceLocatorMethod`
|
||||
@@ -86,8 +88,13 @@ cluster. Valid values are:
|
||||
|
||||
##### `clusters.\*.skipTLSVerify`
|
||||
|
||||
This determines whether or not the Kubernetes client verifies the TLS
|
||||
certificate presented by the API server. Defaults to `false`.
|
||||
This determines whether the Kubernetes client verifies the TLS certificate
|
||||
presented by the API server. Defaults to `false`.
|
||||
|
||||
##### `clusters.\*.skipMetricsLookup`
|
||||
|
||||
This determines whether the Kubernetes client looks up resource metrics
|
||||
CPU/Memory for pods returned by the API server. Defaults to `false`.
|
||||
|
||||
##### `clusters.\*.serviceAccountToken` (optional)
|
||||
|
||||
@@ -188,8 +195,13 @@ regions.
|
||||
|
||||
##### `skipTLSVerify`
|
||||
|
||||
This determines whether or not the Kubernetes client verifies the TLS
|
||||
certificate presented by the API server. Defaults to `false`.
|
||||
This determines whether the Kubernetes client verifies the TLS certificate
|
||||
presented by the API server. Defaults to `false`.
|
||||
|
||||
##### `skipMetricsLookup`
|
||||
|
||||
This determines whether the Kubernetes client looks up resource metrics
|
||||
CPU/Memory for pods returned by the API server. Defaults to `false`.
|
||||
|
||||
### `customResources` (optional)
|
||||
|
||||
@@ -219,6 +231,26 @@ The custom resource's apiVersion.
|
||||
|
||||
The plural representing the custom resource.
|
||||
|
||||
### `apiVersionOverrides` (optional)
|
||||
|
||||
Overrides for the API versions used to make requests for the corresponding
|
||||
objects. If using a legacy Kubernetes version, you may use this config to
|
||||
override the default API versions to ones that are supported by your cluster.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
kubernetes:
|
||||
apiVersionOverrides:
|
||||
cronjobs: 'v1beta1'
|
||||
```
|
||||
|
||||
For more information on which API versions are supported by your cluster, please
|
||||
view the Kubernetes API docs for your Kubernetes version (e.g.
|
||||
[API Groups for v1.22](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#-strong-api-groups-strong-)
|
||||
)
|
||||
|
||||
### Role Based Access Control
|
||||
|
||||
The current RBAC permissions required are read-only cluster wide, for the
|
||||
|
||||
@@ -114,13 +114,15 @@ const routes = (
|
||||
In `Root.tsx`, add the `SidebarSearchModal` component:
|
||||
|
||||
```bash
|
||||
import { SidebarSearchModal } from '@backstage/plugin-search';
|
||||
import { SidebarSearchModal, SearchContextProvider } from '@backstage/plugin-search';
|
||||
|
||||
export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
<SidebarSearchModal />
|
||||
<SearchContextProvider>
|
||||
<SidebarSearchModal />
|
||||
</SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
...
|
||||
```
|
||||
@@ -154,13 +156,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 +291,10 @@ const indexBuilder = new IndexBuilder({ logger, searchEngine });
|
||||
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: new DefaultCatalogCollator({ discovery }),
|
||||
collator: new DefaultCatalogCollator({
|
||||
discovery,
|
||||
tokenManager,
|
||||
}),
|
||||
});
|
||||
|
||||
indexBuilder.addCollator({
|
||||
@@ -303,6 +312,9 @@ its `defaultRefreshIntervalSeconds` value, like this:
|
||||
```typescript {3}
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: new DefaultCatalogCollator({ discovery }),
|
||||
collator: new DefaultCatalogCollator({
|
||||
discovery,
|
||||
tokenManager,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
@@ -4,9 +4,9 @@ title: Search Engines
|
||||
description: Choosing and configuring your search engine for Backstage
|
||||
---
|
||||
|
||||
Backstage supports 2 search engines by default, an in-memory engine called Lunr
|
||||
and ElasticSearch. You can configure your own search engines by implementing the
|
||||
provided interface as mentioned in the
|
||||
Backstage supports 3 search engines by default, an in-memory engine called Lunr,
|
||||
ElasticSearch and Postgres. You can configure your own search engines by
|
||||
implementing the provided interface as mentioned in the
|
||||
[search backend documentation.](./getting-started.md#Backend)
|
||||
|
||||
Provided search engine implementations have their own way of constructing
|
||||
|
||||
@@ -18,17 +18,31 @@ The next step is to add
|
||||
[add templates](http://backstage.io/docs/features/software-templates/adding-templates)
|
||||
to your Backstage app.
|
||||
|
||||
### GitHub
|
||||
### Publishing defaults
|
||||
|
||||
For GitHub, you can configure who can see the new repositories that are created
|
||||
by specifying `visibility` option. Valid options are `public`, `private` and
|
||||
`internal`. The `internal` option is for GitHub Enterprise clients, which means
|
||||
public within the enterprise.
|
||||
Software templates can define _publish_ actions, such as `publish:github`, to
|
||||
create new repositories or submit pull / merge requests to existing
|
||||
repositories. You can configure the author and commit message through the
|
||||
`scaffolder` configuration in `app-config.yaml`:
|
||||
|
||||
```yaml
|
||||
scaffolder:
|
||||
github:
|
||||
visibility: public # or 'internal' or 'private'
|
||||
defaultAuthor:
|
||||
name: M.C. Hammer # Defaults to `Scaffolder`
|
||||
email: hammer@donthurtem.com # Defaults to `scaffolder@backstage.io`
|
||||
defaultCommitMessage: "U can't touch this" # Defaults to 'Initial commit'
|
||||
```
|
||||
|
||||
To configure who can see the new repositories created from software templates,
|
||||
add the `repoVisibility` key within a software template:
|
||||
|
||||
```yaml
|
||||
- id: publish
|
||||
name: Publish
|
||||
action: publish:github
|
||||
input:
|
||||
repoUrl: '{{ parameters.repoUrl }}'
|
||||
repoVisibility: public # or 'internal' or 'private'
|
||||
```
|
||||
|
||||
### Disabling Docker in Docker situation (Optional)
|
||||
@@ -53,3 +67,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.
|
||||

|
||||
|
||||
@@ -12,7 +12,7 @@ code, template in some variables, and then publish the template to some
|
||||
locations like GitHub or GitLab.
|
||||
|
||||
<video width="100%" height="100%" controls>
|
||||
<source src="https://backstage.io/blog/assets/2020-08-05/feature.mp4" type="video/mp4">
|
||||
<source src="https://backstage.io/blog/assets/2020-08-05/feature.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
### Getting Started
|
||||
|
||||
@@ -40,7 +40,7 @@ storage system (e.g. AWS S3, GCS or Azure Blob Storage). Read more in
|
||||
|
||||
## Recommended deployment
|
||||
|
||||
This is how we recommend deploying TechDocs in production environment.
|
||||
This is how we recommend deploying TechDocs in a production environment.
|
||||
|
||||
<img data-zoomable src="../../assets/techdocs/architecture-recommended.drawio.svg" alt="TechDocs Architecture diagram" />
|
||||
|
||||
@@ -58,12 +58,12 @@ Similar to how it is done in the Basic setup, the TechDocs Reader requests
|
||||
your configured storage solution for the necessary files and returns them to
|
||||
TechDocs Reader.
|
||||
|
||||
Note about caching: We have noticed internally that some storage providers can
|
||||
be quite slow, which is why we are recommending a cache that sits between the
|
||||
TechDocs Reader and the Storage.
|
||||
|
||||
_Feel free to suggest better ideas to us in #docs-like-code channel in Discord
|
||||
or via a GitHub issue._
|
||||
Depending on your chosen cloud storage provider and its real-world proximity to
|
||||
your backend server, there may be a comparably high amount of latency when
|
||||
loading TechDocs sites using this deployment approach. If you encounter this,
|
||||
you can optionally configure the `techdocs-backend` to cache responses in a
|
||||
cache store
|
||||
[supported by Backstage](../../overview/architecture-overview.md#cache).
|
||||
|
||||
### Security consideration
|
||||
|
||||
|
||||
@@ -135,6 +135,22 @@ techdocs:
|
||||
# the old, case-sensitive entity triplet behavior.
|
||||
legacyUseCaseSensitiveTripletPaths: false
|
||||
|
||||
# techdocs.cache is optional, and is only recommended when you've configured
|
||||
# an external techdocs.publisher.type above. Also requires backend.cache to
|
||||
# be configured with a valid cache store.
|
||||
cache:
|
||||
# Represents the number of milliseconds a statically built asset should
|
||||
# stay cached. Cache invalidation is handled automatically by the frontend,
|
||||
# which compares the build times in cached metadata vs. canonical storage,
|
||||
# allowing long TTLs (e.g. 1 month/year)
|
||||
ttl: 3600000
|
||||
|
||||
# (Optional) The time (in milliseconds) that the TechDocs backend will wait
|
||||
# for a cache service to respond before continuing on as though the cached
|
||||
# object was not found (e.g. when the cache sercice is unavailable). The
|
||||
# default value is 1000
|
||||
readTimeout: 500
|
||||
|
||||
# (Optional and Legacy) TechDocs makes API calls to techdocs-backend using this URL. e.g. get docs of an entity, get metadata, etc.
|
||||
# You don't have to specify this anymore.
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ This will create a new Backstage App inside the current folder. The name of the
|
||||
app-folder is the name that was provided when prompted.
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/create-app_output.png' width='600' alt='create app'>
|
||||
<img src='../assets/getting-started/create-app_output.png' width='600' alt='create app' />
|
||||
</p>
|
||||
|
||||
Inside that directory, it will generate all the files and folder structure
|
||||
|
||||
@@ -23,7 +23,7 @@ guide to do a repository-based installation.
|
||||
|
||||
- Access to a Linux-based operating system, such as Linux, MacOS or
|
||||
[Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/)
|
||||
- An account with elevated rights
|
||||
- An account with elevated rights to install the dependencies
|
||||
- `curl` or `wget` installed
|
||||
- Node.js Active LTS Release installed (currently v14) using one of these
|
||||
methods:
|
||||
@@ -36,15 +36,16 @@ guide to do a repository-based installation.
|
||||
- `yarn` [Installation](https://classic.yarnpkg.com/en/docs/install)
|
||||
- `docker` [installation](https://docs.docker.com/engine/install/)
|
||||
- `git` [installation](https://github.com/git-guides/install-git)
|
||||
- If the system is not directly accessible over your network, the following
|
||||
ports need to be opened: 3000, 7007
|
||||
- If the system is not directly accessible over your network the following ports
|
||||
need to be opened: 3000, 7007. This is quite uncommon, unless when you're
|
||||
installing in a container, VM or remote system.
|
||||
|
||||
### Create your Backstage App
|
||||
|
||||
To install the Backstage Standalone app, we make use of `npx`, a tool to run
|
||||
Node executables straight from the registry. Running the command below will
|
||||
install Backstage. The wizard will create a subdirectory inside your current
|
||||
working directory.
|
||||
Node executables straight from the registry. This tool is part of your Node.js
|
||||
installation. Running the command below will install Backstage. The wizard will
|
||||
create a subdirectory inside your current working directory.
|
||||
|
||||
```bash
|
||||
npx @backstage/create-app
|
||||
@@ -57,7 +58,7 @@ The wizard will ask you
|
||||
SQLite option.
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/wizard.png' alt='Screenshot of the wizard asking for a name for the app, and a selection menu for the database.'>
|
||||
<img src='../assets/getting-started/wizard.png' alt='Screenshot of the wizard asking for a name for the app, and a selection menu for the database.' />
|
||||
</p>
|
||||
|
||||
### Run the Backstage app
|
||||
@@ -72,18 +73,27 @@ yarn dev
|
||||
```
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/startup.png' alt='Screenshot of the command output, with the message web pack compiled successfully.'>
|
||||
<img src='../assets/getting-started/startup.png' alt='Screenshot of the command output, with the message web pack compiled successfully.'/>
|
||||
</p>
|
||||
|
||||
It might take a little while, but as soon as the message
|
||||
`[0] webpack compiled successfully` appears, you can open a browser and directly
|
||||
navigate to your freshly installed Backstage portal at `http://localhost:3000`.
|
||||
You can start exploring the demo immediately.
|
||||
You can start exploring the demo immediately. Please note that the in-memory
|
||||
database will be cleared when you restart the app, so you'll most likely want to
|
||||
carry on with the database steps.
|
||||
|
||||
<p align='center'>
|
||||
<img src='../assets/getting-started/portal.png' alt='Screenshot of the Backstage portal.'>
|
||||
<img src='../assets/getting-started/portal.png' alt='Screenshot of the Backstage portal.'/>
|
||||
</p>
|
||||
|
||||
The most common next steps are to move to a persistent database, configure
|
||||
authentication, and add a plugin:
|
||||
|
||||
- [Switching from SQLite to PostgresQL](https://backstage.io/docs/tutorials/switching-sqlite-postgres)
|
||||
- [Setting up Authentication](https://backstage.io/docs/auth/)
|
||||
- [Adding a plugin](https://backstage.io/docs/getting-started/configure-app-with-plugins)
|
||||
|
||||
Congratulations! That should be it. Let us know how it went:
|
||||
[on discord](https://discord.gg/EBHEGzX), file issues for any
|
||||
[feature](https://github.com/backstage/backstage/issues/new?labels=help+wanted&template=feature_template.md)
|
||||
@@ -93,10 +103,3 @@ or
|
||||
[bugs](https://github.com/backstage/backstage/issues/new?labels=bug&template=bug_template.md)
|
||||
you have, and feel free to
|
||||
[contribute](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md)!
|
||||
|
||||
The most common next steps are to configure Backstage, add a plugin and moving
|
||||
to a more persistent database:
|
||||
|
||||
- [Setting up Authentication](https://backstage.io/docs/auth/)
|
||||
- [Switching from SQLite to PostgresQL](https://backstage.io/docs/tutorials/switching-sqlite-postgres)
|
||||
- [Adding a plugin](https://backstage.io/docs/getting-started/configure-app-with-plugins)
|
||||
|
||||
@@ -166,13 +166,9 @@ are separated out into their own folder, see further down.
|
||||
plugin and [techdocs-cli](https://github.com/backstage/techdocs-cli).
|
||||
|
||||
- [`test-utils/`](https://github.com/backstage/backstage/tree/master/packages/test-utils) -
|
||||
This package contains more general purpose testing facilities for testing a
|
||||
This package contains general purpose testing facilities for testing a
|
||||
Backstage App or its plugins.
|
||||
|
||||
- [`test-utils-core/`](https://github.com/backstage/backstage/tree/master/packages/test-utils-core) -
|
||||
This package contains specific testing facilities used when testing Backstage
|
||||
core internals.
|
||||
|
||||
- [`theme/`](https://github.com/backstage/backstage/tree/master/packages/theme) -
|
||||
Holds the Backstage Theme.
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ common example being the `migrations` directory.
|
||||
Usage: backstage-cli backend:build [options]
|
||||
|
||||
Options:
|
||||
--minify Minify the generated code
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
@@ -371,6 +372,7 @@ the monorepo.
|
||||
Usage: backstage-cli plugin:build [options]
|
||||
|
||||
Options:
|
||||
--minify Minify the generated code
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -175,15 +175,6 @@ Utilities for writing tests for Backstage plugins and apps.
|
||||
|
||||
Stability: `2`
|
||||
|
||||
### `test-utils-core` [GitHub](https://github.com/backstage/backstage/tree/master/packages/test-utils-core/)
|
||||
|
||||
Internal testing utilities that are separated out for usage in
|
||||
@backstage/core-app-api and @backstage/core-plugin-api. All exports are
|
||||
re-exported by @backstage/test-utils. This package should not be depended on
|
||||
directly.
|
||||
|
||||
Stability: See @backstage/test-utils
|
||||
|
||||
### `theme` [GitHub](https://github.com/backstage/backstage/tree/master/packages/theme/)
|
||||
|
||||
The core Backstage MUI theme along with customization utilities.
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -7,7 +7,7 @@ authorURL: https://twitter.com/stalund
|
||||
**TL;DR** Today we are announcing a new Backstage feature: Software Templates. Simplify setup, standardize tooling, and deploy with the click of a button. Using automated templates, your engineers can spin up a new microservice, website, or other software component with your organization’s best practices built-in, right from the start.
|
||||
|
||||
<video width="100%" height="100%" controls>
|
||||
<source src="/blog/assets/2020-08-05/feature.mp4" type="video/mp4">
|
||||
<source src="/blog/assets/2020-08-05/feature.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
@@ -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.1",
|
||||
"yarn-lock-check": "^1.0.5"
|
||||
},
|
||||
"prettier": "@spotify/prettier-config"
|
||||
|
||||
+4
-4
@@ -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.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
|
||||
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
|
||||
|
||||
prismjs@^1.22.0:
|
||||
version "1.25.0"
|
||||
|
||||
+4
-1
@@ -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",
|
||||
@@ -61,7 +63,8 @@
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.14.0",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"@spotify/prettier-config": "^11.0.0",
|
||||
"@spotify/prettier-config": "^12.0.0",
|
||||
"@types/node": "^14.14.32",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"cross-env": "^7.0.0",
|
||||
|
||||
@@ -29,17 +29,17 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/core-components": "^0.7.4",
|
||||
"@backstage/core-app-api": "^0.1.21",
|
||||
"@backstage/core-plugin-api": "^0.2.0",
|
||||
"@backstage/theme": "^0.2.13",
|
||||
"@backstage/core-components": "^0.7.6",
|
||||
"@backstage/core-app-api": "^0.1.24",
|
||||
"@backstage/core-plugin-api": "^0.2.2",
|
||||
"@backstage/theme": "^0.2.14",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"react": "^16.12.0",
|
||||
"react-router-dom": "6.0.0-beta.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.9.0",
|
||||
"@backstage/cli": "^0.10.0",
|
||||
"@backstage/test-utils": "^0.1.22",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.55
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-azure-devops@0.1.5
|
||||
- @backstage/core-components@0.7.6
|
||||
- @backstage/theme@0.2.14
|
||||
- @backstage/plugin-user-settings@0.3.12
|
||||
- @backstage/plugin-api-docs@0.6.16
|
||||
- @backstage/cli@0.10.0
|
||||
- @backstage/plugin-circleci@0.2.30
|
||||
- @backstage/core-plugin-api@0.2.2
|
||||
- @backstage/plugin-search@0.5.0
|
||||
- @backstage/plugin-tech-insights@0.1.0
|
||||
- @backstage/core-app-api@0.1.24
|
||||
- @backstage/plugin-kubernetes@0.4.22
|
||||
- @backstage/plugin-scaffolder@0.11.13
|
||||
- @backstage/plugin-techdocs@0.12.8
|
||||
|
||||
## 0.2.53
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+15
-14
@@ -1,24 +1,24 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.53",
|
||||
"version": "0.2.55",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/app-defaults": "^0.1.1",
|
||||
"@backstage/catalog-model": "^0.9.7",
|
||||
"@backstage/cli": "^0.9.0",
|
||||
"@backstage/core-app-api": "^0.1.21",
|
||||
"@backstage/core-components": "^0.7.4",
|
||||
"@backstage/core-plugin-api": "^0.2.0",
|
||||
"@backstage/cli": "^0.10.0",
|
||||
"@backstage/core-app-api": "^0.1.24",
|
||||
"@backstage/core-components": "^0.7.6",
|
||||
"@backstage/core-plugin-api": "^0.2.2",
|
||||
"@backstage/integration-react": "^0.1.14",
|
||||
"@backstage/plugin-api-docs": "^0.6.14",
|
||||
"@backstage/plugin-azure-devops": "^0.1.4",
|
||||
"@backstage/plugin-api-docs": "^0.6.16",
|
||||
"@backstage/plugin-azure-devops": "^0.1.5",
|
||||
"@backstage/plugin-badges": "^0.2.14",
|
||||
"@backstage/plugin-catalog": "^0.7.3",
|
||||
"@backstage/plugin-catalog-graph": "^0.2.2",
|
||||
"@backstage/plugin-catalog-import": "^0.7.4",
|
||||
"@backstage/plugin-catalog-react": "^0.6.4",
|
||||
"@backstage/plugin-circleci": "^0.2.29",
|
||||
"@backstage/plugin-circleci": "^0.2.30",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.28",
|
||||
"@backstage/plugin-code-coverage": "^0.1.18",
|
||||
"@backstage/plugin-cost-insights": "^0.11.11",
|
||||
@@ -29,22 +29,23 @@
|
||||
"@backstage/plugin-home": "^0.4.6",
|
||||
"@backstage/plugin-jenkins": "^0.5.12",
|
||||
"@backstage/plugin-kafka": "^0.2.21",
|
||||
"@backstage/plugin-kubernetes": "^0.4.20",
|
||||
"@backstage/plugin-kubernetes": "^0.4.22",
|
||||
"@backstage/plugin-lighthouse": "^0.2.30",
|
||||
"@backstage/plugin-newrelic": "^0.3.9",
|
||||
"@backstage/plugin-org": "^0.3.28",
|
||||
"@backstage/plugin-pagerduty": "0.3.18",
|
||||
"@backstage/plugin-rollbar": "^0.3.19",
|
||||
"@backstage/plugin-scaffolder": "^0.11.11",
|
||||
"@backstage/plugin-search": "^0.4.18",
|
||||
"@backstage/plugin-scaffolder": "^0.11.13",
|
||||
"@backstage/plugin-search": "^0.5.0",
|
||||
"@backstage/plugin-sentry": "^0.3.29",
|
||||
"@backstage/plugin-shortcuts": "^0.1.14",
|
||||
"@backstage/plugin-tech-radar": "^0.4.12",
|
||||
"@backstage/plugin-techdocs": "^0.12.6",
|
||||
"@backstage/plugin-techdocs": "^0.12.8",
|
||||
"@backstage/plugin-todo": "^0.1.15",
|
||||
"@backstage/plugin-user-settings": "^0.3.11",
|
||||
"@backstage/plugin-user-settings": "^0.3.12",
|
||||
"@backstage/search-common": "^0.2.0",
|
||||
"@backstage/theme": "^0.2.11",
|
||||
"@backstage/plugin-tech-insights": "^0.1.0",
|
||||
"@backstage/theme": "^0.2.14",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
SignInPage,
|
||||
} from '@backstage/core-components';
|
||||
import { apiDocsPlugin, ApiExplorerPage } from '@backstage/plugin-api-docs';
|
||||
import { AzurePullRequestsPage } from '@backstage/plugin-azure-devops';
|
||||
import {
|
||||
CatalogEntityPage,
|
||||
CatalogIndexPage,
|
||||
@@ -175,7 +176,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>
|
||||
@@ -203,6 +217,7 @@ const routes = (
|
||||
element={<CostInsightsLabelDataflowInstructionsPage />}
|
||||
/>
|
||||
<Route path="/settings" element={<UserSettingsPage />} />
|
||||
<Route path="/azure-pull-requests" element={<AzurePullRequestsPage />} />
|
||||
</FlatRoutes>
|
||||
);
|
||||
|
||||
|
||||
@@ -29,7 +29,10 @@ import LogoIcon from './LogoIcon';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { GraphiQLIcon } from '@backstage/plugin-graphiql';
|
||||
import { Settings as SidebarSettings } from '@backstage/plugin-user-settings';
|
||||
import { SidebarSearchModal } from '@backstage/plugin-search';
|
||||
import {
|
||||
SidebarSearchModal,
|
||||
SearchContextProvider,
|
||||
} from '@backstage/plugin-search';
|
||||
import { Shortcuts } from '@backstage/plugin-shortcuts';
|
||||
import {
|
||||
Sidebar,
|
||||
@@ -41,6 +44,7 @@ import {
|
||||
SidebarSpace,
|
||||
SidebarScrollWrapper,
|
||||
} from '@backstage/core-components';
|
||||
import { AzurePullRequestsIcon } from '@backstage/plugin-azure-devops';
|
||||
|
||||
const useSidebarLogoStyles = makeStyles({
|
||||
root: {
|
||||
@@ -79,7 +83,9 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
<SidebarSearchModal />
|
||||
<SearchContextProvider>
|
||||
<SidebarSearchModal />
|
||||
</SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
{/* Global nav, not org-specific */}
|
||||
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
|
||||
@@ -94,6 +100,11 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarItem icon={RuleIcon} to="lighthouse" text="Lighthouse" />
|
||||
<SidebarItem icon={MoneyIcon} to="cost-insights" text="Cost Insights" />
|
||||
<SidebarItem icon={GraphiQLIcon} to="graphiql" text="GraphiQL" />
|
||||
<SidebarItem
|
||||
icon={AzurePullRequestsIcon}
|
||||
to="azure-pull-requests"
|
||||
text="Azure PRs"
|
||||
/>
|
||||
</SidebarScrollWrapper>
|
||||
<SidebarDivider />
|
||||
<Shortcuts />
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.9.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 905dd952ac: Create a `TokenManager` interface and `ServerTokenManager` implementation to generate and validate server tokens for authenticated backend-to-backend API requests.
|
||||
- 6b500622d5: Move to using node-fetch internally instead of cross-fetch
|
||||
- 54989b671d: Fixed a potential crash in the log redaction code
|
||||
- Updated dependencies
|
||||
- @backstage/integration@0.6.10
|
||||
- @backstage/config-loader@0.8.1
|
||||
|
||||
## 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
|
||||
|
||||
@@ -175,9 +175,17 @@ export function createStatusCheckRouter(options: {
|
||||
// @public (undocumented)
|
||||
export class DatabaseManager {
|
||||
forPlugin(pluginId: string): PluginDatabaseManager;
|
||||
static fromConfig(config: Config): DatabaseManager;
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
options?: DatabaseManagerOptions,
|
||||
): DatabaseManager;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type DatabaseManagerOptions = {
|
||||
migrations?: PluginDatabaseManager['migrations'];
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export class DockerContainerRunner implements ContainerRunner {
|
||||
constructor({ dockerClient }: { dockerClient: Docker });
|
||||
@@ -395,6 +403,9 @@ export type PluginCacheManager = {
|
||||
// @public
|
||||
export interface PluginDatabaseManager {
|
||||
getClient(): Promise<Knex>;
|
||||
migrations?: {
|
||||
skip?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// @public
|
||||
@@ -526,6 +537,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 +608,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>;
|
||||
@@ -618,4 +653,8 @@ export function useHotCleanup(
|
||||
|
||||
// @public
|
||||
export function useHotMemoize<T>(_module: NodeModule, valueFactory: () => T): T;
|
||||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/database/types.d.ts:23:12 - (tsdoc-undefined-tag) The TSDoc tag "@default" is not defined in this configuration
|
||||
```
|
||||
|
||||
Vendored
+28
@@ -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. */
|
||||
@@ -82,6 +96,12 @@ export interface Config {
|
||||
* @default database
|
||||
*/
|
||||
pluginDivisionMode?: 'database' | 'schema';
|
||||
/**
|
||||
* Arbitrary config object to pass to knex when initializing
|
||||
* (https://knexjs.org/#Installation-client). Most notable is the debug
|
||||
* and asyncStackTraces booleans
|
||||
*/
|
||||
knexConfig?: object;
|
||||
/** Plugin specific database configuration and client override */
|
||||
plugin?: {
|
||||
[pluginId: string]: {
|
||||
@@ -97,6 +117,14 @@ export interface Config {
|
||||
* Defaults to base config if unspecified.
|
||||
*/
|
||||
ensureExists?: boolean;
|
||||
/**
|
||||
* Arbitrary config object to pass to knex when initializing
|
||||
* (https://knexjs.org/#Installation-client). Most notable is the
|
||||
* debug and asyncStackTraces booleans.
|
||||
*
|
||||
* This is merged recursively into the base knexConfig
|
||||
*/
|
||||
knexConfig?: object;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.9.10",
|
||||
"version": "0.9.12",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -31,9 +31,9 @@
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.6",
|
||||
"@backstage/config": "^0.1.11",
|
||||
"@backstage/config-loader": "^0.8.0",
|
||||
"@backstage/errors": "^0.1.4",
|
||||
"@backstage/integration": "^0.6.9",
|
||||
"@backstage/config-loader": "^0.8.1",
|
||||
"@backstage/errors": "^0.1.5",
|
||||
"@backstage/integration": "^0.6.10",
|
||||
"@backstage/types": "^0.1.1",
|
||||
"@google-cloud/storage": "^5.8.0",
|
||||
"@lerna/project": "^4.0.0",
|
||||
@@ -46,7 +46,6 @@
|
||||
"compression": "^1.7.4",
|
||||
"concat-stream": "^2.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"cross-fetch": "^3.0.6",
|
||||
"dockerode": "^3.3.1",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
@@ -54,6 +53,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",
|
||||
@@ -63,6 +63,7 @@
|
||||
"minimist": "^1.2.5",
|
||||
"morgan": "^1.10.0",
|
||||
"node-abort-controller": "^3.0.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"raw-body": "^2.4.1",
|
||||
"selfsigned": "^1.10.7",
|
||||
"stoppable": "^1.1.0",
|
||||
@@ -80,8 +81,8 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.9.0",
|
||||
"@backstage/test-utils": "^0.1.22",
|
||||
"@backstage/cli": "^0.10.0",
|
||||
"@backstage/test-utils": "^0.1.23",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
"@types/concat-stream": "^1.6.0",
|
||||
|
||||
@@ -36,25 +36,45 @@ describe('DatabaseManager', () => {
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
|
||||
describe('DatabaseManager.fromConfig', () => {
|
||||
it('accesses the backend.database key', () => {
|
||||
const config = new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'pg',
|
||||
connection: {
|
||||
host: 'localhost',
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
database: 'foodb',
|
||||
},
|
||||
const backendConfig = {
|
||||
backend: {
|
||||
database: {
|
||||
client: 'pg',
|
||||
connection: {
|
||||
host: 'localhost',
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
database: 'foodb',
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
it('accesses the backend.database key', () => {
|
||||
const config = new ConfigReader(backendConfig);
|
||||
const getConfigSpy = jest.spyOn(config, 'getConfig');
|
||||
DatabaseManager.fromConfig(config);
|
||||
|
||||
expect(getConfigSpy).toHaveBeenCalledWith('backend.database');
|
||||
});
|
||||
|
||||
it('handles default options', () => {
|
||||
const config = new ConfigReader(backendConfig);
|
||||
const database = DatabaseManager.fromConfig(config);
|
||||
const client = database.forPlugin('test');
|
||||
|
||||
expect(client.migrations?.skip).toBe(false);
|
||||
});
|
||||
|
||||
it('handles migrations options', () => {
|
||||
const config = new ConfigReader(backendConfig);
|
||||
const database = DatabaseManager.fromConfig(config, {
|
||||
migrations: { skip: true },
|
||||
});
|
||||
const client = database.forPlugin('test');
|
||||
|
||||
expect(client.migrations?.skip).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DatabaseManager.forPlugin', () => {
|
||||
@@ -505,5 +525,42 @@ describe('DatabaseManager', () => {
|
||||
'database_name_overriden',
|
||||
);
|
||||
});
|
||||
|
||||
it('fetches and merges additional knex config', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'pg',
|
||||
connection: {
|
||||
host: 'localhost',
|
||||
database: 'foodb',
|
||||
},
|
||||
knexConfig: {
|
||||
something: false,
|
||||
},
|
||||
plugin: {
|
||||
testdbname: {
|
||||
knexConfig: {
|
||||
debug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
await testManager.forPlugin('testdbname').getClient();
|
||||
|
||||
const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1);
|
||||
const [baseConfig] = mockCalls[0];
|
||||
|
||||
expect(baseConfig.data).toEqual(
|
||||
expect.objectContaining({
|
||||
debug: true,
|
||||
something: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,20 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Knex } from 'knex';
|
||||
import { omit } from 'lodash';
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { Knex } from 'knex';
|
||||
import { merge, omit } from 'lodash';
|
||||
import { mergeDatabaseConfig } from './config';
|
||||
import {
|
||||
createNameOverride,
|
||||
ensureDatabaseExists,
|
||||
normalizeConnection,
|
||||
createSchemaOverride,
|
||||
ensureSchemaExists,
|
||||
createDatabaseClient,
|
||||
createNameOverride,
|
||||
createSchemaOverride,
|
||||
ensureDatabaseExists,
|
||||
ensureSchemaExists,
|
||||
normalizeConnection,
|
||||
} from './connection';
|
||||
import { PluginDatabaseManager } from './types';
|
||||
import { mergeDatabaseConfig } from './config';
|
||||
|
||||
/**
|
||||
* Provides a config lookup path for a plugin's config block.
|
||||
@@ -36,6 +36,15 @@ function pluginPath(pluginId: string): string {
|
||||
return `plugin.${pluginId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options object.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type DatabaseManagerOptions = {
|
||||
migrations?: PluginDatabaseManager['migrations'];
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export class DatabaseManager {
|
||||
/**
|
||||
@@ -47,19 +56,25 @@ export class DatabaseManager {
|
||||
* names if config is not provided.
|
||||
*
|
||||
* @param config - The loaded application configuration.
|
||||
* @param options - An optional configuration object.
|
||||
*/
|
||||
static fromConfig(config: Config): DatabaseManager {
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
options?: DatabaseManagerOptions,
|
||||
): DatabaseManager {
|
||||
const databaseConfig = config.getConfig('backend.database');
|
||||
|
||||
return new DatabaseManager(
|
||||
databaseConfig,
|
||||
databaseConfig.getOptionalString('prefix'),
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(
|
||||
private readonly config: Config,
|
||||
private readonly prefix: string = 'backstage_plugin_',
|
||||
private readonly options?: DatabaseManagerOptions,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -76,6 +91,10 @@ export class DatabaseManager {
|
||||
getClient(): Promise<Knex> {
|
||||
return _this.getDatabase(pluginId);
|
||||
},
|
||||
migrations: {
|
||||
skip: false,
|
||||
..._this.options?.migrations,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -138,6 +157,24 @@ export class DatabaseManager {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the knexConfig which should be used for a given plugin.
|
||||
*
|
||||
* @param pluginId Plugin to get the knexConfig for
|
||||
* @returns the merged kexConfig value or undefined if it isn't specified
|
||||
*/
|
||||
private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {
|
||||
const pluginConfig = this.config
|
||||
.getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)
|
||||
?.get<JsonObject>();
|
||||
|
||||
const baseConfig = this.config
|
||||
.getOptionalConfig('knexConfig')
|
||||
?.get<JsonObject>();
|
||||
|
||||
return merge(baseConfig, pluginConfig);
|
||||
}
|
||||
|
||||
private getEnsureExistsConfig(pluginId: string): boolean {
|
||||
const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;
|
||||
return (
|
||||
@@ -200,6 +237,7 @@ export class DatabaseManager {
|
||||
const { client } = this.getClientType(pluginId);
|
||||
|
||||
return {
|
||||
...this.getAdditionalKnexConfig(pluginId),
|
||||
client,
|
||||
connection: this.getConnectionConfig(pluginId),
|
||||
};
|
||||
|
||||
@@ -30,6 +30,18 @@ export interface PluginDatabaseManager {
|
||||
* stores so that plugins are discouraged from database integration.
|
||||
*/
|
||||
getClient(): Promise<Knex>;
|
||||
|
||||
/**
|
||||
* This property is used to control the behavior of database migrations.
|
||||
*/
|
||||
migrations?: {
|
||||
/**
|
||||
* skip database migrations. Useful if connecting to a read-only database.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
skip?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,4 +31,5 @@ export * from './paths';
|
||||
export * from './reading';
|
||||
export * from './scm';
|
||||
export * from './service';
|
||||
export * from './tokens';
|
||||
export * from './util';
|
||||
|
||||
@@ -54,10 +54,13 @@ export function setRootLoggerRedactionList(redactionList: string[]) {
|
||||
* and replaces them with the corresponding identifier.
|
||||
*/
|
||||
function redactLogLine(info: winston.Logform.TransformableInfo) {
|
||||
// TODO(hhogg): The logger is created before the config is loaded,
|
||||
// because the logger is needed in the config loader. There is a risk of
|
||||
// a secret being logged out during the config loading stage.
|
||||
if (redactionRegExp) {
|
||||
// TODO(hhogg): The logger is created before the config is loaded, because the
|
||||
// logger is needed in the config loader. There is a risk of a secret being
|
||||
// logged out during the config loading stage.
|
||||
// TODO(freben): Added a check that info.message actually was a string,
|
||||
// because it turned out that this was not necessarily guaranteed.
|
||||
// https://github.com/backstage/backstage/issues/8306
|
||||
if (redactionRegExp && typeof info.message === 'string') {
|
||||
info.message = info.message.replace(redactionRegExp, '[REDACTED]');
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
getAzureRequestOptions,
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import fetch from 'cross-fetch';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import { Minimatch } from 'minimatch';
|
||||
import { Readable } from 'stream';
|
||||
import { NotFoundError, NotModifiedError } from '@backstage/errors';
|
||||
@@ -72,7 +72,13 @@ export class AzureUrlReader implements UrlReader {
|
||||
try {
|
||||
response = await fetch(builtUrl, {
|
||||
...getAzureRequestOptions(this.integration.config),
|
||||
...(signal && { signal }),
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can
|
||||
// be removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
...(signal && { signal: signal as any }),
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`Unable to read ${url}, ${e}`);
|
||||
@@ -123,7 +129,13 @@ export class AzureUrlReader implements UrlReader {
|
||||
...getAzureRequestOptions(this.integration.config, {
|
||||
Accept: 'application/zip',
|
||||
}),
|
||||
...(signal && { signal }),
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can be
|
||||
// removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
...(signal && { signal: signal as any }),
|
||||
});
|
||||
if (!archiveAzureResponse.ok) {
|
||||
const message = `Failed to read tree from ${url}, ${archiveAzureResponse.status} ${archiveAzureResponse.statusText}`;
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
getBitbucketRequestOptions,
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import fetch from 'cross-fetch';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { trimEnd } from 'lodash';
|
||||
import { Minimatch } from 'minimatch';
|
||||
@@ -94,7 +94,13 @@ export class BitbucketUrlReader implements UrlReader {
|
||||
try {
|
||||
response = await fetch(bitbucketUrl.toString(), {
|
||||
...requestOptions,
|
||||
...(signal && { signal }),
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can be
|
||||
// removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
...(signal && { signal: signal as any }),
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`Unable to read ${url}, ${e}`);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { NotFoundError, NotModifiedError } from '@backstage/errors';
|
||||
import fetch from 'cross-fetch';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import {
|
||||
ReaderFactory,
|
||||
ReadTreeResponse,
|
||||
@@ -86,7 +86,13 @@ export class FetchUrlReader implements UrlReader {
|
||||
headers: {
|
||||
...(options?.etag && { 'If-None-Match': options.etag }),
|
||||
},
|
||||
signal: options?.signal,
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can
|
||||
// be removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
signal: options?.signal as any,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`Unable to read ${url}, ${e}`);
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import { RestEndpointMethodTypes } from '@octokit/rest';
|
||||
import fetch from 'cross-fetch';
|
||||
import fetch, { RequestInit, Response } from 'node-fetch';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { Minimatch } from 'minimatch';
|
||||
import { Readable } from 'stream';
|
||||
@@ -110,7 +110,13 @@ export class GithubUrlReader implements UrlReader {
|
||||
...(options?.etag && { 'If-None-Match': options.etag }),
|
||||
Accept: 'application/vnd.github.v3.raw',
|
||||
},
|
||||
signal: options?.signal,
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can
|
||||
// be removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
signal: options?.signal as any,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`Unable to read ${url}, ${e}`);
|
||||
@@ -165,7 +171,13 @@ export class GithubUrlReader implements UrlReader {
|
||||
repoDetails.repo.archive_url,
|
||||
commitSha,
|
||||
filepath,
|
||||
{ headers, signal: options?.signal },
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can be
|
||||
// removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
{ headers, signal: options?.signal as any },
|
||||
options,
|
||||
);
|
||||
}
|
||||
@@ -189,7 +201,7 @@ export class GithubUrlReader implements UrlReader {
|
||||
repoDetails.repo.archive_url,
|
||||
commitSha,
|
||||
filepath,
|
||||
{ headers, signal: options?.signal },
|
||||
{ headers, signal: options?.signal as any },
|
||||
);
|
||||
|
||||
return { files, etag: commitSha };
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
GitLabIntegration,
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import fetch from 'cross-fetch';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { Minimatch } from 'minimatch';
|
||||
import { Readable } from 'stream';
|
||||
@@ -76,7 +76,13 @@ export class GitlabUrlReader implements UrlReader {
|
||||
...getGitLabRequestOptions(this.integration.config).headers,
|
||||
...(etag && { 'If-None-Match': etag }),
|
||||
},
|
||||
...(signal && { signal }),
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can be
|
||||
// removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
...(signal && { signal: signal as any }),
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(`Unable to read ${url}, ${e}`);
|
||||
@@ -145,7 +151,13 @@ export class GitlabUrlReader implements UrlReader {
|
||||
).toString(),
|
||||
{
|
||||
...getGitLabRequestOptions(this.integration.config),
|
||||
...(signal && { signal }),
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can
|
||||
// be removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
...(signal && { signal: signal as any }),
|
||||
},
|
||||
);
|
||||
if (!commitsGitlabResponse.ok) {
|
||||
@@ -169,7 +181,13 @@ export class GitlabUrlReader implements UrlReader {
|
||||
)}/repository/archive?sha=${branch}`,
|
||||
{
|
||||
...getGitLabRequestOptions(this.integration.config),
|
||||
...(signal && { signal }),
|
||||
// TODO(freben): The signal cast is there because pre-3.x versions of
|
||||
// node-fetch have a very slightly deviating AbortSignal type signature.
|
||||
// The difference does not affect us in practice however. The cast can
|
||||
// be removed after we support ESM for CLI dependencies and migrate to
|
||||
// version 3 of node-fetch.
|
||||
// https://github.com/backstage/backstage/issues/8242
|
||||
...(signal && { signal: signal as any }),
|
||||
},
|
||||
);
|
||||
if (!archiveGitLabResponse.ok) {
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.10",
|
||||
"@backstage/backend-common": "^0.9.12",
|
||||
"@backstage/config": "^0.1.11",
|
||||
"@backstage/errors": "^0.1.4",
|
||||
"@backstage/types": "^0.1.1",
|
||||
@@ -43,8 +43,8 @@
|
||||
"zod": "^3.9.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-test-utils": "^0.1.9",
|
||||
"@backstage/cli": "^0.9.0",
|
||||
"@backstage/backend-test-utils": "^0.1.10",
|
||||
"@backstage/cli": "^0.10.0",
|
||||
"jest": "^26.0.1",
|
||||
"wait-for-expect": "^3.0.2"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @backstage/backend-test-utils
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-common@0.9.12
|
||||
- @backstage/cli@0.10.0
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-test-utils",
|
||||
"description": "Test helpers library for Backstage backends",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.10",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -30,8 +30,8 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.10",
|
||||
"@backstage/cli": "^0.9.0",
|
||||
"@backstage/backend-common": "^0.9.12",
|
||||
"@backstage/cli": "^0.10.0",
|
||||
"@backstage/config": "^0.1.9",
|
||||
"knex": "^0.95.1",
|
||||
"mysql2": "^2.2.5",
|
||||
@@ -41,7 +41,7 @@
|
||||
"uuid": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.9.0",
|
||||
"@backstage/cli": "^0.10.0",
|
||||
"jest": "^26.0.1"
|
||||
},
|
||||
"files": [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user