Merge branch 'master' into scaffolder/EntityPicker-arbitrary-values
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search': patch
|
||||
---
|
||||
|
||||
Add Optional Props to Override Icon for SidebarSearch and SidebarSearchModal Component
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-github-actions': patch
|
||||
---
|
||||
|
||||
Show empty state only when workflow API call has completed
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/app-defaults': patch
|
||||
'@backstage/core-app-api': patch
|
||||
'@backstage/core-plugin-api': patch
|
||||
---
|
||||
|
||||
Add `FetchApi` and related `fetchApiRef` which implement fetch, with an added Backstage token header when available.
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Fixed bug in backend-common to allow passing of remote option in order to enable passing remote url in --config option. The remote option should be passed along with reloadIntervalSeconds from packages/backend/src/index.ts (Updated the file as well)
|
||||
|
||||
These changes are needed in `packages/backend/src/index.ts` if remote URLs are desired to be passed in --config option and read and watch remote files for config.
|
||||
|
||||
```diff
|
||||
@@ -86,7 +86,11 @@ async function main() {
|
||||
const config = await loadBackendConfig({
|
||||
argv: process.argv,
|
||||
logger,
|
||||
+ remote: {
|
||||
+ reloadIntervalSeconds: 60 * 10 // Check remote config changes every 10 minutes. Change to your desired interval in seconds
|
||||
+ }
|
||||
});
|
||||
+
|
||||
const createEnv = makeCreateEnv(config);
|
||||
|
||||
const healthcheckEnv = useHotMemoize(module, () => createEnv('healthcheck'));
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/config-loader': patch
|
||||
---
|
||||
|
||||
In case remote.reloadIntervalSeconds is passed, it must be a valid positive value
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-user-settings': patch
|
||||
---
|
||||
|
||||
Fix undefined identity bug in UserSettingsProfileCard caused by using deprecated methods of the IdentityApi
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
'@backstage/core-plugin-api': minor
|
||||
---
|
||||
|
||||
**BREAKING CHANGE** The `StorageApi` has received several updates that fills in gaps for some use-cases and makes it easier to avoid mistakes:
|
||||
|
||||
- The `StorageValueChange` type has been renamed to `StorageValueSnapshot`, the `newValue` property has been renamed to `value`, the stored value type has been narrowed to `JsonValue`, and it has received a new `presence` property that is `'unknown'`, `'absent'`, or `'present'`.
|
||||
- The `get` method has been deprecated in favor of a new `snapshot` method, which returns a `StorageValueSnapshot`.
|
||||
- The `observe$` method has had its contract changed. It should now emit values when the `presence` of a key changes, this may for example happen when remotely stored values are requested on page load and the presence switches from `'unknown'` to either `'absent'` or `'present'`.
|
||||
|
||||
The above changes have been made with deprecations in place to maintain much of the backwards compatibility for consumers of the `StorageApi`. The only breaking change is the narrowing of the stored value type, which may in some cases require the addition of an explicit type parameter to the `get` and `observe$` methods.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-config-schema': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Fix a small browser console warning
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
added useOwnedEntities hook to get the list of entities of the logged-in user
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes': minor
|
||||
---
|
||||
|
||||
Includes `KubernetesBackendClient` in the export to allow developers to use it externally.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Added peerPluginDependencies option to experimentalInstallationRecipe for install command to install plugins it depends on.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-tech-radar': minor
|
||||
---
|
||||
|
||||
Add new property to enable open links in a new window/tab
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-org': patch
|
||||
---
|
||||
|
||||
Fixed bug in OwnershipCard component where text wasn't correctly pluralized
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-rails': patch
|
||||
---
|
||||
|
||||
Add new options to rails new (force and skipTests)
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-common': minor
|
||||
---
|
||||
|
||||
Create catalog-common and add catalog permissions.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-bazaar': patch
|
||||
'@backstage/plugin-bazaar-backend': patch
|
||||
---
|
||||
|
||||
made the linkage between a Bazaar project to a catalog Entity optional
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
---
|
||||
|
||||
Updated `WebStorageApi` to reflect the `StorageApi` changes in `@backstage/core-plugin-api`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/test-utils': minor
|
||||
---
|
||||
|
||||
Updated `MockStorageApi` to reflect the `StorageApi` changes in `@backstage/core-plugin-api`.
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Deprecated the `CatalogClientWrapper` class.
|
||||
|
||||
The default implementation of `catalogApiRef` that this plugin exposes, is now powered by the new `fetchApiRef`. The default implementation of _that_ API, in turn, has the ability to inject the user's Backstage token in requests in a similar manner to what the deprecated `CatalogClientWrapper` used to do. The latter has therefore been taken out of the default catalog API implementation.
|
||||
|
||||
If you use a custom `fetchApiRef` implementation that does NOT issue tokens, or use a custom `catalogApiRef` implementation which does NOT use the default `fetchApiRef`, you can still for some time wrap your catalog API in this class to get back the old behavior:
|
||||
|
||||
```ts
|
||||
// Add this to your packages/app/src/plugins.ts if you want to get back the old
|
||||
// catalog client behavior:
|
||||
createApiFactory({
|
||||
api: catalogApiRef,
|
||||
deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef },
|
||||
factory: ({ discoveryApi, identityApi }) =>
|
||||
new CatalogClientWrapper({
|
||||
client: new CatalogClient({ discoveryApi }),
|
||||
identityApi,
|
||||
}),
|
||||
}),
|
||||
```
|
||||
|
||||
But do consider migrating to making use of the `fetchApiRef` as soon as convenient, since the wrapper class will be removed in a future release.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/catalog-client': patch
|
||||
---
|
||||
|
||||
Add the ability to supply a custom `fetchApi`. In the default frontend app setup, this will use the `fetchApiRef` implementation.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/config-loader': minor
|
||||
---
|
||||
|
||||
Removed deprecated option `env` from `LoadConfigOptions` and associated tests
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-newrelic-dashboard': patch
|
||||
---
|
||||
|
||||
Created a New Plugin , which imports dashboard links and snapshots from New Relic
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-home': patch
|
||||
---
|
||||
|
||||
Fix undefined identity bug in `WelcomeTitle` caused by using deprecated methods of the IdentityApi
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/test-utils': minor
|
||||
---
|
||||
|
||||
Removed deprecated `Keyboard` class which has been superseded by `@testing-library/user-event#userEvent`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-rollbar-backend': patch
|
||||
---
|
||||
|
||||
Bump `axios`
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
---
|
||||
|
||||
- Removed deprecated definition `createApp` from `@backstage/core-app-api` which has been replaced by `@backstage/app-defaults#createApp`
|
||||
- Removed deprecated type `BackstagePluginWithAnyOutput`
|
||||
- Removed deprecated constructors for `GithubAuth`, `OAuth2`, and `SamlAuth` as the `create` method should be used instead
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/core-plugin-api': minor
|
||||
---
|
||||
|
||||
- Removed deprecated option `description` from `ApiRefConfig`
|
||||
- Removed descriptions from all plugin API refs
|
||||
- Removed deprecated parameters `path`, `icon`, and `title` in `createRouteRef`
|
||||
- Removed deprecated types `Error` and `ErrorContext` from `ErrorApi`
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
The `index.html` template of the app has been updated to use the new `config` global provided by the Backstage CLI.
|
||||
|
||||
To apply this change to an existing app, make the following changes to `packages/app/public/index.html`:
|
||||
|
||||
```diff
|
||||
- <title><%= app.title %></title>
|
||||
+ <title><%= config.getString('app.title') %></title>
|
||||
```
|
||||
|
||||
```diff
|
||||
- <% if (app.googleAnalyticsTrackingId && typeof app.googleAnalyticsTrackingId === 'string') { %>
|
||||
+ <% if (config.has('app.googleAnalyticsTrackingId')) { %>
|
||||
<script
|
||||
async
|
||||
- src="https://www.googletagmanager.com/gtag/js?id=<%= app.googleAnalyticsTrackingId %>"
|
||||
+ src="https://www.googletagmanager.com/gtag/js?id=<%= config.getString('app.googleAnalyticsTrackingId') %>"
|
||||
></script>
|
||||
```
|
||||
|
||||
```diff
|
||||
- gtag('config', '<%= app.googleAnalyticsTrackingId %>');
|
||||
+ gtag(
|
||||
+ 'config',
|
||||
+ '<%= config.getString("app.googleAnalyticsTrackingId") %>',
|
||||
+ );
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/test-utils': minor
|
||||
---
|
||||
|
||||
Removed deprecated `msw` definition which was replaced by calling `setupRequestMockHandlers` directly
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/config-loader': minor
|
||||
---
|
||||
|
||||
Removed deprecated option `configPaths` as it has been superseded by `configTargets`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Added OwnedEntityPicker field which displays Owned Entities in options
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
The frontend configuration is now available as a `config` global during templating of the `index.html` file. This allows for much more flexibility as the values available during templating is not longer hardcoded to a fixed set of values.
|
||||
|
||||
For example, to access the app title, you would now do the following:
|
||||
|
||||
```html
|
||||
<title><%= config.getString('app.title') %></title>
|
||||
```
|
||||
|
||||
Along with this change, usage of the existing `app.<key>` values has been deprecated and will be removed in a future release. The general pattern for migrating existing usage is to replace `<%= app.<key> %>` with `<%= config.getString('app.<key>') %>`, although in some cases you may need to use for example `config.has('app.<key>')` or `config.getOptionalString('app.<key>')` instead.
|
||||
|
||||
The [`@backstage/create-app` changelog](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md#049) also contains more details how to migrate existing usage.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
Fixed the fallback identity population to correctly generate an entity reference for `userEntityRef` if no token is provided.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/app-defaults': patch
|
||||
'@backstage/core-app-api': minor
|
||||
'@backstage/core-plugin-api': minor
|
||||
---
|
||||
|
||||
- Removed deprecation configuration option `theme` from `AppTheme` of the `AppThemeApi`
|
||||
- Removed reference to `theme` in the `app-defaults` default `AppTheme`
|
||||
- Removed logic in `AppThemeProvider` that creates `ThemeProvider` from `appTheme.theme`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/catalog-client': patch
|
||||
---
|
||||
|
||||
Add support for passing paging parameters to the getEntities call of the catalog client
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/plugin-search-backend': minor
|
||||
---
|
||||
|
||||
Search result location filtering
|
||||
|
||||
This change introduces a filter for search results based on their location protocol. The intention is to filter out unsafe or
|
||||
malicious values before they can be consumed by the frontend. By default locations must be http/https URLs (or paths).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Do not `setState` when unmounted in `OverflowTooltip`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'embedded-techdocs-app': patch
|
||||
---
|
||||
|
||||
The `index.html` template was updated to use the new `config` global.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-backend': patch
|
||||
---
|
||||
|
||||
Fixed a bug preventing cache from being enabled in TechDocs "recommended" deployment mode.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
In @backstage/plugin-scaffolder - When user will have one option available in hostUrl or owner - autoselect and select component should be readonly.
|
||||
|
||||
in @backstage/core-components - Select component has extended API with few more props: native : boolean, disabled: boolean. native - if set to true - Select component will use native browser select picker (not rendered by Material UI lib ).
|
||||
disabled - if set to true - action on component will not be possible.
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-circleci': patch
|
||||
'@backstage/plugin-cloudbuild': patch
|
||||
'@backstage/plugin-github-actions': patch
|
||||
'@backstage/plugin-gitops-profiles': patch
|
||||
'@backstage/plugin-jenkins': patch
|
||||
'@backstage/plugin-lighthouse': patch
|
||||
'@backstage/plugin-org': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-search': patch
|
||||
'@backstage/plugin-sentry': patch
|
||||
'@backstage/plugin-sonarqube': patch
|
||||
---
|
||||
|
||||
Prefer using `Link` from `@backstage/core-components` rather than material-UI.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-jenkins-backend': patch
|
||||
---
|
||||
|
||||
feature: add crumbIssuer option to Jenkins (optional) configuration, improve the UI to show a notification after executing the action re-build
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-jenkins': patch
|
||||
---
|
||||
|
||||
feature: add crumbIssuer option to Jenkins (optional) configuration, improve the UI to show a notification after executing the action re-build
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Add DescriptionField override to support Markdown
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-apache-airflow': minor
|
||||
---
|
||||
|
||||
Introduces a new plugin for the Apache Airflow workflow management platform.
|
||||
This implementation has been tested with the Apache Airflow v2 API,
|
||||
authenticating with basic authentication through the Backstage proxy plugin.
|
||||
|
||||
Supported functionality includes:
|
||||
|
||||
- Information card of version information of the Airflow instance
|
||||
- Information card of instance health for the meta-database and scheduler
|
||||
- Table of DAGs with meta information and status, along with a link to view
|
||||
details in the Airflow UI
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': patch
|
||||
---
|
||||
|
||||
Schema-validate local storage cached session info on load
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-plugin-api': minor
|
||||
---
|
||||
|
||||
Removed deprecated types `ApiRefType` and `ApiRefsToTypes`
|
||||
@@ -42,3 +42,4 @@
|
||||
/.changeset/search-* @backstage/techdocs-core
|
||||
/.changeset/techdocs-* @backstage/techdocs-core
|
||||
/cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core
|
||||
/plugins/apache-airflow @backstage/reviewers @cmpadden
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
catalog:
|
||||
- plugins/catalog/**/*
|
||||
- plugins/catalog-*/**/*
|
||||
- packages/catalog-*/**/*
|
||||
scaffolder:
|
||||
- plugins/scaffolder/**/*
|
||||
- plugins/scaffolder-*/**/*
|
||||
search:
|
||||
- plugins/search/**/*
|
||||
- plugins/search-*/**/*
|
||||
- packages/search-*/**/*
|
||||
docs-like-code:
|
||||
- plugins/techdocs/**/*
|
||||
- plugins/techdocs-*/**/*
|
||||
- packages/techdocs-*/**/*
|
||||
documentation:
|
||||
- docs/**/*
|
||||
microsite:
|
||||
- microsite/**/*
|
||||
auth:
|
||||
- plugins/auth-backend/**/*
|
||||
- packages/core-app-api/src/apis/implementations/auth/**/*
|
||||
- packages/core-app-api/src/lib/Auth*/**/*
|
||||
- packages/core-plugin-api/src/apis/definitions/auth.ts
|
||||
@@ -12,6 +12,7 @@ Atlassian
|
||||
automations
|
||||
autoscaling
|
||||
Autoscaling
|
||||
autoselect
|
||||
Avro
|
||||
backrub
|
||||
Bigtable
|
||||
@@ -53,6 +54,7 @@ configs
|
||||
const
|
||||
cookiecutter
|
||||
cron
|
||||
cronjobs
|
||||
css
|
||||
Datadog
|
||||
dataflow
|
||||
@@ -90,10 +92,12 @@ Figma
|
||||
firehydrant
|
||||
FireHydrant
|
||||
Firekube
|
||||
Firestore
|
||||
Fiverr
|
||||
gitbeaker
|
||||
GitHub
|
||||
GitLab
|
||||
Gource
|
||||
Grafana
|
||||
graphql
|
||||
GraphQL
|
||||
@@ -187,6 +191,7 @@ OAuth
|
||||
octokit
|
||||
oidc
|
||||
Okta
|
||||
Oldsberg
|
||||
onboarding
|
||||
Onboarding
|
||||
OpenShift
|
||||
@@ -194,6 +199,8 @@ orgs
|
||||
pagerduty
|
||||
pageview
|
||||
parallelization
|
||||
Patrik
|
||||
Peloton
|
||||
plantuml
|
||||
Platformize
|
||||
Podman
|
||||
@@ -293,6 +300,7 @@ truthy
|
||||
typeahead
|
||||
ui
|
||||
unbreak
|
||||
Unconference
|
||||
unmanaged
|
||||
unregister
|
||||
unregistration
|
||||
@@ -304,6 +312,7 @@ utils
|
||||
validator
|
||||
validators
|
||||
varchar
|
||||
Wayfair
|
||||
Weaveworks
|
||||
Webpack
|
||||
winston
|
||||
@@ -316,4 +325,3 @@ Zalando
|
||||
Zhou
|
||||
zoomable
|
||||
zsh
|
||||
Firestore
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
name: Create Changeset PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
- name: Create Release Pull Request
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Fossa
|
||||
run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
name: 'Pull Request Labeler'
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v3
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
sync-labels: true
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
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
|
||||
days-before-pr-close: 5
|
||||
exempt-pr-labels: reviewer-approved,awaiting-review
|
||||
stale-pr-label: stale
|
||||
operations-per-run: 100
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
# [Backstage](https://backstage.io)
|
||||
|
||||
> 🎄 The maintainers will be taking a break over the holidays from week beginning 20th Dec. The Repository and Discord may be quieter than usual. We will be back next year, rested and restored, on Jan. 3. 🎄
|
||||
|
||||
> 🎅 Happy holidays and a Happy New Year to all, and especially those that have made this year special for Backstage! 🎅
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://www.cncf.io/projects)
|
||||
[](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22)
|
||||
|
||||
@@ -74,6 +74,11 @@ proxy:
|
||||
headers:
|
||||
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
|
||||
|
||||
'/newrelic/api':
|
||||
target: https://api.newrelic.com
|
||||
headers:
|
||||
X-Api-Key: ${NEW_RELIC_USER_KEY}
|
||||
|
||||
'/pagerduty':
|
||||
target: https://api.pagerduty.com
|
||||
headers:
|
||||
|
||||
@@ -61,3 +61,125 @@ breaking change to make `theme` optional. This means that if you currently
|
||||
construct the themes that you pass on to `createApp` using `AppTheme` as an
|
||||
intermediate type, you will need to work around this in some way, for example by
|
||||
passing the themes to `createApp` more directly.
|
||||
|
||||
### Generic Auth API Refs
|
||||
|
||||
`Released 2021-12-16 in @backstage/core-plugin-api v0.3.1`
|
||||
|
||||
There are four auth Utility API references in `@backstage/core-plugin-api` that
|
||||
were too generic to be useful. The APIs in question are `auth0AuthApiRef`,
|
||||
`oauth2ApiRef`, `oidcAuthApiRef`, and `samlAuthApiRef`. The issue with these
|
||||
APIs was that they had no actual contract of what the backing auth provider was.
|
||||
This made it more or less impossible to use these providers in open source
|
||||
plugins in any meaningful way. We also did not want to keep these Utility API
|
||||
references around just as helpers either, instead opting to remove them and let
|
||||
integrators define their own APIs that are more specific to their auth provider.
|
||||
This is also falls in line with a long-term goal to unify all auth providers to
|
||||
not have separate frontend implementations.
|
||||
|
||||
If you're currently using one of these API references for either Sign-In or
|
||||
access delegation within an app, there are a couple of steps you need to take to
|
||||
migrate to your own custom API.
|
||||
|
||||
First, you'll need to define a new Utility API reference. If you're only using
|
||||
the API for sign-in, you can put the definition in `packages/app/src/apis.ts`.
|
||||
However, if you need to access your auth API inside plugins you you'll need to
|
||||
export it from a common package. If you don't already have one we recommended
|
||||
creating `@internal/apis` and from there export the API reference.
|
||||
|
||||
```ts
|
||||
// `ProfileInfoApi & BackstageIdentityApi & SessionApi` are required for sign-in
|
||||
// Include `OAuthApi & OpenIdConnectApi` only if applicable
|
||||
export const acmeAuthApiRef: ApiRef<
|
||||
OAuthApi &
|
||||
OpenIdConnectApi &
|
||||
ProfileInfoApi &
|
||||
BackstageIdentityApi &
|
||||
SessionApi
|
||||
> = createApiRef({
|
||||
id: 'internal.auth.acme',
|
||||
});
|
||||
```
|
||||
|
||||
Next you'll want to wire up the API inside `packages/app/src/apis.ts`, which
|
||||
varies depending on which API you're replacing. If you for example are replacing
|
||||
the `oauth2ApiRef`, the factory might look like this:
|
||||
|
||||
```ts
|
||||
// oauth2
|
||||
createApiFactory({
|
||||
api: acmeAuthApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
oauthRequestApi: oauthRequestApiRef,
|
||||
configApi: configApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
|
||||
OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
Provider specific factory implementations, copy the code you need into the
|
||||
factory method depending on which apiRef you previously used.
|
||||
|
||||
```ts
|
||||
// samlAuthApiRef
|
||||
SamlAuth.create({
|
||||
discoveryApi,
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
});
|
||||
|
||||
// oidcAuthApiRef
|
||||
OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
provider: {
|
||||
id: 'oidc',
|
||||
title: 'Your Identity Provider',
|
||||
icon: () => null,
|
||||
},
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
});
|
||||
|
||||
// auth0AuthApiRef
|
||||
OAuth2.create({
|
||||
discoveryApi,
|
||||
oauthRequestApi,
|
||||
provider: {
|
||||
id: 'auth0',
|
||||
title: 'Auth0',
|
||||
icon: () => null,
|
||||
},
|
||||
defaultScopes: ['openid', 'email', 'profile'],
|
||||
environment: configApi.getOptionalString('auth.environment'),
|
||||
});
|
||||
```
|
||||
|
||||
Finally, for the provider to show up in your settings menu, you also need to
|
||||
update the settings route in `packages/app/src/App.tsx` to pass the
|
||||
`acmeAuthApiRef` to the `UserSettingsPage`. This replaces all existing provider
|
||||
items, so you might want to add back any of the default ones that you are using
|
||||
from the
|
||||
[DefaultProviderSettings](https://github.com/backstage/backstage/blob/a3ec122170e0205fd3f9c307b98b1c5e4f55bf5f/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx#L35).
|
||||
|
||||
```tsx
|
||||
<Route
|
||||
path="/settings"
|
||||
element={
|
||||
<UserSettingsPage
|
||||
providerSettings={
|
||||
<ProviderSettingsItem
|
||||
title="ACME"
|
||||
description="Provides sign-in via ACME"
|
||||
apiRef={acmeAuthApiRef}
|
||||
icon={Star}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
@@ -128,8 +128,8 @@ the core APIs. The core APIs are the ones exported by
|
||||
[configApiRef](../reference/core-plugin-api.configapiref.md).
|
||||
|
||||
The core APIs are loaded for any app created with
|
||||
[createApp](../reference/core-app-api.createapp.md) from
|
||||
[@backstage/core-plugin-api](../reference/core-plugin-api.md), which means that
|
||||
[createApp](../reference/app-defaults.createapp.md) from
|
||||
[@backstage/core-plugin-api](../reference/app-defaults.md), which means that
|
||||
there is no step that needs to be taken to include these APIs in an app.
|
||||
|
||||
### Plugin APIs
|
||||
@@ -168,7 +168,7 @@ Lastly, the app itself is the final point where APIs can be added, and what has
|
||||
the final say in what APIs will be loaded at runtime. The app may override the
|
||||
factories for any of the core or plugin APIs, with the exception of the config,
|
||||
app theme, and identity APIs. These are static APIs that are tied into the
|
||||
[createApp](../reference/core-app-api.createapp.md) implementation, and
|
||||
[createApp](../reference/app-defaults.createapp.md) implementation, and
|
||||
therefore not possible to override.
|
||||
|
||||
Overriding APIs is useful for apps that want to switch out behavior to tailor it
|
||||
@@ -313,7 +313,7 @@ The common development environment for plugins is included in
|
||||
[createDevApp](../reference/dev-utils.createdevapp.md) function creates an
|
||||
application with implementations for all core APIs already present. Contrary to
|
||||
the method for wiring up Utility API implementations in an app created with
|
||||
[createApp](../reference/core-app-api.createapp.md),
|
||||
[createApp](../reference/app-defaults.createapp.md),
|
||||
[createDevApp](../reference/dev-utils.createdevapp.md) uses automatic dependency
|
||||
injection. This is to make it possible to replace any API implementation, and
|
||||
having that be reflected in dependents of that API.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr000
|
||||
title: ADR000: [TITLE]
|
||||
title: 'ADR000: [TITLE]'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) for [TITLE] [DESCRIPTION]
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr001
|
||||
title: ADR001: Architecture Decision Record (ADR) log
|
||||
title: 'ADR001: Architecture Decision Record (ADR) log'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) logs as a reference point for the team
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr002
|
||||
title: ADR002: Default Software Catalog File Format
|
||||
title: 'ADR002: Default Software Catalog File Format'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Default Software Catalog File Format
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr003
|
||||
title: ADR003: Avoid Default Exports and Prefer Named Exports
|
||||
title: 'ADR003: Avoid Default Exports and Prefer Named Exports'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Avoid Default Exports and Prefer Named Exports
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr004
|
||||
title: ADR004: Module Export Structure
|
||||
title: 'ADR004: Module Export Structure'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Module Export Structure
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr005
|
||||
title: ADR005: Catalog Core Entities
|
||||
title: 'ADR005: Catalog Core Entities'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Catalog Core Entities
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr006
|
||||
title: ADR006: Avoid React.FC and React.SFC
|
||||
title: 'ADR006: Avoid React.FC and React.SFC'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Avoid React.FC and React.SFC
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr007
|
||||
title: ADR007: Use MSW to mock http requests
|
||||
title: 'ADR007: Use MSW to mock http requests'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Use MSW to mock http requests
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr008
|
||||
title: ADR008: Default Catalog File Name
|
||||
title: 'ADR008: Default Catalog File Name'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Default Catalog File Name
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr009
|
||||
title: ADR009: Entity References
|
||||
title: 'ADR009: Entity References'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) log on Entity References
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr010
|
||||
title: ADR010: Use the Luxon Date Library
|
||||
title: 'ADR010: Use the Luxon Date Library'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) for Luxon Date Library
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr011
|
||||
title: ADR011: Plugin Package Structure
|
||||
title: 'ADR011: Plugin Package Structure'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) for Plugin Package Structure
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
id: adrs-adr012
|
||||
title: ADR012: Use Luxon.toLocaleString and date/time presets
|
||||
title: 'ADR012: Use Luxon.toLocaleString and date/time presets'
|
||||
# prettier-ignore
|
||||
description: Architecture Decision Record (ADR) for using Luxon's toLocaleString method and date/time presets for displaying dates and times
|
||||
---
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
id: adrs-overview
|
||||
title: Architecture Decision Records (ADR)
|
||||
sidebar_label: Overview
|
||||
# prettier-ignore
|
||||
description: Overview of Architecture Decision Records (ADR)
|
||||
---
|
||||
|
||||
|
||||
@@ -48,6 +48,6 @@ The Microsoft provider is a structure with three configuration keys:
|
||||
|
||||
## Adding the provider to the Backstage frontend
|
||||
|
||||
To add the provider to the frontend, add the `microsoftAuthApi` reference and
|
||||
To add the provider to the frontend, add the `microsoftAuthApiRef` reference and
|
||||
`SignInPage` component as shown in
|
||||
[Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page).
|
||||
|
||||
@@ -67,7 +67,7 @@ production build.
|
||||
|
||||
## Configuration Files
|
||||
|
||||
It is possible to have multiple configuration files (bundled and/or remote),
|
||||
It is possible to have multiple configuration files (bundled and/or remote\*),
|
||||
both to support different environments, but also to define configuration that is
|
||||
local to specific packages. The configuration files to load are selected using a
|
||||
`--config <local-path|url>` flag, and it is possible to load any number of
|
||||
@@ -77,6 +77,9 @@ root when running the backend, you would use `--config ../../my-config.yaml`,
|
||||
and for config file on a config server you would use
|
||||
`--config https://some.domain.io/app-config.yaml`
|
||||
|
||||
**Note**: In case URLs are passed, it is also needed to set the remote option in
|
||||
the loadBackendConfig call.
|
||||
|
||||
If no `config` flags are specified, the default behavior is to load
|
||||
`app-config.yaml` and, if it exists, `app-config.local.yaml` from the repo root.
|
||||
In the provided project setup, `app-config.local.yaml` is `.gitignore`'d, making
|
||||
|
||||
@@ -264,6 +264,12 @@ following objects:
|
||||
- horizontalpodautoscalers
|
||||
- ingresses
|
||||
|
||||
The following RBAC permissions are required on the batch API group for the
|
||||
following objects:
|
||||
|
||||
- jobs
|
||||
- cronjobs
|
||||
|
||||
## Surfacing your Kubernetes components as part of an entity
|
||||
|
||||
There are two ways to surface your Kubernetes components as part of an entity.
|
||||
|
||||
@@ -90,6 +90,18 @@ within your instance. The configuration options are documented in the
|
||||
The underlying functionality is using official ElasticSearch client version 7.x,
|
||||
meaning that ElasticSearch version 7 is the only one confirmed to be supported.
|
||||
|
||||
Should you need to create your own bespoke search experiences that require more
|
||||
than just a query translator (such as faceted search or Relay pagination), you
|
||||
can access the configuration of the search engine in order to create new elastic
|
||||
search clients. The version of the client need not be the same as one used
|
||||
internally by the elastic search engine plugin. For example:
|
||||
|
||||
```typescript
|
||||
import { Client } from '@elastic/elastic-search';
|
||||
|
||||
const client = searchEngine.newClient(options => new Client(options));
|
||||
```
|
||||
|
||||
## Example configurations
|
||||
|
||||
### AWS
|
||||
|
||||
@@ -26,7 +26,7 @@ You can create your own Field Extension by using the
|
||||
`API` like below:
|
||||
|
||||
```tsx
|
||||
//packages/app/scaffolder/MyCustomExtension/MyCustomExtension.tsx
|
||||
//packages/app/src/scaffolder/MyCustomExtension/MyCustomExtension.tsx
|
||||
import React from 'react';
|
||||
import { FieldProps, FieldValidation } from '@rjsf/core';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
@@ -68,7 +68,7 @@ export const myCustomValidation = (
|
||||
```
|
||||
|
||||
```tsx
|
||||
// packages/app/scaffolder/MyCustomExtension/extensions.ts
|
||||
// packages/app/src/scaffolder/MyCustomExtension/extensions.ts
|
||||
|
||||
/*
|
||||
This is where the magic happens and creates the custom field extension.
|
||||
@@ -94,7 +94,7 @@ export const MyCustomFieldExtension = plugin.provide(
|
||||
```
|
||||
|
||||
```tsx
|
||||
// packages/app/scaffolder/MyCustomExtension/index.ts
|
||||
// packages/app/src/scaffolder/MyCustomExtension/index.ts
|
||||
|
||||
export { MyCustomFieldExtension } from './extension';
|
||||
```
|
||||
@@ -102,7 +102,7 @@ export { MyCustomFieldExtension } from './extension';
|
||||
Once all these files are in place, you then need to provide your custom
|
||||
extension to the `scaffolder` plugin.
|
||||
|
||||
You do this in `packages/app/App.tsx`. You need to provide the
|
||||
You do this in `packages/app/src/App.tsx`. You need to provide the
|
||||
`customFieldExtensions` as children to the `ScaffolderPage`.
|
||||
|
||||
```tsx
|
||||
@@ -118,7 +118,7 @@ const routes = (
|
||||
Should look something like this instead:
|
||||
|
||||
```tsx
|
||||
import { MyCustomFieldExtension } from './scafffolder/MyCustomExtension';
|
||||
import { MyCustomFieldExtension } from './scaffolder/MyCustomExtension';
|
||||
const routes = (
|
||||
<FlatRoutes>
|
||||
...
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# TechDocs CLI
|
||||
---
|
||||
id: cli
|
||||
title: TechDocs CLI
|
||||
# prettier-ignore
|
||||
description: TechDocs CLI - a utility command line interface for managing TechDocs sites in Backstage.
|
||||
---
|
||||
|
||||
Utility command line interface for managing TechDocs sites in
|
||||
[Backstage](https://github.com/backstage/backstage).
|
||||
|
||||
@@ -54,7 +54,7 @@ For example, adding the theme that we created in the previous section can be
|
||||
done like this:
|
||||
|
||||
```ts
|
||||
import { createApp } from '@backstage/core-app-api';
|
||||
import { createApp } from '@backstage/app-defaults';
|
||||
|
||||
const app = createApp({
|
||||
apis: ...,
|
||||
|
||||
@@ -368,7 +368,7 @@ The following is an example of creation and usage of a parameterized route:
|
||||
```tsx
|
||||
// Creation of a parameterized route
|
||||
const myRouteRef = createRouteRef({
|
||||
title: 'My Named Route',
|
||||
id: 'myroute',
|
||||
params: ['name']
|
||||
})
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ that implements the `OAuthApi` type, it's now working in the frontend too.
|
||||
```ts
|
||||
const spotifyAuthApiRef = createApiRef<OAuthApi>({
|
||||
id: 'core.auth.spotify',
|
||||
description: 'Provides authentication towards Spotify APIs',
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -99,7 +99,6 @@ export interface MyAwesomeApi {
|
||||
|
||||
export const myAwesomeApiRef = createApiRef<MyAwesomeApi>({
|
||||
id: 'plugin.my-awesome-api.service',
|
||||
description: 'Example API definition',
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
---
|
||||
title: Backstage Wrapped 2021
|
||||
author: Lee Mills, Spotify
|
||||
authorURL: https://github.com/leemills83
|
||||
authorImageURL: https://avatars1.githubusercontent.com/u/1236238?s=460&v=4
|
||||
---
|
||||
|
||||

|
||||
|
||||
What a year 2021 has been for the Backstage project and community. As the year comes to a close, we can look back at some of the happenings, the successes, and welcome all the newcomers to our growing community.
|
||||
|
||||
In a year that has had its fair share of ups and downs, this community has been something that has brought me so much in the support you provide each other, your eagerness, passion, and willingness to share. Thank you to all of you for creating such a great community, and welcome to everyone joining us. I can’t wait to meet you all and see what great things we can create together in the new year.
|
||||
|
||||
In 2021 we’ve seen the project and community grow in every dimension, reaching over 75 public adopters, over 500 contributors from around the world all bringing new ideas and perspectives. We’ve had so many of you sharing and demoing your hard work in our monthly community sessions, added new plugins, built new features and really started to see Backstage have an impact for engineering teams across so many of our users.
|
||||
|
||||
Now let’s hear from the maintainers and look at the stats!
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
## The community grew…and grew
|
||||
|
||||
This year, Netflix, [Expedia][metrics], Wayfair, Peloton, [Box][10], [DAZN][dazn], TELUS, and Unity all officially joined the community — along with more than 50 other public [adopters][md]. Contributors grew by leaps and bounds, too.
|
||||
|
||||
Patrik Oldsberg ([@Rugvip][rugvip]):
|
||||
|
||||
> It’s been awesome to see the engagement by the community grow even more in 2021, especially the way people within the community support each other. Thanks to our growing number of stable, experienced, and knowledgeable contributors it’s now possible to get help in places like Discord anytime, day or night.
|
||||
|
||||
### More adopters, more contributors
|
||||
|
||||

|
||||
|
||||
In January, Backstage had 17 public adopters. By September, [we had 50][50]. And the curve only got steeper from there.
|
||||
|
||||
- **75+ public adopters**
|
||||
- **500+ contributors**
|
||||
- **4,000+ Discord members**
|
||||
- **9,000+ PRs & issues**
|
||||
|
||||
### A very busy repo
|
||||
|
||||
Along with the growth in contributors, PRs, and issues, our active, thriving community has crossed (or is just about to cross) other big milestones on GitHub, too.
|
||||
|
||||
- **Nearly 2,000 forks**
|
||||
- **20,000+ commits**
|
||||
- **14,000+ GitHub stars**
|
||||
|
||||
### Where in the world is the Backstage community?
|
||||
|
||||
Watch the visualization below to see where in the world all those contributions came from this past year.
|
||||
|
||||
<iframe width="780" height="440" src="https://www.youtube.com/embed/O1xtDv_XDt4" frameBorder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
|
||||
|
||||
### What does 9,000 contributions look like?
|
||||
|
||||
<iframe width="780" height="440" src="https://www.youtube.com/embed/bCqhoK7it2g" frameBorder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
|
||||
|
||||
Can you spot your name in the video above?
|
||||
|
||||
Picking up from the end of 2020, the video shows every single contribution to the Backstage source code over this past year. The visualization was built using [Gource.io][gource]:
|
||||
|
||||
> Software projects are displayed by Gource as an animated tree with the root directory of the project at its centre. Directories appear as branches with files as leaves. Developers can be seen working on the tree at the times they contributed to the project.
|
||||
|
||||
And if your name isn’t in there, it’s never too late to get started [contributing][contributing] — so that you too can become a bright, sparkling, laser-beam-shooting spider-node thing in 2022!
|
||||
|
||||
## Other 2021 milestones
|
||||
|
||||
As the community grew, so did the product — with the addition of new features as well as important performance and stability improvements to the core.
|
||||
|
||||
Ben Lambert ([@benjdlambert][blam]):
|
||||
|
||||
> We’ve had a lot of priorities this year. Our first priority was rebuilding the catalog to make it more efficient. Then, toward the later part of the year, we’ve been stabilizing the core with deprecations and API changes ahead of our 1.0 release of the Core Framework next year.
|
||||
>
|
||||
> It’s been a super productive year for us all as Core Maintainers, and the product has come on leaps and bounds with the help of everyone involved in the project!
|
||||
|
||||
### New features
|
||||
|
||||
These new features were built with the community, and made with customization and extensibility in mind.
|
||||
|
||||
- **Kubernetes Service Monitoring ([RFC][k8s])**
|
||||
- **Search Platform ([Alpha][search])**
|
||||
- **Composable Homepage ([README][home])**
|
||||
- **Authorization Framework ([RFC][auth])**
|
||||
|
||||
### Major stability updates
|
||||
|
||||
As we get the ball rolling for [CNCF Incubation][cncf], we’ve been busy updating, refining, documenting, deprecating, and stabilizing the core.
|
||||
|
||||
- **Software Templates ([Beta][scaffolder])**
|
||||
- **TechDocs ([Beta][techdocs])**
|
||||
- **API Reference ([docs][api])**
|
||||
|
||||
### 50+ open source plugins
|
||||
|
||||
We reached [50+ plugins][plugins] built by the community this year, including official plugins (**Snyk**, **FireHydrant**), highly requested plugins (**PagerDuty**, **Prometheus**), and plugins based on new ideas and functionality (**XCMetrics**, **[Tech Insights][techrfc]**) — all tailor-made for Backstage.
|
||||
|
||||
### In the spotlight
|
||||
|
||||
This year Backstage was center stage at both community-organized events and at major conferences.
|
||||
|
||||
- **New (and [expanded][09]) Community Sessions**
|
||||
- **Backstage Users Unconference + [Open Mic][openmic]**
|
||||
- **KubeCon + CloudNativeCon [Europe][europe] & [North America][na]**
|
||||
- **GitHub Universe 2021 [Keynote][day2]**
|
||||
|
||||
Find more talks, podcasts, blog posts, and Backstage in the news [here][news].
|
||||
|
||||
## Goodbye, 2021. Hello, 2022!
|
||||
|
||||
Lastly, thanks to everyone in the global Backstage community who contributed to the open source project in 2021.
|
||||
|
||||
This was the first year Spotify hosted [Backstage Community Sessions][meetups], and it’s been a great source of inspiration, motivation, and joy getting to know all the people behind the contributions. We look forward to seeing all your faces again in 2022 — and hopefully many new ones as well.
|
||||
|
||||
Until then, [grab this Backstage Zoom background][zoom] to use at the next Community Session.
|
||||
|
||||

|
||||
|
||||
See you then! Happy holidays from everyone on the Backstage team at Spotify!
|
||||
|
||||
[metrics]: https://backstage.spotify.com/blog/measuring-backstage-proof-of-value-at-expedia/
|
||||
[10]: https://backstage.spotify.com/blog/community-session/10-box-and-spotify-paid-plugins/
|
||||
[dazn]: https://backstage.spotify.com/blog/adopter-spotlight/dazn/
|
||||
[md]: https://github.com/backstage/backstage/blob/master/ADOPTERS.md
|
||||
[rugvip]: https://github.com/Rugvip
|
||||
[50]: https://backstage.io/blog/2021/09/30/50-public-adopters
|
||||
[gource]: https://gource.io
|
||||
[contributing]: https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md
|
||||
[blam]: https://github.com/benjdlambert
|
||||
[k8s]: https://github.com/backstage/backstage/issues/2857
|
||||
[search]: https://backstage.io/blog/2021/06/24/announcing-backstage-search-platform
|
||||
[home]: https://github.com/backstage/backstage/blob/master/plugins/home/README.md
|
||||
[auth]: https://backstage.spotify.com/blog/authorization-framework-rfc/
|
||||
[scaffolder]: https://backstage.io/blog/2021/07/26/software-templates-are-now-in-beta
|
||||
[techdocs]: https://backstage.io/blog/2021/09/16/the-techdocs-beta-has-landed
|
||||
[api]: https://backstage.io/docs/reference/
|
||||
[cncf]: https://github.com/cncf/toc/pull/717
|
||||
[plugins]: https://backstage.io/plugins
|
||||
[techrfc]: https://github.com/backstage/backstage/issues/7576
|
||||
[09]: https://backstage.spotify.com/blog/community-session/09-prometheus-homepage-templates/
|
||||
[openmic]: https://backstage-openmic.com
|
||||
[europe]: https://www.youtube.com/watch?v=aIURaocR5D8
|
||||
[na]: https://backstage.spotify.com/blog/kubecon-na-2021/
|
||||
[day2]: https://www.youtube.com/watch?v=7yQJlYvpoYs&t=269s
|
||||
[news]: https://github.com/backstage/community#newsletters
|
||||
[meetups]: https://github.com/backstage/community#meetups
|
||||
[zoom]: https://drive.google.com/file/d/14wOPXEBZ5Qmi29ms4Sqp1m56dM0AIHbB/view?usp=sharing
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 226 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 313 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
+5
-4
@@ -55,9 +55,9 @@
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@microsoft/api-documenter": "^7.13.68",
|
||||
"@microsoft/api-extractor": "^7.18.7",
|
||||
"@microsoft/api-extractor-model": "^7.13.5",
|
||||
"@microsoft/api-documenter": "^7.13.77",
|
||||
"@microsoft/api-extractor": "^7.19.2",
|
||||
"@microsoft/api-extractor-model": "^7.15.1",
|
||||
"@microsoft/tsdoc": "^0.13.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -78,11 +78,12 @@
|
||||
"prettier": "^2.2.1",
|
||||
"shx": "^0.3.2",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "~4.3.5",
|
||||
"yarn-lock-check": "^1.0.5"
|
||||
},
|
||||
"prettier": "@spotify/prettier-config",
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"*.{js,jsx,ts,tsx,mjs,cjs}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
|
||||
@@ -34,6 +34,8 @@ import {
|
||||
OneLoginAuth,
|
||||
UnhandledErrorForwarder,
|
||||
AtlassianAuth,
|
||||
createFetchApi,
|
||||
FetchMiddlewares,
|
||||
} from '@backstage/core-app-api';
|
||||
|
||||
import {
|
||||
@@ -42,6 +44,8 @@ import {
|
||||
analyticsApiRef,
|
||||
errorApiRef,
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
identityApiRef,
|
||||
oauthRequestApiRef,
|
||||
googleAuthApiRef,
|
||||
githubAuthApiRef,
|
||||
@@ -92,6 +96,27 @@ export const apis = [
|
||||
deps: { errorApi: errorApiRef },
|
||||
factory: ({ errorApi }) => WebStorage.create({ errorApi }),
|
||||
}),
|
||||
createApiFactory({
|
||||
api: fetchApiRef,
|
||||
deps: {
|
||||
configApi: configApiRef,
|
||||
identityApi: identityApiRef,
|
||||
discoveryApi: discoveryApiRef,
|
||||
},
|
||||
factory: ({ configApi, identityApi, discoveryApi }) => {
|
||||
return createFetchApi({
|
||||
middleware: [
|
||||
FetchMiddlewares.resolvePluginProtocol({
|
||||
discoveryApi,
|
||||
}),
|
||||
FetchMiddlewares.injectIdentityAuth({
|
||||
identityApi,
|
||||
config: configApi,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
}),
|
||||
createApiFactory({
|
||||
api: oauthRequestApiRef,
|
||||
deps: {},
|
||||
|
||||
@@ -73,7 +73,7 @@ const DefaultErrorBoundaryFallback = ({
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a set of default components to pass along to {@link @backstage/core-app-api#createApp}.
|
||||
* Creates a set of default components to pass along to {@link @backstage/core-app-api#createSpecializedApp}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,6 @@ export const themes: AppTheme[] = [
|
||||
title: 'Light Theme',
|
||||
variant: 'light',
|
||||
icon: <LightIcon />,
|
||||
theme: lightTheme,
|
||||
Provider: ({ children }) => (
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<CssBaseline>{children}</CssBaseline>
|
||||
@@ -40,7 +39,6 @@ export const themes: AppTheme[] = [
|
||||
title: 'Dark Theme',
|
||||
variant: 'dark',
|
||||
icon: <DarkIcon />,
|
||||
theme: darkTheme,
|
||||
Provider: ({ children }) => (
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<CssBaseline>{children}</CssBaseline>
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.57
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-github-actions@0.4.27
|
||||
- @backstage/core-app-api@0.2.1
|
||||
- @backstage/plugin-kubernetes@0.5.1
|
||||
- @backstage/core-plugin-api@0.3.1
|
||||
- @backstage/core-components@0.8.1
|
||||
- @backstage/plugin-org@0.3.31
|
||||
- @backstage/plugin-azure-devops@0.1.7
|
||||
- @backstage/cli@0.10.2
|
||||
- @backstage/catalog-model@0.9.8
|
||||
- @backstage/plugin-techdocs@0.12.10
|
||||
- @backstage/plugin-catalog-react@0.6.7
|
||||
- @backstage/plugin-apache-airflow@0.1.0
|
||||
|
||||
## 0.2.56
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+14
-13
@@ -1,39 +1,40 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.56",
|
||||
"version": "0.2.57",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/app-defaults": "^0.1.2",
|
||||
"@backstage/catalog-model": "^0.9.7",
|
||||
"@backstage/cli": "^0.10.1",
|
||||
"@backstage/core-app-api": "^0.2.0",
|
||||
"@backstage/core-components": "^0.8.0",
|
||||
"@backstage/core-plugin-api": "^0.3.0",
|
||||
"@backstage/catalog-model": "^0.9.8",
|
||||
"@backstage/cli": "^0.10.2",
|
||||
"@backstage/core-app-api": "^0.2.1",
|
||||
"@backstage/core-components": "^0.8.1",
|
||||
"@backstage/core-plugin-api": "^0.3.1",
|
||||
"@backstage/integration-react": "^0.1.15",
|
||||
"@backstage/plugin-api-docs": "^0.6.18",
|
||||
"@backstage/plugin-azure-devops": "^0.1.6",
|
||||
"@backstage/plugin-apache-airflow": "^0.0.0",
|
||||
"@backstage/plugin-azure-devops": "^0.1.7",
|
||||
"@backstage/plugin-apache-airflow": "^0.1.0",
|
||||
"@backstage/plugin-badges": "^0.2.16",
|
||||
"@backstage/plugin-catalog": "^0.7.4",
|
||||
"@backstage/plugin-catalog-graph": "^0.2.3",
|
||||
"@backstage/plugin-catalog-import": "^0.7.5",
|
||||
"@backstage/plugin-catalog-react": "^0.6.5",
|
||||
"@backstage/plugin-catalog-react": "^0.6.7",
|
||||
"@backstage/plugin-circleci": "^0.2.31",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.29",
|
||||
"@backstage/plugin-code-coverage": "^0.1.19",
|
||||
"@backstage/plugin-cost-insights": "^0.11.13",
|
||||
"@backstage/plugin-explore": "^0.3.22",
|
||||
"@backstage/plugin-gcp-projects": "^0.3.10",
|
||||
"@backstage/plugin-github-actions": "^0.4.26",
|
||||
"@backstage/plugin-github-actions": "^0.4.27",
|
||||
"@backstage/plugin-graphiql": "^0.2.24",
|
||||
"@backstage/plugin-home": "^0.4.7",
|
||||
"@backstage/plugin-jenkins": "^0.5.14",
|
||||
"@backstage/plugin-kafka": "^0.2.22",
|
||||
"@backstage/plugin-kubernetes": "^0.5.0",
|
||||
"@backstage/plugin-kubernetes": "^0.5.1",
|
||||
"@backstage/plugin-lighthouse": "^0.2.31",
|
||||
"@backstage/plugin-newrelic": "^0.3.10",
|
||||
"@backstage/plugin-org": "^0.3.30",
|
||||
"@backstage/plugin-newrelic-dashboard": "^0.1.0",
|
||||
"@backstage/plugin-org": "^0.3.31",
|
||||
"@backstage/plugin-pagerduty": "0.3.19",
|
||||
"@backstage/plugin-rollbar": "^0.3.20",
|
||||
"@backstage/plugin-scaffolder": "^0.11.14",
|
||||
@@ -41,7 +42,7 @@
|
||||
"@backstage/plugin-sentry": "^0.3.30",
|
||||
"@backstage/plugin-shortcuts": "^0.1.15",
|
||||
"@backstage/plugin-tech-radar": "^0.4.13",
|
||||
"@backstage/plugin-techdocs": "^0.12.9",
|
||||
"@backstage/plugin-techdocs": "^0.12.10",
|
||||
"@backstage/plugin-todo": "^0.1.16",
|
||||
"@backstage/plugin-user-settings": "^0.3.13",
|
||||
"@backstage/search-common": "^0.2.0",
|
||||
|
||||
@@ -47,13 +47,12 @@
|
||||
min-height: 100%;
|
||||
}
|
||||
</style>
|
||||
<title><%= app.title %></title>
|
||||
<title><%= config.getString('app.title') %></title>
|
||||
|
||||
<% if (app.googleAnalyticsTrackingId && typeof
|
||||
app.googleAnalyticsTrackingId==='string' ) { %>
|
||||
<% if (config.has('app.googleAnalyticsTrackingId')) { %>
|
||||
<script
|
||||
async
|
||||
src="https://www.googletagmanager.com/gtag/js?id=<%= app.googleAnalyticsTrackingId %>"
|
||||
src="https://www.googletagmanager.com/gtag/js?id=<%= config.getString('app.googleAnalyticsTrackingId') %>"
|
||||
></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
@@ -62,10 +61,12 @@
|
||||
}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', '<%= app.googleAnalyticsTrackingId %>');
|
||||
gtag(
|
||||
'config',
|
||||
'<%= config.getString("app.googleAnalyticsTrackingId") %>',
|
||||
);
|
||||
</script>
|
||||
<% } %> <% if (app.datadogRum.clientToken && app.datadogRum.applicationId )
|
||||
{ %>
|
||||
<% } %> <% if (config.has('app.datadogRum')) { %>
|
||||
<script>
|
||||
(function (h, o, u, n, d) {
|
||||
h = h[d] = h[d] || {
|
||||
@@ -88,11 +89,12 @@
|
||||
);
|
||||
DD_RUM.onReady(function () {
|
||||
DD_RUM.init({
|
||||
clientToken: '<%= app.datadogRum.clientToken %>',
|
||||
applicationId: '<%= app.datadogRum.applicationId %>',
|
||||
site: '<%= app.datadogRum.site %>' || 'datadoghq.com',
|
||||
clientToken: '<%= config.getString("app.datadogRum.clientToken") %>',
|
||||
applicationId:
|
||||
'<%= config.getString("app.datadogRum.applicationId") %>',
|
||||
site: '<%= config.getOptionalString("app.datadogRum.site") || "datadoghq.com" %>',
|
||||
service: 'backstage',
|
||||
env: '<%= app.datadogRum.env %>',
|
||||
env: '<%= config.getString("app.datadogRum.env") %>',
|
||||
sampleRate: 100,
|
||||
trackInteractions: true,
|
||||
});
|
||||
|
||||
@@ -124,8 +124,16 @@ import {
|
||||
EntityTravisCIOverviewCard,
|
||||
isTravisciAvailable,
|
||||
} from '@roadiehq/backstage-plugin-travis-ci';
|
||||
import {
|
||||
isNewRelicDashboardAvailable,
|
||||
EntityNewRelicDashboardContent,
|
||||
EntityNewRelicDashboardCard,
|
||||
} from '@backstage/plugin-newrelic-dashboard';
|
||||
|
||||
import React, { ReactNode, useMemo, useState } from 'react';
|
||||
|
||||
const customEntityFilterKind = ['Component', 'API', 'System'];
|
||||
|
||||
const EntityLayoutWrapper = (props: { children?: ReactNode }) => {
|
||||
const [badgesDialogOpen, setBadgesDialogOpen] = useState(false);
|
||||
|
||||
@@ -289,6 +297,14 @@ const overviewContent = (
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isNewRelicDashboardAvailable}>
|
||||
<Grid item md={6} xs={12}>
|
||||
<EntityNewRelicDashboardCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
<Grid item md={4} xs={12}>
|
||||
<EntityLinksCard />
|
||||
</Grid>
|
||||
@@ -369,6 +385,14 @@ const serviceEntityPage = (
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route
|
||||
if={isNewRelicDashboardAvailable}
|
||||
path="/newrelic-dashboard"
|
||||
title="New Relic Dashboard"
|
||||
>
|
||||
<EntityNewRelicDashboardContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
|
||||
<EntityKubernetesContent />
|
||||
</EntityLayout.Route>
|
||||
@@ -427,6 +451,13 @@ const websiteEntityPage = (
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent />
|
||||
</EntityLayout.Route>
|
||||
<EntityLayout.Route
|
||||
if={isNewRelicDashboardAvailable}
|
||||
path="/newrelic-dashboard"
|
||||
title="New Relic Dashboard"
|
||||
>
|
||||
<EntityNewRelicDashboardContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route path="/kubernetes" title="Kubernetes">
|
||||
<EntityKubernetesContent />
|
||||
@@ -523,7 +554,10 @@ const userPage = (
|
||||
<EntityUserProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
<EntityOwnershipCard
|
||||
variant="gridItem"
|
||||
entityFilterKind={customEntityFilterKind}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</EntityLayout.Route>
|
||||
@@ -539,7 +573,10 @@ const groupPage = (
|
||||
<EntityGroupProfileCard variant="gridItem" />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<EntityOwnershipCard variant="gridItem" />
|
||||
<EntityOwnershipCard
|
||||
variant="gridItem"
|
||||
entityFilterKind={customEntityFilterKind}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<EntityMembersListCard />
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.9.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fe24bc9a32: Each plugin now saves to a separate sqlite database file when `connection.filename` is provided in the sqlite config.
|
||||
Any existing sqlite database files will be ignored.
|
||||
|
||||
## 0.9.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -21,6 +21,7 @@ import { GitLabIntegration } from '@backstage/integration';
|
||||
import { isChildPath } from '@backstage/cli-common';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { Knex } from 'knex';
|
||||
import { LoadConfigOptionsRemote } from '@backstage/config-loader';
|
||||
import { Logger as Logger_2 } from 'winston';
|
||||
import { MergeResult } from 'isomorphic-git';
|
||||
import { PushResult } from 'isomorphic-git';
|
||||
@@ -338,6 +339,7 @@ export function isDatabaseConflictError(e: unknown): boolean;
|
||||
// @public
|
||||
export function loadBackendConfig(options: {
|
||||
logger: Logger_2;
|
||||
remote?: LoadConfigOptionsRemote;
|
||||
argv: string[];
|
||||
}): Promise<Config>;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.9.13",
|
||||
"version": "0.9.14",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -81,7 +81,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.10.1",
|
||||
"@backstage/cli": "^0.10.2",
|
||||
"@backstage/test-utils": "^0.1.24",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
@@ -94,7 +94,7 @@
|
||||
"@types/recursive-readdir": "^2.2.0",
|
||||
"@types/stoppable": "^1.1.0",
|
||||
"@types/supertest": "^2.0.8",
|
||||
"@types/tar": "^4.0.3",
|
||||
"@types/tar": "^6.1.1",
|
||||
"@types/unzipper": "^0.10.3",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"aws-sdk-mock": "^5.2.1",
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
loadConfig,
|
||||
ConfigSchema,
|
||||
ConfigTarget,
|
||||
LoadConfigOptionsRemote,
|
||||
} from '@backstage/config-loader';
|
||||
import { AppConfig, Config, ConfigReader } from '@backstage/config';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
@@ -178,6 +179,7 @@ let currentCancelFunc: () => void;
|
||||
export async function loadBackendConfig(options: {
|
||||
logger: Logger;
|
||||
// process.argv or any other overrides
|
||||
remote?: LoadConfigOptionsRemote;
|
||||
argv: string[];
|
||||
}): Promise<Config> {
|
||||
const args = parseArgs(options.argv);
|
||||
@@ -202,8 +204,8 @@ export async function loadBackendConfig(options: {
|
||||
const config = new ObservableConfigProxy(options.logger);
|
||||
const { appConfigs } = await loadConfig({
|
||||
configRoot: paths.targetRoot,
|
||||
configPaths: [],
|
||||
configTargets: configTargets,
|
||||
remote: options.remote,
|
||||
watch: {
|
||||
onChange(newConfigs) {
|
||||
options.logger.info(
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { omit } from 'lodash';
|
||||
import path from 'path';
|
||||
import {
|
||||
createDatabaseClient,
|
||||
ensureDatabaseExists,
|
||||
@@ -170,28 +171,6 @@ describe('DatabaseManager', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('uses top level sqlite database filename if plugin config is not present', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: 'some-file-path',
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await testManager.forPlugin('pluginwithoutconfig').getClient();
|
||||
const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1);
|
||||
const [_, overrides] = mockCalls[0];
|
||||
|
||||
expect(overrides).toHaveProperty(
|
||||
'connection.filename',
|
||||
expect.stringContaining('some-file-path'),
|
||||
);
|
||||
});
|
||||
|
||||
it('provides an inmemory sqlite database if top level is also inmemory and plugin config is not present', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
@@ -214,6 +193,110 @@ describe('DatabaseManager', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if top level sqlite filename is provided', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: 'some-file-path',
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(
|
||||
testManager.forPlugin('pluginwithoutconfig').getClient(),
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
|
||||
it('creates plugin-specific sqlite files when plugin config is not present', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
directory: 'sqlite-files',
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await testManager.forPlugin('pluginwithoutconfig').getClient();
|
||||
const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1);
|
||||
const [_, overrides] = mockCalls[0];
|
||||
|
||||
expect(overrides).toHaveProperty(
|
||||
'connection.filename',
|
||||
path.join('sqlite-files', 'pluginwithoutconfig.sqlite'),
|
||||
);
|
||||
});
|
||||
|
||||
it('uses sqlite directory from top level config and filename from plugin config', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
directory: 'sqlite-files',
|
||||
},
|
||||
plugin: {
|
||||
test: {
|
||||
connection: {
|
||||
filename: 'other.sqlite',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await testManager.forPlugin('test').getClient();
|
||||
const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1);
|
||||
const [_, overrides] = mockCalls[0];
|
||||
|
||||
expect(overrides).toHaveProperty(
|
||||
'connection.filename',
|
||||
path.join('sqlite-files', 'other.sqlite'),
|
||||
);
|
||||
});
|
||||
|
||||
it('uses sqlite directory and filename from plugin config', async () => {
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
directory: 'sqlite-files',
|
||||
},
|
||||
plugin: {
|
||||
test: {
|
||||
connection: {
|
||||
directory: 'custom-sqlite-files',
|
||||
filename: 'other.sqlite',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await testManager.forPlugin('test').getClient();
|
||||
const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1);
|
||||
const [_, overrides] = mockCalls[0];
|
||||
|
||||
expect(overrides).toHaveProperty(
|
||||
'connection.filename',
|
||||
path.join('custom-sqlite-files', 'other.sqlite'),
|
||||
);
|
||||
});
|
||||
|
||||
it('connects to a plugin database using a specific database name', async () => {
|
||||
// testdbname.connection.database is set in config
|
||||
await manager.forPlugin('testdbname').getClient();
|
||||
@@ -282,7 +365,10 @@ describe('DatabaseManager', () => {
|
||||
expect(baseConfig.get().client).toEqual('sqlite3');
|
||||
|
||||
// sqlite3 uses 'filename' instead of 'database'
|
||||
expect(overrides).toHaveProperty('connection.filename');
|
||||
expect(overrides).toHaveProperty(
|
||||
'connection.filename',
|
||||
'plugin_with_different_client',
|
||||
);
|
||||
});
|
||||
|
||||
it('provides database client specific base from plugin connection string when client set under plugin', async () => {
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
normalizeConnection,
|
||||
} from './connection';
|
||||
import { PluginDatabaseManager } from './types';
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Provides a config lookup path for a plugin's config block.
|
||||
@@ -114,10 +115,18 @@ export class DatabaseManager {
|
||||
const connection = this.getConnectionConfig(pluginId);
|
||||
|
||||
if (this.getClientType(pluginId).client === 'sqlite3') {
|
||||
// sqlite database name should fallback to ':memory:' as a special case
|
||||
return (
|
||||
(connection as Knex.Sqlite3ConnectionConfig)?.filename ?? ':memory:'
|
||||
);
|
||||
const sqliteFilename: string | undefined = (
|
||||
connection as Knex.Sqlite3ConnectionConfig
|
||||
).filename;
|
||||
|
||||
if (sqliteFilename === ':memory:') {
|
||||
return sqliteFilename;
|
||||
}
|
||||
|
||||
const sqliteDirectory =
|
||||
(connection as { directory?: string }).directory ?? '.';
|
||||
|
||||
return path.join(sqliteDirectory, sqliteFilename ?? `${pluginId}.sqlite`);
|
||||
}
|
||||
|
||||
const databaseName = (connection as Knex.ConnectionConfig)?.database;
|
||||
@@ -205,6 +214,17 @@ export class DatabaseManager {
|
||||
this.config.get('connection'),
|
||||
this.config.getString('client'),
|
||||
);
|
||||
|
||||
if (
|
||||
client === 'sqlite3' &&
|
||||
'filename' in baseConnection &&
|
||||
baseConnection.filename !== ':memory:'
|
||||
) {
|
||||
throw new Error(
|
||||
'`connection.filename` is not supported for the base sqlite connection. Prefer `connection.directory` or provide a filename for the plugin connection instead.',
|
||||
);
|
||||
}
|
||||
|
||||
// Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The
|
||||
// `database` property from the base connection is omitted unless `pluginDivisionMode`
|
||||
// is set to `schema`. SQLite3's `filename` property is an exception as this is used as a
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user